NSInvocation
最后更新于
最后更新于
当前环境: Xcode10.0 Swift4.2 iOS SDK 12.1
Demo: https://github.com/zColdWater/NSInvocationDemo
NSInvocation 对象用于在对象之间和应用程序之间存储和转发消息,主要是通过 NSTimer 对象和分布式对象系统。一个 NSInvocation 对象包含一个 Objective-C 消息的所有元素:一个目标,一个选择器,参数和返回值。可以直接设置这些元素中的每一个,并在 NSInvocation 调度对象时自动设置返回值。 一个 NSInvocation 对象可以被反复派遣到不同的目标; 它的参数可以在发送之间修改以获得不同的结果; 甚至它的选择器也可以使用相同的方法签名(参数和返回类型)更改为另一个。这种灵活性 NSInvocation 有助于重复具有许多参数和变体的消息; 而不是为每条消息重新输入略有不同的表达式
默认情况下,此类不保留包含的调用的参数。如果这些对象可能在您创建实例 NSInvocation 的时间和使用它的时间之间消失,那么您应该自己显式保留对象或调用方法以使调用对象自己保留它们。retainArguments
这里我上一段 Demo,或许你也可以在上面 Demo 的地址里面找到答案。
为了看下效果,我故意给 foo 函数包含 2 个参数,一个返回值。
通过类名,创建类对象并且调用其内部方法。该如何实现呢?
创建 demo 类 FooObject
FooObject.h 文件
FooObject.m 文件
在外部通过类名调用 FooObject
对象
这里有个插曲 再动态拿这个函数的返回结果的时候 Crash 了,经过 Google 找到了解决办法,下面给了答案地址和解释。
```ObjectiveC
// Invoke method id expectInstance = [self dynamicCreateInstance]; SEL sayhello = NSSelectorFromString(@"sayHello"); [expectInstance performSelector:sayhello withObject:nil];
(id)dynamicCreateInstance {
id fooClass = [NSClassFromString(@"FooObject") alloc]; SEL fooInitSel = NSSelectorFromString(@"initWithWebView:"); NSMethodSignature fooSign = [fooClass methodSignatureForSelector:fooInitSel]; NSInvocation fooInvocation = [NSInvocation invocationWithMethodSignature:fooSign]; fooInvocation.selector = fooInitSel; UIView *webview = [[UIView alloc] init]; [fooInvocation setArgument:&webview atIndex:2]; [fooInvocation invokeWithTarget:fooClass];
// prevent crash // stackoverflow: https://stackoverflow.com/questions/22018272/nsinvocation-returns-value-but-makes-app-crash-with-exc-bad-access id __unsafe_unretained tempResultSet; [fooInvocation getReturnValue:&tempResultSet]; id resultSet = tempResultSet;
// id fooResult = nil; // [fooInvocation getReturnValue:&fooResult]; // NSLog(@"FooObject 对象实例:%@",fooResult);
return resultSet; }
```
本文参考: https://developer.apple.com/documentation/foundation/nsinvocation?language=objc https://stackoverflow.com/questions/5608476/whats-the-difference-between-a-method-and-a-selector