IOS Dev Intro - IOS Runtime

来源:互联网 发布:js confirm 重写 编辑:程序博客网 时间:2024/05/21 17:38


http://blog.qiji.tech/archives/5460

概述

运行时机制是OC的底层机制,算是一个特色吧,跟其他的语言不太一样。
关于这方面,其实我也只是看了一遍而已,肯定会有不少疏漏的地方,请大家务必批评指正。
如果希望深入学习,我推荐阅读“图灵教育”的《精通Objective-C》。

头文件

要学习和利用runtime,首先当然是要知道用哪个头文件啦

概念

其次就是一些概念

消息

调用对象时发送的 选择器名称和一系列参数

实例变量

用一个结构体保存类里的实例变量

选择器(SEL)

例如:insertObject:atIndex: 不带参数和参数的数据类型

方法(IMP)

OC中的类或实例方法,方法声明中包括 名称,输入参数,返回值,和方法签名(即输入参数和返回值的数据类型)

方法签名

即输入参数和返回值的数据类型,方法签名不匹配会导致很多错误!

方法绑定

运行时系统接收 向指定接收器发送的消息 并 寻找和执行适当方法的处理过程。在OC中,这个过程是动态的,称为动态绑定

动态类型

对象的类型可以在运行时才决定,之前可以用 id类型或对象的类型的父类(以及父类的父类等) 声明

内省

检查对象所属的类型

动态绑定

是指在运行时,而不是在编译时讲消息与方法对应起来

动态方法决议

使用动态方法决议能够以动态方式实现方法。
使用@dynamic指令,可以告知编译器与属性关联的方法会以动态方式实现。
翻译的不太顺口,举个例子,CoreData中,写Model的子类时,在实现里声明读取方法,用的就不是@synthesize,而是@dynamic。这表示,系统不会自动创建对应的读取方法,而是去调用这两个方法:

理论

运行时机制

Objective-C拥有与众不同的运行时机制,这个东西的模型大概是:
首先,跟其他语言一样,OC里,实例变量和类方法是分开保存的
每个类的方法分为两部分保存,分别保存实例方法和 类方法(这部分称为“元类”),实例方法能访问实例变量和属性,类方法不行,调用类方法需要用class方法(无论是对于类还是对象,都一样)
在OC里,类也是对象(Class类(跟类)),也有isa指针;NSObject也有isa指针。不过他们指向不一样,NSObject的衍生类,isa指针指向他们归属的类,类的isa指针指向他们的父类(元类也是)
所以,其实每个类中的方法分成好几级,每级又分为两个部分,是分开存放的,调用其中的方法时,从最低级开始,顺着isa指针找就是了,知道这一级包含需要的方法,要是更高的层级中也有这个方法,很不幸,是调不到的,他们就这么被重载了。如果非要调用的话,请使用super指针。
不知道我这么白活(huo四声),看的人能不能看懂,反正我是找不到那张图了。。。

特别的指针

说到指针,有那么几个指针很特别
self,指向当前的对象,也可以说指向当前类,毕竟方法并没有存在对象中,如果当前类中没有对应的方法,向上查找;
super,指向当前的类的父类,如果其中没有,向上查找;
isa指针;
_cmd指针,指向当前方法
this指针,OC里没有,C++和一些别的语言有,指向当前对象,它们没有运行时机制,子类把父类的方法都复制了一份。。。大概吧,我瞎白活的。。。

用法

来点实用的,我分不清哪些算是运行时,哪些不算,反正差不多的都写在这吧,但是也不全,毕竟我懒嘛

内省

消息转发

平时,我们用OC对对象发出的消息,都是在通过消息转发机制调用对象所在的类的方法

消息转发机制通常通过objc_msgSend()函数实现

所以以下两种写法是等效的

但是第一种写法,在我这是会提示错误的,当时我把系统的头文件都改了才勉强实现了一次。大神,是不是我哪里做错了,请务必教我!

有一种说法是OC编译的时候是会先转化成C/C++语言的
例如拉酷里的一篇文章
我还没有去证实

在程序运行的时候修改OC对象(类,对象,方法。。。)

这是运行时机制最主要的用法了
相关的函数很多,主要分为五组,它们的前缀分别是
+ objc_ 创建,注册,销毁类等等,还有一些其它的操作都在这一组
+ ivar_ 获取实例变量的信息
+ property_ 获取属性的信息
+ protocol_ 获取协议的信息
+ method_ 获取方法的信息
+ sel_ 获取选择器的信息
+ imp_ 获取保存方法的实现的位置的结构体的信息
前缀后面的内容说明了函数的作用
例如
+ objc_copy开头的函数可以获取相应的 实例变量/协议/选择器等 的列表
+ objc_add开头的函数可以为一个类增加 实例变量/协议/选择器等
很好理解,就不一一列举了。

限制

  • 运行时不支持对已经存在的类添加 实例变量,属性,方法,除非销毁重建
  • 对类的修改要在创建之后,注册之前进行,注册后的更改是无效的
  • 如果想要更改,只能销毁之前存在的类,重新创建,但是之前创建的这个类的实例也会被销毁
  • 未注册的类之间可以重名,但是不能与注册过的类重名

我试着把一些函数封装成OC对象了,有兴趣的可以看看
运行时的封装类

总结

OC中运行时系统的作用

  • 控制编译过的代码的运行
  • OC这个语言尽可能的将一些决定从编译和链接时推迟到运行时。它会尽可能的动态的处理事情。这意味这个语言不仅需要一个编译器,还需要一个运行时系统去执行编译过的代码。这个运行时系统扮演着对于OC这个语言操作系统的的角色,使得这个语言得以运行。

更多的内容

有些内容似乎也可以算作运行时机制,例如
+ 动态加载,但是苹果似乎不允许在iOS程序中使用
+ 动态方式实现 方法(动态方法决议)
+ 消息转发


0 0
原创粉丝点击