美文网首页
深入浅出Objective-C Runtime

深入浅出Objective-C Runtime

作者: 蓝天白云_Sam | 来源:发表于2018-11-30 18:48 被阅读0次

    从方法调用说起

    OC的方法调用,也叫消息发送.对于OC的方法调用[receiver message];,编译器会转化成以下调用:

    objc_msgSend(receiver, selector);
    

    如果有多个消息参数,如:[receiver message:arg1 arg2:arg2 arg3:arg3 ....];则转化为:

    objc_msgSend(receiver, selector, arg1, arg2, arg3, ...);
    

    我们可以用clang -rewrite-objc命令将OC代码转换成C++代码,具体参考附录1

    什么是runtime?

    OC是一门动态语言,与C++这种静态语言不同,静态语言的各种数据结构在编译期已经决定了,不能够被修改。而动态语言却可以使我们在程序运行期,动态的修改一个类的结构,如修改方法实现,绑定实例变量等。

    OC作为动态语言,它总会想办法将静态语言在编译期决定的事情,推迟到运行期来做。所以,仅有编译器是不够的,它需要一个运行时系统(runtime system),这也就是OC的runtime系统的意义,它是OC运行框架的基石。

    附录

    附录1: clang -rewrite-objc:将OC代码转换成C++代码

    Clang 编译器通过以下命令可以将OC代码转换成C++代码:
    clang -rewrite-objc inputfile
    如以下代码(main.m):
    <font color=red>内容</font>

    @interface Person : NSObject
    @property(nonatomic,strong) NSString * name;
    @end
    
    @implementation Person
    
    -(void) sayHello{
        NSLog(@"@Hello %@",self.name);
    }
    @end
    
    int main(int argc, const char * argv[]) {
        Person * person = [[Person alloc]init];
        person.name = @"Sammy Lan";
        [person sayHello];
        return 0;
    }
    
    

    通过执行-rewrite-objc main.m生成main.cpp文件:

    #ifndef _REWRITER_typedef_Person
    #define _REWRITER_typedef_Person
    typedef struct objc_object Person;
    typedef struct {} _objc_exc_Person;
    #endif
    
    extern "C" unsigned long OBJC_IVAR_$_Person$_name;
    struct Person_IMPL {
        struct NSObject_IMPL NSObject_IVARS;
        NSString *_name;
    };
    
    // @property(nonatomic,strong) NSString * name;
    /* @end */
    
    
    // @implementation Person
    
    
    static void _I_Person_sayHello(Person * self, SEL _cmd) {
        NSLog((NSString *)&__NSConstantStringImpl__var_folders_mv_r6qfhyyn59n3lprfy6qyhjrh0000gn_T_main_b2bce8_mi_0,((NSString *(*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("name")));
    }
    
    static NSString * _I_Person_name(Person * self, SEL _cmd) { return (*(NSString **)((char *)self + OBJC_IVAR_$_Person$_name)); }
    static void _I_Person_setName_(Person * self, SEL _cmd, NSString *name) { (*(NSString **)((char *)self + OBJC_IVAR_$_Person$_name)) = name; }
    // @end
    
    
    int main(int argc, const char * argv[]) {
        Person * person = ((Person *(*)(id, SEL))(void *)objc_msgSend)((id)((Person *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("Person"), sel_registerName("alloc")), sel_registerName("init"));
        ((void (*)(id, SEL, NSString *))(void *)objc_msgSend)((id)person, sel_registerName("setName:"), (NSString *)&__NSConstantStringImpl__var_folders_mv_r6qfhyyn59n3lprfy6qyhjrh0000gn_T_main_b2bce8_mi_1);
        ((void (*)(id, SEL))(void *)objc_msgSend)((id)person, sel_registerName("sayHello"));
        return 0;
    }
    

    相关文章

      网友评论

          本文标题:深入浅出Objective-C Runtime

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