01 runtime用法之发送消息

作者: 小码码 | 来源:发表于2017-03-24 16:27 被阅读29次

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/message.h>
  • 取消objc_msgSend方法使用的限制
    xcode6以后,苹果不希望我们使用runtime,对objc_msgSend实行了注释,如下:
OBJC_EXPORT void objc_msgSend(void /* id self, SEL op, ... */ )

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


  • 使用举例
    • 举例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用法之发送消息

    1 runtime简介 RunTime简称运行时。OC就是运行时机制,也就是在运行时候的一些机制,其中最主要的是消...

  • Runtime之消息发送

    调用对象的方法,在Objective-C中叫做传递消息,先来看一下C语言中的函数调用方式 C语言中的函数调用方式 ...

  • Runtime --- 消息发送

    上篇内容我们主要了解了objc_msgSend方法的几个参数和objc_class的结构本篇内容我们一起了解 消息...

  • runtime消息发送

    一、runtime简介 RunTime简称运行时。OC就是运行时机制,也就是在运行时候的一些机制,其中最主要的是消...

  • Runtime 消息发送

    1、isa 详解 isa 在 arm64 架构之前就是一个普通的指针,存储着 Class、Meta-Class 对...

  • Runtime消息发送

    对象方法的调用就是向这个对象发送消息 objc_method这个结构体的内容: SEL method_name 方...

  • Runtime — 消息发送

    一、Runtime 1. Runtime介绍 Objective-C 是一门动态语言,而承载整个 OC 动态特性的...

  • Runtime-原理

    runtime初探对象与方法的本质runtime-消息发送runtime-动态方法解析runtime-消息转发 r...

  • RunTime的一些知识点之消息发送

    RunTime的一些知识点之消息发送 了解Runtime首先就要看下他内部是如何实现的可以参考Runtime源码,...

  • runtime objc_msgSend使用

    前言 想要通过runtime发送消息,就必须要掌握runtime如何发送消息,是调用哪个函数?又是如何调用的?本篇...

网友评论

    本文标题:01 runtime用法之发送消息

    本文链接:https://www.haomeiwen.com/subject/hpkfottx.html