iOS方法调用的几种方式

iOS调用一个方法基本上有四种方式:1)直接对类调用类方法,对象调用对象方法。2)使用performSelector的方式调用。3)使用NSInvocation调用方法。4)使用runtime,ojbc_msgSend调用。

1)直接调用

[self getPropertyList];
[self getIvarList];
[self getInstanceMethodList];
[self getClassMethodList];

2)使用performSelector的方式调用,

performSelector是运行时系统负责去找方法的,在编译时候不做任何校验;如果直接调用编译是会自动校验。如果imageDownloader:didFinishWithImage:image:不存在,那么直接调用在编译时候就能够发现(借助Xcode可以写完就发现),但是使用performSelector的话一定是在运行时候才能发现(此时程序崩溃);Cocoa支持在运行时向某个类添加方法,即方法编译时不存在,但是运行时候存在,这时候必然需要使用performSelector去调用。所以有时候如果使用了performSelector,为了程序的健壮性,会使用检查方法
if ([obj.observer respondsToSelector:obj.selecotr]) {
            [obj.observer performSelector:obj.selecotr withObject:obj];
}

3)使用NSInvocation去调用方法

//创建一个函数签名,这个签名可以是任意的,但需要注意,签名函数的参数数量要和调用的一 致。
SEL myMethod =@selector(privateMethod);
//通过签名初始化
NSMethodSignature* sig = [NSNumber instanceMethodSignatureForSelector:@selector(init)];
NSInvocation* invocatin = [NSInvocation invocationWithMethodSignature:sig];
//设置target
[invocatin setTarget:self];
//设置selecteor
[invocatin setSelector:myMethod];
//消息调用
[invocatin invoke];

注意:1、这里设置参数的Index 需要从2开始,因为前两个被selector和target占用。下面这样写也没有任何问题:2、这里的传参方式必须是传递参数地址。

4)objc_msgSend的写法要复杂一点,具体可以参看这篇文章,讲的很清楚

http://www.jianshu.com/p/efeb33712445

但是有个缺点是,需要指定好传递参数的类型,是不是可以直接都用id呢?

经测试id可用

// objc_msgSend
SEL sel = NSSelectorFromString(@"printWithString:withNum:withArray:");
((void (*) (id, SEL, NSString *, NSNumber *, NSArray *)) objc_msgSend) (self, sel, str, num, arr);

 

posted on 2019-01-16 19:01  sunyaxue  阅读(1306)  评论(0编辑  收藏  举报

导航