Skip to content
This repository has been archived by the owner on Dec 5, 2019. It is now read-only.

Commit

Permalink
Merge remote-tracking branch 'origin/PROViewModelParentAndRootPropert…
Browse files Browse the repository at this point in the history
…ies'
  • Loading branch information
jspahrsummers committed Apr 10, 2012
2 parents f2a7131 + ddab5f2 commit b04de8e
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 4 deletions.
22 changes: 21 additions & 1 deletion Proton/PROViewModel.h
Expand Up @@ -96,6 +96,26 @@ typedef enum {
*/
@property (nonatomic, strong) id model;

/**
* Parent View Models
*/

/**
* The immediate parent view model of the receiver. Returns `nil` if the
* receiver is the <rootViewModel> for its hierarchy.
*
* This property is `nil` by default.
*/
@property (nonatomic, weak) PROViewModel *parentViewModel;

/**
* The root view model of the receiver.
*
* Returns the <[PROViewModel rootViewModel]> of the receiver's <parentViewModel>
* or the receiver if it has no parent.
*/
@property (nonatomic, weak, readonly) PROViewModel *rootViewModel;

/**
* @name Declared Properties
*/
Expand Down Expand Up @@ -135,7 +155,7 @@ typedef enum {
/**
* Returns whether the given action selector can be validly invoked, given the
* current state of the receiver.
*
*
* The default implementation of this method looks for a method named
* `-validate<Action>` on the receiver, invoking it and using its result if
* present. Subclasses that override this method to perform custom logic should
Expand Down
12 changes: 10 additions & 2 deletions Proton/PROViewModel.m
Expand Up @@ -41,6 +41,7 @@ @implementation PROViewModel
@synthesize model = m_model;
@synthesize observationInfo = m_observationInfo;
@synthesize initializingFromArchive = m_initializingFromArchive;
@synthesize parentViewModel = m_parentViewModel;

- (void)setModel:(id)model {
if (model == m_model)
Expand All @@ -52,6 +53,13 @@ - (void)setModel:(id)model {
m_model = model;
}

- (PROViewModel *)rootViewModel {
if (!self.parentViewModel)
return self;

return self.parentViewModel.rootViewModel;
}

#pragma mark - Lifecycle

- (id)init; {
Expand Down Expand Up @@ -196,15 +204,15 @@ - (id)initWithCoder:(NSCoder *)coder {

[self.class enumeratePropertiesUsingBlock:^(objc_property_t property, NSString *key){
id value = [coder decodeObjectForKey:key];

if (!value) {
PROAssert([self.class encodingBehaviorForKey:key] != PROViewModelEncodingBehaviorUnconditional, @"Key \"%@\" of %@ should have been unconditionally encoded, but is not present in the archive", key, self.class);
return;
}

if ([value isEqual:[NSNull null]])
value = nil;

[self setValue:value forKey:key];
}];

Expand Down
27 changes: 26 additions & 1 deletion ProtonTests/PROViewModelTests.m
Expand Up @@ -77,6 +77,8 @@ - (BOOL)validateSomeAction;
expect(viewModel.date).toBeNil();
expect(viewModel.enabled).toBeFalsy();
expect(viewModel.initializingFromArchive).toBeFalsy();
expect(viewModel.parentViewModel).toBeNil();
expect(viewModel.rootViewModel).toEqual(viewModel);
});

describe(@"with an instance", ^{
Expand Down Expand Up @@ -105,6 +107,29 @@ - (BOOL)validateSomeAction;
expect(viewModel).not.toEqual(otherViewModel);
});

describe(@"with parent view models", ^{
__block PROViewModel *parentViewModel;

before(^{
parentViewModel = [[PROViewModel alloc] init];
expect(parentViewModel).not.toBeNil();

viewModel.parentViewModel = parentViewModel;
expect(viewModel.parentViewModel).toEqual(parentViewModel);
});

it(@"returns its parentViewModel as its rootViewModel when its parentViewModel has no ancestors", ^{
expect(viewModel.rootViewModel).toEqual(parentViewModel);
});

it(@"returns its ancestor parentViewModel as its rootViewModel", ^{
PROViewModel *grandParentViewModel = [[PROViewModel alloc] init];
parentViewModel.parentViewModel = grandParentViewModel;

expect(viewModel.rootViewModel).toEqual(grandParentViewModel);
});
});

describe(@"archiving behavior", ^{
__block id unretainedObject = nil;

Expand Down Expand Up @@ -140,7 +165,7 @@ - (BOOL)validateSomeAction;

NSMutableData *encoded = [NSMutableData data];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:encoded];

[archiver encodeObject:unretainedObject forKey:@"unretainedObject"];
[archiver encodeObject:viewModel forKey:@"viewModel"];

Expand Down

0 comments on commit b04de8e

Please sign in to comment.