01 runtime用法之发送消息

1 runtime简介

  • RunTime简称运行时。OC就是运行时机制,也就是在运行时候的一些机制,其中最主要的是消息机制。
  • 对于C语言,函数的调用在编译的时候会决定调用哪个函数。
    对于OC的函数,属于动态调用过程,在编译的时候并不能决定真正调用哪个函数,只有在真正运行的时候才会根据函数的名称找到对应的函数来调用。
  • 事实证明:
    在编译阶段,OC可以调用任何函数,即使这个函数并未实现,只要声明过就不会报错。
    在编译阶段,C语言调用未实现的函数就会报错。

2 消息机制验证

  • 2.1 在xcode中创建一个Command Line(命令行)工程,在main.m文件中写上以下两句代码:
int main(int argc, const char * argv[]) {
    @autoreleasepool {
      // 创建并初始化一个object对象
        NSObject *object= [NSObject alloc];
        object = [object init];
    }
    return 0;
}
  • 2.2 OC代码转换成C++格式
  • cd /Users/Desktop/Clang 进入到main.m所在的文件夹
  • clang -rewrite-objc main.m 执行此命令,将oc转化成C++
    此时文件夹中多了一个main.cpp文件
  • 打开main.cpp,发现main.m文件转化成了10多万行C++代码,以下是被转换后的main函数中的代码:
int main(int argc, const char * argv[]) {
    /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; 
        NSObject *object= ((NSObject *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("NSObject"), sel_registerName("alloc"));
        object = ((NSObject *(*)(id, SEL))(void *)objc_msgSend)((id)object, sel_registerName("init"));
    }
    return 0;
}
 alloc对应的函数 :  objc_msgSend(objc_getClass("NSObject"), sel_registerName("alloc"));
 init对应的函数:  objc_msgSend(object, sel_registerName("init"));
// 第一个参数:谁发送消息,类名
// 第二个参数:发送一个什么样的消息,方法名

3 objc_msgSend方法的使用

  • 导入头文件#import
  • 取消objc_msgSend方法使用的限制
    xcode6以后,苹果不希望我们使用runtime,对objc_msgSend实行了注释,如下:
OBJC_EXPORT void objc_msgSend(void /* id self, SEL op, ... */ )

要想使用runtime方法,需要进行如下配置:


01 runtime用法之发送消息_第1张图片
  • 使用举例
    • 举例1:
// OC写法:
NSObject *objc = [NSObject alloc];
objc = [objc init];
// 纯runtime写法
NSObject *objc = objc_msgSend(objc_getClass("NSObject"), sel_registerName("alloc"));
objc = objc_msgSend(objc, sel_registerName("init"));
// runtime与OC的混合写法
NSObject *objc = objc_msgSend([NSObject class]), @selector(alloc));
objc = objc_msgSend(objc, @selector(init));
备注:
    // 谁的事情谁开头 -> 对象(objc)
    // objc_getClass(<#const char *name#>):根据类名获取类对象
    // 类方法用类对象,对象方法用对象
  • 举例2:
(1)场景:创建一个person类,并实现两个私有方法(没有声明的方法):
- (void)eat{  
    NSLog(@"吃东西");
}

- (void)run:(NSString *)name metre:(int)metre
{
    NSLog(@"%@跑了%d米", name ,metre);
}

(2)实现过程代码
    // 分配内存
    Person *p = objc_msgSend([Person class], @selector(alloc)); 
    // 初始化
    p = objc_msgSend(p, @selector(init));
    // 调用eat方法(没有参数)
    objc_msgSend(p, @selector(eat)); 
    // 调用run方法(有参数)
    objc_msgSend(p, @selector(run:metre:),@"小明", 100);

4 消息机制使用场景

  • 1.封装自己框架,尽量少的暴露接口,装逼用
  • 2.调用私有的方法,前提:知道已经实现,只是没有声明暴露出来

你可能感兴趣的:(01 runtime用法之发送消息)