解释runtime

一下懵逼的感觉,时时刻刻都在接触runtime但是当问起我们的时候真的就知道怎么回答这个问题。作为一个iOS开发者需要对这个概念有个系统的认识。
我对回答这个问题提出两点建议。

1.不要过早的陷入细节,从最高的层次上来阅读runtime解释出来,有一个大概的认识
在这之间说一下消息机制,message_send()。还有isa指针的指向问题,和方法搜索机制。总结就是消息机制,稍微提一下动态决议。
2.描述自己擅长的层面,体现自己的独特见解。从细节上剖析问题

宏观

runtime,运行时机制是OC的底层实现,OC的幕后支持者。他是一套C语言库:主要包含类/成员变量/方法的API接口。比如获取类里面的所有成员变量,为类动态添加成员变量,动态改变类的方法实现,为类动态添加新的方法等
runtime有啥用?
在OC对象执行一个方法时,[obj dosomething].runtime会在运行时将他转化为objc_msgsend(obj,@selector(dosomething))。转化为就要执行这个函数,运行时会根据obj对象的isa指针找到类,类内有Cache成员,在近期调用过的方法被缓存在这。运行时机制优先在Cache搜查方法dosomething,猜测使用hash实现,根据名字直接找到方法地址。没有的话就在methodLists列表继续寻找,如果有的话就加入cache。再找不到就像superclass继续寻找直至找到NSObject类(他的父类是nil)。这里说NSObject类是有技术支持的。所有对象的父类都是NSObject包括类(类也是对象)。解释下就是,类也有isa指针他指向类的元类。他的方法列表还有Cache都会存储在这个元类,所以执行类方法是和上述对象方法是一样的。既然是元类他也有父类,他的NSObject类前的父类和对象是一样的但是到了NSObject的元类他的父类就指向了NSObject类。所以我说NSObject是所有的父类。既然类是对象,那么元类也是对象那也有他isa,这样递归下去无穷无尽,所以规定元类的isa都指向NSObject的元类。自己的总结就是superclass用来找.这样runtime形成了一个完美的闭环及NSObject的元类superclass指向NSObject而NSObject父类为nil。所有的对象基类都是NSObject,所有的元类都指向NSObject的元类。
clang -rewrite-objc 源代码文件名 重写
消息转发
基础层
1>能动态产生一个类、一个成员变量、一个方法
2>能动态修改一个类、一个成员变量、一个方法
3>能动态删除一个类、一个成员变量、一个方法
4>能获取类的属性、成员变量、方法.都是这样的形式:class_copyIvarList()
提高层
1>绑定两个对象,一个对象成为另一个的“属性”
2>交换两个方法的实现
3>KVC,KVO
实际上我们编写的所有OC代码,最终都是转成了runtime库的东西,比如类转成了runtime库里面的结构体等数据类型,方法转成了runtime库里面的C语言函数,平时调方法都是转成了objc_msgSend函数(所以说OC有个消息发送机制)

需要了解的:以下这些东西都可以通过runtime获取到

    typedef struct objc_class *Class;
    struct objc_class {
        Class isa; // 指向metaclass
        Class super_class ; // 指向其父类
        const char *name ; // 类名
        long version ; // 类的版本信息,初始化默认为0,可以通过runtime函数class_setVersion和class_getVersion进行修改、读取
        long info; // 一些标识信息,如CLS_CLASS (0x1L) 表示该类为普通 class ,其中包含对象方法和成员变量;CLS_META (0x2L) 表示该类为 metaclass,其中包含类方法;
        long instance_size ; // 该类的实例变量大小(包括从父类继承下来的实例变量);
        struct objc_ivar_list *ivars; // 用于存储每个成员变量的地址
        struct objc_method_list **methodLists ; // 与 info 的一些标志位有关,如CLS_CLASS (0x1L),则存储对象方法,如CLS_META (0x2L),则存储类方法;
        struct objc_cache *cache; // 指向最近使用的方法的指针,用于提升效率;
        struct objc_protocol_list *protocols; // 存储该类遵守的协议
    }

细节

1.swizzle交换两个方法名

大家可以参考下这篇文章swizzle黑魔法
有不理解的留言我在细细讲解

2.巧妙运用AssociatedObject,解决代码冗余

参考我的另一篇runtime实用操作-AssociatedObject

3.KVC,KVO

参考KVO实现原理
就是文章有点零散。这个我务必会整理,并尽量写出源码。

认真的讲解下IMP和method的区别和联系:

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

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

Method是runtime内部定义的方法,我们在调用runtime库内函数的时候才会放回Method类型,Class中定义了一个变量objc_method_list链表都是objc_method类型的。我个人理解是库内为了方便操作做得进一步对IMP的封装,出了这个范围就不能用了。

对于IMP:id是一个指向objc_object结构体的指针,该结构体只有一个成员isa,所以任何继承自NSObject的类对象都可以用id来指代,因为NSObject的第一个成员实例就是isa。
IMP是一个函数指针,这个被指向的函数包含一个接收消息的对象id调用方法的选标SEL,以及不定个数的方法参数,并返回一个id。也就是说IMP是消息最终调用的执行代码,是方法真正的实现代码。我们可以像在C语言里面一样使用这个函数指针。
NSObject类中的methodForSelector:方法就是这样一个获取指向方法实现IMP的指针,methodForSelector:返回的指针和赋值的变量类型必须完全一致,包括方法参数类型和返回值类型。

写到这了就在写一下SEL吧

typedef struct objc_selector *SEL;
- (void)helloJianShu:(id)sender{
       ...
}
NSLog(@"SEL = %s",@selector(helloJianShu:)); 
打印结果: SEL = helloJianShu:

可以看出SEL的本质是一个以字符串为核心的结构体;

FOUNDATION_EXPORT NSString *NSStringFromSelector(SEL aSelector);//SEL转字符串
FOUNDATION_EXPORT SEL NSSelectorFromString(NSString *aSelectorName);//字符串转SEL

另外两个隐藏参数self和_cmd.这两个隐藏参数相对的意思是相对于在执行[... ...]方法的时候才有的叫法。实际上他就对应着转换成runtime中的objc_msgSend()中间必须的第一个参数self和第二个参数_cmd。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,324评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,356评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,328评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,147评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,160评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,115评论 1 296
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,025评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,867评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,307评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,528评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,688评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,409评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,001评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,657评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,811评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,685评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,573评论 2 353

推荐阅读更多精彩内容

  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 1,709评论 0 9
  • 这篇文章完全是基于南峰子老师博客的转载 这篇文章完全是基于南峰子老师博客的转载 这篇文章完全是基于南峰子老师博客的...
    西木阅读 30,554评论 33 466
  • 参考链接: http://www.cnblogs.com/ioshe/p/5489086.html 简介 Runt...
    乐乐的简书阅读 2,135评论 0 9
  • 我们常常会听说 Objective-C 是一门动态语言,那么这个「动态」表现在哪呢?我想最主要的表现就是 Obje...
    Ethan_Struggle阅读 2,192评论 0 7
  • 有一种分别,不是摆脱。 而是只能到这里。 挥手再见。 一次次挥手, 一次次转身, 让过去过去, 看脚下延伸。
    心源宝贝阅读 202评论 0 1