From 86d2ab617eec00263af22f7f77d5f71c3c3d5632 Mon Sep 17 00:00:00 2001 From: Garrett Moon Date: Wed, 17 Aug 2016 17:59:28 -0700 Subject: [PATCH] I didn't really understand NSProxy (#2089) * I didn't really understand NSProxy But I think I do now :) Previously I inherited from NSObject because I didn't think I needed anything fancy, but it turns out NSProxy is *less* fancy than NSObject and allows for overriding more methods. This change is probably purely academic in that we don't use this class to forward NSObject specific messages, but I believe this is the 'right thing'. * Update comment, thanks @maicki! --- AsyncDisplayKit/Details/ASWeakProxy.h | 2 +- AsyncDisplayKit/Details/ASWeakProxy.m | 22 +++++++++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/AsyncDisplayKit/Details/ASWeakProxy.h b/AsyncDisplayKit/Details/ASWeakProxy.h index 1891085238..a3c2276b06 100644 --- a/AsyncDisplayKit/Details/ASWeakProxy.h +++ b/AsyncDisplayKit/Details/ASWeakProxy.h @@ -12,7 +12,7 @@ #import -@interface ASWeakProxy : NSObject +@interface ASWeakProxy : NSProxy @property (nonatomic, weak, readonly) id target; diff --git a/AsyncDisplayKit/Details/ASWeakProxy.m b/AsyncDisplayKit/Details/ASWeakProxy.m index 506f274e7a..d26439f178 100644 --- a/AsyncDisplayKit/Details/ASWeakProxy.m +++ b/AsyncDisplayKit/Details/ASWeakProxy.m @@ -16,7 +16,7 @@ - (instancetype)initWithTarget:(id)target { - if (self = [super init]) { + if (self) { _target = target; } return self; @@ -32,4 +32,24 @@ return _target; } +- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector +{ + // Check for a compiled definition for the selector + NSMethodSignature *methodSignature = [[_target class] instanceMethodSignatureForSelector:aSelector]; + + // Unfortunately, in order to get this object to work properly, the use of a method which creates an NSMethodSignature + // from a C string. -methodSignatureForSelector is called when a compiled definition for the selector cannot be found. + // This is the place where we have to create our own dud NSMethodSignature. This is necessary because if this method + // returns nil, a selector not found exception is raised. The string argument to -signatureWithObjCTypes: outlines + // the return type and arguments to the message. To return a dud NSMethodSignature, pretty much any signature will + // suffice. Since the -forwardInvocation call will do nothing if the delegate does not respond to the selector, + // the dud NSMethodSignature simply gets us around the exception. + return methodSignature ?: [NSMethodSignature signatureWithObjCTypes:"@^v^c"]; +} + +- (void)forwardInvocation:(NSInvocation *)invocation +{ + // If we are down here this means _target where nil. Just don't do anything to prevent a crash +} + @end