Created
October 14, 2012 03:54
-
-
Save chakrit/3887222 to your computer and use it in GitHub Desktop.
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
// | |
// ATInterceptor.h | |
// AddressTalk | |
// | |
// Created by Chakrit Wichian on 4/25/12. | |
// Copyright (c) 2012 Oozou Ltd. All rights reserved. | |
// | |
// ---- | |
// | |
// Receives and relays any messages sent to it to the middleman if the | |
// middleman responds to it. Otherwise, the message is forwarded to the target. | |
// Useful for implementing multiple delegate objects for a single source. | |
// | |
// Adapted from: http://stackoverflow.com/a/3862591/3055 | |
// | |
// NOTE: The interceptor itself *must* be retained in order to stay alive. | |
// Usually the middleman should be the one managing the interceptor's lifetime. | |
// This also means that the interceptor should be detached from all message | |
// sources before being de-alloc'ed to prevent messages being sent to | |
// dead instance. | |
// | |
// Also, the interceptor will retain neither the target nor the middleman, | |
// so it is expected that both is already retained by someone else. | |
// | |
@interface ATInterceptor : NSObject | |
@property (nonatomic, assign) id target; | |
@property (nonatomic, assign) id middleMan; | |
+ (id)interceptor; | |
+ (id)interceptorWithTarget:(id)target middleMan:(id)aMiddleMan; | |
- (id)init; | |
- (id)initWithTarget:(id)target middleMan:(id)aMiddleMan; | |
@end |
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
// | |
// ATInterceptor.m | |
// AddressTalk | |
// | |
// Created by Chakrit Wichian on 4/25/12. | |
// Copyright (c) 2012 Oozou Ltd. All rights reserved. | |
// | |
#import "ATInterceptor.h" | |
@implementation ATInterceptor | |
@synthesize target=_target, middleMan=_middleMan; | |
+ (id)interceptor { | |
return [[[ATInterceptor alloc] init] autorelease]; | |
} | |
+ (id)interceptorWithTarget:(id)target middleMan:(id)aMiddleMan { | |
return [[[ATInterceptor alloc] initWithTarget:target middleMan:aMiddleMan] autorelease]; | |
} | |
- (id)init { | |
return [self initWithTarget:nil middleMan:nil]; | |
} | |
- (id)initWithTarget:(id)target middleMan:(id)aMiddleMan { | |
// ensure we're not already intercepting the same target with the same middleman | |
BOOL already = [aMiddleMan isKindOfClass:[ATInterceptor class]]; | |
already = already && ((ATInterceptor *)aMiddleMan).target == target; | |
if (already) | |
return aMiddleMan; | |
// we're safe, normal init | |
if (self = [super init]) { | |
self.target = target; | |
self.middleMan = aMiddleMan; | |
} | |
return self; | |
} | |
#pragma mark - Forwarding mechanism | |
- (id)forwardingTargetForSelector:(SEL)aSelector { | |
if ([_middleMan respondsToSelector:aSelector]) return _middleMan; | |
if ([_target respondsToSelector:aSelector]) return _target; | |
return [super forwardingTargetForSelector:aSelector]; | |
} | |
- (BOOL)respondsToSelector:(SEL)aSelector { | |
if ([_middleMan respondsToSelector:aSelector]) return YES; | |
if ([_target respondsToSelector:aSelector]) return YES; | |
return [super respondsToSelector:aSelector]; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment