Skip to content

Instantly share code, notes, and snippets.

@karolkozub
Last active August 29, 2015 14:01
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save karolkozub/22627a1231613d4755ba to your computer and use it in GitHub Desktop.
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.
// 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