Last active
August 29, 2015 14:01
-
-
Save karolkozub/22627a1231613d4755ba to your computer and use it in GitHub Desktop.
A quick follow up on http://macoscope.com/blog/mvc-layer-interaction-architecture/ to clarify ModelManager usage.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Since ModelManager is usually a simple facade for many other smaller managers, it can dispatch most method calls to its subcomponents based on which protocol includes the selector. | |
BOOL ProtocolIncludesSelector (Protocol *protocol, SEL selector) | |
{ | |
struct objc_method_description methodDescription = protocol_getMethodDescription(protocol, selector, YES, YES); | |
return NULL != methodDescription.name; | |
} | |
@implementation ModelManager | |
... | |
- (instancetype)init | |
{ | |
self = [super init]; | |
if (self) { | |
self.dataManager = [[DataManager alloc] initWithUpdatePropagator:self]; | |
self.remoteConnectionManager = [[RemoteConnectionManager alloc] initWithDataManager:self.dataManager]; | |
} | |
return self; | |
} | |
- (id)forwardingTargetForSelector:(SEL)selector | |
{ | |
if (ProtocolIncludesSelector(@protocol(DataManagerOperations), selector)) { | |
return self.dataManager; | |
} else if (ProtocolIncludesSelector(@protocol(RemoteConnectionManagerOperations), selector)) { | |
return self.remoteConnectionManager; | |
} else if (...) { | |
... | |
} else { | |
return nil; | |
} | |
} | |
... | |
@end | |
// The submanagers can then answer any concrete data access requests. | |
@protocol DataManagerOperations <NSObject> | |
- (UIImage *)avatarImageForEmailAddress:(NSString *)emailAddress; | |
... | |
@end | |
@protocol RemoteConnectionManagerOperations <NSObject> | |
- (void)requestAvatarImageForEmailAddress:(NSString *)emailAddress; | |
... | |
@end | |
@implementation DataManager | |
... | |
- (void)saveAvatarImage:(UIImage *)image forEmailAddress:(NSString *)emailAddress | |
{ | |
self.avatarImagesForEmailAddresses[emailAddress] = image; | |
[self.updatePropagator propagateUpdate:[ModelUpdate avatarImageUpdateForEmailAddress:emailAddress]]; | |
} | |
- (UIImage *)avatarImageForEmailAddress:(NSString *)emailAddress | |
{ | |
return self.avatarImagesForEmailAddresses[emailAddress]; | |
} | |
... | |
@end | |
@implementation RemoteConnectionManager | |
... | |
- (void)requestAvatarImageForEmailAddress:(NSString *)emailAddress | |
{ | |
if ([self.dataManager hasAvatarImageForEmailAddress:emailAddress]) { | |
return; | |
} | |
[self sendRemoteAvatarImageRequestForEmailAddress:emailAddress withCompletionBlock:^(UIImage *image) { | |
[self.dataManager saveAvatarImage:image forEmailAddress:emailAddress]; | |
}]; | |
} | |
... | |
@end | |
@implementation SomeViewController | |
... | |
- (void)viewDidLoad | |
{ | |
[super viewDidLoad]; | |
[self setupAvatarView]; | |
[[ModelManager sharedInstance] requestAvatarImageForEmailAddress:self.emailAddress]; | |
} | |
- (void)modelUpdated:(ModelUpdate *)update | |
{ | |
if (update.type == ModelUpdateTypeAvatarImage && [update.emailAddres isEqualToString:self.emailAddress]) { | |
[self setupAvatarView]; | |
} | |
} | |
- (void)setupAvatarView | |
{ | |
self.avatarView.image = [[ModelManager sharedInstance] avatarImageForEmailAddress:self.emailAddress]; | |
} | |
... | |
@end | |
// These examples are very simplified, but hopefully enough to clarify the whole concept. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment