欢迎关注
最酷最in的云资讯

performSelector:和NSInvocation

这两天做一个优化需求,需要在pod库a里面调用另外一个pod库b中的方法。有两种做法来实现,第一种是在pod的spec中添加dependency,这样pod install的时候,会保证pod库b一定会安装。因为a,b库分别由两个团队维护,切版本号更新同步会引起一些问题,所以决定使用另一种方法,利用消息分发来实现这个需求。

performSelector:

首先想到的自然是performSelector:,看了下系统方法有这个两个:

performSelector:withObject:performSelector:withObject:withObject:

这么看是不是有点太简陋了?

官方文档里有提到,接收者一般是不管理内存的,那么当performSelector:调用的类的构造方法如copy,init等,由于该方法是运行时处理,所以编译时Xcode并不能成功提示内存问题,官方也推荐用NSInvocation来处理。

记得之前面试有人问过,消息分发用什么,我就说performSelector,然后人家问多个传参怎么用,我就说后面的object穿数组或者字典啊,后来想想估计面试人的内心也是哔了狗…

另外插一句,如果用performSelector:,必须搭配respondsToSelector:使用,防止闪退。

NSInvocation

好了闲话不多说,NSInvocation还是很好用的:

NSString *className = @"name";NSString *selectorName = "selectorname";id object = @"参数";Class class = NSClassFromString(className);if (class) {if ([class respondsToSelector:@selector(selectorName)]) {SEL selector = NSSelectorFromString(selectorName);if ([shareObject respondsToSelector:selector]) {NSMethodSignature *signature = [shareObject methodSignatureForSelector:selector];NSInvocation* invocation = [NSInvocation invocationWithMethodSignature:signature];[invocation setTarget:shareObject];[invocation setSelector:selector];[invocation setArgument:&object atIndex:2];//添加更多参数...[invocation invoke];}}}

如果要获得方法的回调,很多文章都这么写:

id returnValue;[invocation invoke];[invocation getReturnValue:&returnValue];

但其实这么写是有问题的,官方文档也有写

This class does not retain the arguments for the contained invocation by default. If those objects might disappear between the time you create your instance of NSInvocation and the time you use it, you should explicitly retain the objects yourself or invoke the retainArguments method to have the invocation object retain them itself.

如果直接使用returnValue,极有可能因为没有人持有他,造成野指针。
解决方法有很多:
给returnValue的类型添加:

__unsafe_unretained__weak__autoreleasing

或者使用C语言的指针:

void *temp = NULL;[invocation invoke];[invocation getReturnValue:&temp];NSArray *resultSet = (__bridge NSArray*)temp;

或者

void * temp = (void *)malloc(signature.methodReturnLength);[invocation getReturnValue:temp];result = *((NSInteger*) temp);free(temp);

这样就不会有野指针的问题了啊…

赞(0) 打赏
未经允许不得转载:云微资讯 » performSelector:和NSInvocation
分享到: 更多 (0)

云微资讯 科技新媒体资讯平台

关于我们联系我们

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏