使用performSelector或者NSInvocation调用方法

有时候,写程序的时候会用到自己以前写的东西,但某些接口是不对外开放的,只有我自己知道。这个时候,可以使用如下方法来调用那些实际存在但被藏起来的方法。

objc_msgSend

根据objective-c的运行时特性,向某个对象或对象的实例发送消息,最终调用的其实是objc_msgSend。

objc_msgSend(receiver, selector, arg1, arg2, …);

第一个参数为方法的接收对象,第二个参数为SEL,后面是方法需要的参数。

performSelector

最多带两个参数,且参数为object,不能是int之类的基础类型

新建一个工程,在ViewController.m里面定义一些方法


- (void)function0
{
    NSLog(@"no par");
}

- (void)function1:(NSString *)first
{
    NSLog(@"one par,=%@",first);
}

- (void)function2:(NSString *)first second:(NSString *)second
{
    NSLog(@"two par,first =%@,second=%@",first,second);
}


- (void)function3:(NSString *)first second:(NSString *)second third:(int)third
{
    NSLog(@"third par,first =%@,second=%@,third=%d",first,second,third);
}

对于function0,function1, function2可以使用performSelector调用

[self performSelector:@selector(function0) withObject:nil];
[self performSelector:@selector(function1:) withObject:@"aaaa"];
[self performSelector:@selector(function2:second:) withObject:@"xxxx" withObject:@"yyyy"];

打印出的东西如下:

pic

但对于function3来说,超过2个参数,如果使用performSelector:withObject:withObject:withObject的方式,xcode会直接提示错误,编译就不能通过。

这个时候只能用到NSInvocation

NSInvocation

如果是实例方法,那么可以使用如下代码

	SEL mySelector = @selector(function3:second:third:);
    id target = self;
    NSMethodSignature* signature1 = [self methodSignatureForSelector:mySelector];
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature1];
    

    [invocation setTarget:target];
    [invocation setSelector:mySelector];
    NSString * f = @"mmmm";
    NSString * s = @"nnnn";
    int i = 100;
    [invocation setArgument:&f atIndex:2];
    [invocation setArgument:&s atIndex:3];
    [invocation setArgument:&i atIndex:4];
    [invocation invoke];

如果是类方法,那么方法签名应该是类签名

	NSMethodSignature* signature1 = [[self class] methodSignatureForSelector:mySelector];
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature1];
    

要获取返回值

performSelector并没有获取返回值的功能。如果你需要某个方法的返回值,那么只能使用NSInvocation。

假如说使用上方介绍的NSInvocation,那么要获得返回值,应该这样做。

//假如说有个NSString类型的返回值
…………
…………
NSString * result;
[invocation getReturnValue:&result];
[invocation invoke];

参考

1.
http://www.apblog.cn/blog/2013/09/09/object-c-zhong-shi-yong-nsinvocation-zai-runtime-shi-diao-yong-fang-fa-chuan-ru-duo-ge-can-shu/

2.http://stackoverflow.com/questions/2716143/sel-performselector-and-arguments

3.http://mobile.9sssd.com/ios/art/915

4.2.http://stackoverflow.com/questions/8439052/ios-how-to-implement-a-performselector-with-multiple-arguments-and-with-afterd

Show Comments