什么是前向调用?该怎么办?为何使用它?

时间:2015-12-23 17:28:43

标签: ios objective-c

我在一个项目中遇到了这个代码,它正在使用// Public interface @interface CCDelegateSplitter : NSObject - (void) addDelegate: (id) delegate; - (void) addDelegates: (NSArray*) delegates; @end // Private interface @interface CCDelegateSplitter () @property(strong) NSMutableSet *delegates; @end @implementation CCDelegateSplitter - (id) init { self = [super init]; _delegates = [NSMutableSet set]; return self; } - (void) addDelegate: (id) delegate { [_delegates addObject:delegate]; } - (void) addDelegates: (NSArray*) delegates { [_delegates addObjectsFromArray:delegates]; } - (void) forwardInvocation: (NSInvocation*) invocation { for (id delegate in _delegates) { [invocation invokeWithTarget:delegate]; } } - (NSMethodSignature*) methodSignatureForSelector: (SEL) selector { NSMethodSignature *our = [super methodSignatureForSelector:selector]; NSMethodSignature *delegated = [(NSObject *)[_delegates anyObject] methodSignatureForSelector:selector]; return our ? our : delegated; } - (BOOL) respondsToSelector: (SEL) selector { return [[_delegates anyObject] respondsToSelector:selector]; } @end 。我想知道它应该做什么,为什么我们需要它。简单的解释将不胜感激。我发布了代码。

{{1}}

2 个答案:

答案 0 :(得分:4)

我假设您知道NSInvocation是什么(如果不是,它是一个包含进行方法调用所需的所有信息的数据结构;想想"块&#34 ;从很久以前就把块添加到语言中了。)

forwardInvocation:是运行时无法找到方法实现的方法之一。因此,如果您将-doSomething消息传递给对象[object doSomething],它将首先检查它是否具有doSomething方法。然后它会检查它的超类。它会尝试动态方法解析(例如resolveInstanceMethod)。它会查找转发目标(forwardingTargetForSelector:),最后,如果其他所有内容都失败,它将创建一个调用(使用methodSignatureForSelector:并向{} {向{ {1}}。默认情况下,forwardInvocation:只调用forwardInvocation:会在iOS上崩溃你(或终止OS X上的当前线程)。但你可以覆盖它来做其他事情(就像他们在这里一样) )。

doesNotRecognizeSelector:是必需的,以便运行时系统可以从消息中创建调用。这个要么从这个对象或它的超类返回一个方法签名,要么它的一个目标要求适当的方法签名。选择器本身并不足以弄清楚如何调用方法。系统需要向对象询问方法的实际工作方式(所需的类型和返回的类型)。

您发布的代码是一个多代表蹦床。它将接受其目标响应的任何选择器(技术上它会选择一个随机目标并查看它是否响应),并且它会将该消息转发给它的所有目标。

对于类似的蹦床和一些关于使用的评论,您可能需要查看RNObserverManager

答案 1 :(得分:3)

看看bfitch评论中的链接。这涵盖 NSInvocation是什么,并暗示为什么你会使用它,但不会详细介绍为什么

NSInvocation允许您执行相当高级的操作,例如创建实际将消息转发到另一个对象的代理对象。使用NSInvocation,可以在运行时获取 ANY 消息并将其转发给另一个对象。

另一个例子是performSelector系列方法。有performSelector:performSelector:withObject:performSelector:withObject:withObject:。 (加上performSelector:withObject:afterDelay:performSelector:onThread:等变体。)这些方法将0,1或2个对象作为参数。如果你需要在另一个带有标量参数的对象上调用一个方法,或者除了0,1或2个对象之外的任何对象,你就不幸了。但是,您可以使用NSInvocation发送包含任何类型参数的消息。

请注意,当将块添加到Objective-C时,对performSelector和NSInvocation等技巧的需求会减少。块可以从其封闭范围引用变量,这使它们更加灵活。