Objective-C Runtime总结

Objective-C Runtime总结

转载原址:http://www.jianshu.com/p/6f3c0319842b

在伯乐在线看了7篇关于Objective-C Runtime的博文,确定很详尽也很深入。但是看起来有点凌乱,不容易懂。我认为Objective-C Runtime主要包括如下几个方便。

1、数据类型,怎样定义id,对象,class,成员,属性,方法,分类,协议等
2、消息执行逻辑,方法查找,方法缓存,动态添加。
3、对象关联。


在http://www.jianshu.com/p/b1a6c51cfe3e里面的7篇文章说得非常全面了,我就换个角度去总结吧。OC class的定义如下图

1、数据类型:


OC 1.0的就不说了,那都是历史了。上面可以看到class定义里面还是有isa的Class。这个到底是什么呢?带着问题,再看看object的定义。

struct objc_object { Class isa; };

object里面也包含了Class,这个Class又是什么呢?一个对象包含一个Class,我觉得很正常,也是可以直接理解为就是创造这个 类对象 的类呗,但是为什么class里面还包含了一个Class呢?这个到底是什么呢?这个类难道又是另外一个类创建的呢?细心的同学,的确会这些疑问。事实上OC里面还有一个隐藏的概念(Meta-class),class里面对应的isa就是该类的Meta-class。我觉得这个是OC很神奇的地方,不过也合理。对象方法和类方法分来加载和存放,的确可以节约内存和提高加载的效率。

怎么证明我说的是对的,不是瞎扯的呢?没错就是就是想办法打印类的地址。

NSLog(@"NSObject's class is %p", [NSObject class]);
NSLog(@"NSObject's class is %p",objc_getClass(class_getName([NSObject class])));
NSLog(@"NSObject's meta class is %p",objc_getMetaClass(class_getName([NSObject class])));

想学习的人,还是自己跑一跑代码吧,加深印象,通过打印的确发现两个地址是不同的。
2016-04-05 10:24:06.538 test[806:67538] NSObject's class is 0x765000
2016-04-05 10:24:06.538 test[806:67538] NSObject's class is 0x765000
2016-04-05 10:24:06.538 test[806:67538] NSObject's meta class is 0x765014

这样就证明的确有两个类。那么怎样知道Meta-class里面是存放类方法呢?没错,就是打印方法表。这个留给爱好者去干吧。最后再上一张经典的图,看不懂的就留言吧。

说完了最基本的类,可以说说其他的了,

id的定义

typedef struct objc_object *id;

成员列表


方法列表



方法的定义

typedef struct objc_method *Method;
struct objc_method 
{
    SEL method_name     OBJC2_UNAVAILABLE;
    char *method_types  OBJC2_UNAVAILABLE;
    IMP method_imp      OBJC2_UNAVAILABLE;
}


成员的定义

typedef struct objc_ivar *Ivar;
struct objc_ivar 
{
<span style="white-space:pre">	</span>char *ivar_name   OBJC2_UNAVAILABLE;
<span style="white-space:pre">	</span>char *ivar_type   OBJC2_UNAVAILABLE;
<span style="white-space:pre">	</span>int ivar_offset   OBJC2_UNAVAILABLE;
<span style="white-space:pre">	</span>#ifdef __LP64__
 <span style="white-space:pre">		</span>int space        OBJC2_UNAVAILABLE;
<span style="white-space:pre">	</span>#endif
}


IMP的定义

typedef id (*IMP)(id, SEL, ...);

cache的定义

typedef struct objc_cache *Cache
struct objc_cache 
{
<span style="white-space:pre">	</span>unsigned int mask
<span style="white-space:pre">	</span>/* total = mask + 1 */
<span style="white-space:pre">	</span>OBJC2_UNAVAILABLE;
<span style="white-space:pre">	</span>unsigned int occupied OBJC2_UNAVAILABLE;
<span style="white-space:pre">	</span>Method buckets[1]     OBJC2_UNAVAILABLE;
};


Category的定义

typedef struct objc_category *Category;
struct objc_category 
{
<span style="white-space:pre">	</span>char *category_name                          OBJC2_UNAVAILABLE; // 分类名
<span style="white-space:pre">	</span>char *class_name                             OBJC2_UNAVAILABLE; // 分类所属的类名
<span style="white-space:pre">	</span>struct objc_method_list *instance_methods    OBJC2_UNAVAILABLE; // 实例方法列表
<span style="white-space:pre">	</span>struct objc_method_list *class_methods       OBJC2_UNAVAILABLE; // 类方法列表
<span style="white-space:pre">	</span>struct objc_protocol_list *protocols         OBJC2_UNAVAILABLE; // 分类所实现的协议列表
}


Protocol的定义

typedef struct objc_object Protocol;


最后我们发现,协议就是一个对象,Category和class很像。我们可以动态创建协议,但是好像没有方法修改Category。

还值得注意的是如下的定义,很有用。

struct objc_super { id receiver; Class superClass; };


2、消息执行逻辑

说到消息,肯定要提到msg_send的,msg_send的原型如下:

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


receiver是一个非常值得关心的东西,例如[self class]和[super class],那他们的receiver到底是谁呢,上面还特意提到了struct objc_super,事实上super的receiver依然是self。

objc_msgSend的执行过程如下,很简单明了。但是这只是正常情况的调用过程。


好吧,我决定再上一张网上找的图,这个图比较全面。


这张图就是比完整了,包括动态调用的流程。这个调用过程没有例子是很难说得清楚的,在这里就不再展开说了,有了这个图,看伯乐在线的博文,也比较容易懂了。有机会的话,我写几个例子玩一玩吧。

3、对象关联

类本身是不支持动态添加成员的,除非你动态创建类的时候添加进去,一旦类注册了就不能再添加了,协议也是如此,一旦发布了,就不能修改了。这样不科学呀,很多时候我们需要动态添加成员,那怎么办呀?于是后来有了对象关联,当然还是可以添加属性的,setValue等

void objc_setAssociatedObject ( id object,constvoid*key, id value, objc_AssociationPolicy policy );
id objc_getAssociatedObject ( id object,constvoid*key );
void objc_removeAssociatedObjects ( id object );


对象关联比较简单,也挺常用的。



文/IamOnelong(简书作者)
原文链接:http://www.jianshu.com/p/6f3c0319842b
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值