Share
Embed
Transcript
20 slides
-
@interface LBDelegateMatrioska () @property (nonatomic, strong) NSPointerArray *mutableDelegates; @end !
! @implementation LBDelegateMatrioska ! - (instancetype)initWithDelegates:(NSArray *)delegates { _mutableDelegates = [NSPointerArray weakObjectsPointerArray]; [delegates enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { [_mutableDelegates addPointer:(void *)obj]; }]; return self; } -
@interface LBRViewController () @property (weak, nonatomic) IBOutlet MKMapView *mapView; @property
(strong, nonatomic) LBDelegateMatrioska *delegateMatrioska; @property (strong, nonatomic) LBClusteredMapViewDelegate *clusteringDelegate; @end ! @implementation LBRViewController ! - (void)viewDidLoad { [super viewDidLoad]; ! self.delegateMatrioska = ({ self.clusteringDelegate = [LBClusteredMapViewDelegate new]; NSArray *delegates = @[self.clusteringDelegate, self]; LBDelegateMatrioska *matrioska = [[LBDelegateMatrioska alloc] initWithDelegates:delegates]; matrioska; }); self.mapView.delegate = (id<MKMapViewDelegate>)self.delegateMatrioska; } -
@implementation LBDelegateMatrioska ! ! #pragma mark - NSObject ! -
(BOOL)respondsToSelector:(SEL)aSelector { id firstResponder = [self p_firstResponderToSelector:aSelector]; return (firstResponder ? YES : NO); } -
@implementation LBDelegateMatrioska ! #pragma mark - NSProxy ! - (void)forwardInvocation:(NSInvocation
*)invocation { for (id delegate in self.mutableDelegates) { if ([delegate respondsToSelector:invocation.selector]) { [invocation invokeWithTarget:delegate]; } } } ! - (NSMethodSignature *)methodSignatureForSelector:(SEL)sel { id firstResponder = [self p_firstResponderToSelector:sel]; if (firstResponder) { return [firstResponder methodSignatureForSelector:sel]; } return nil; } -
#pragma mark - NSProxy ! - (void)forwardInvocation:(NSInvocation *)invocation { //
If the invoked method return void I can safely call all the delegates // otherwise I just invoke it on the first delegate that // respond to the given selector if ([invocation methodReturnTypeIsVoid]) { for (id delegate in self.mutableDelegates) { if ([delegate respondsToSelector:invocation.selector]) { [invocation invokeWithTarget:delegate]; } } } else { id firstResponder = [self p_firstResponderToSelector:invocation.selector]; [invocation invokeWithTarget:firstResponder]; } } -
context(@"when a method is called", ^{ it(@"should be received by
all the delegates that receive the message", ^{ SEL testSelector = @selector(didSelect); #pragma clang diagnostic push #pragma clang diagnostic ignored "-Warc-performSelector-leaks" [[firstObject should] receive:testSelector]; [[secondObject should] receive:testSelector]; [[thirdObject shouldNot] receive:testSelector]; [(id <CannedProtocol>)matrioska performSelector:testSelector]; testSelector = @selector(didDeselect); [[firstObject shouldNot] receive:testSelector]; [[secondObject shouldNot] receive:testSelector]; [[thirdObject should] receive:testSelector]; [(id <CannedProtocol>)matrioska performSelector:testSelector]; #pragma clang diagnostic pop }); }); #import <Kiwi/NSProxy+KiwiVerifierAdditions.h>