深入研究Runtime(1) - 前言
Christi8914
9年前
<p>首先我们先看看文档如何描述Runtime的,如下:</p> <blockquote> <p>The Objective-C language defers as many decisions as it can from compile time and link time to runtime. Whenever possible, it does things dynamically. This means that the language requires not just a compiler, but also a runtime system to execute the compiled code. The runtime system acts as a kind of operating system for the Objective-C language; it’s what makes the language work.</p> </blockquote> <p>大概的意思就是:OC语言尽可能的<code>动态地</code>处理事情,将决定尽可能地从<code>编译时</code>和<code>链接时</code>推迟到<code>运行时</code>。意味着,OC语言不仅仅需要一个编译器,还需要一个<code>运行时系统</code>执行已经编译好的代码。</p> <p>下面将从两个方面学习Runtime:</p> <ol> <li>OC 运行时系统是如何工作的?</li> <li>如何使用运行时系统?</li> </ol> <p><strong><em>补充:</em></strong><br> 其实发展到现在,Runtime技术已经发展了两个版本,一个OC2.0以后的<code>modern</code>版本,和之前<code>legacy</code>版本。<br> 这两个版本的主要区别是:</p> <ol> <li>类中实例变量的排序改变后,是否需要<strong>重新编译</strong>该类的子类,在<code>legacy</code>版本是必须的,而<code>modern</code>则不必须。</li> <li><code>modern</code>版本支持@property属性</li> </ol> <p><strong><em>支持的平台:</em></strong><br> <code>modern</code>:iPhone系统 && 64-bit OS X v10.5后的系统<br> <code>legacy</code>:32bit OS X 系统</p> <p>与运行时系统交互的的方式( 详细的交互在后面章节再说明 )</p> <p>分为三个不同的层次:</p> <ol> <li>Objective-C 源码</li> <li>NSObject 的方法</li> <li>直接调用 runtime 函数</li> </ol> <p>Objective-C 源码</p> <p>当编译器编译OC的类和方法时,会生成<code>数据结构</code>和<code>函数调用</code>实现语言的动态特性。</p> <ul> <li> <p><code>数据结构</code>在哪里获取到信息?</p> <ol> <li>类和分类定义 / 协议声明</li> <li>类对象和协议对象</li> <li>方法选择器( method selector )</li> <li>实例变量模板</li> <li>源码提取到的其它信息</li> </ol> </li> <li> <p><code>函数调用</code>:</p> <ol> <li>最主要的运行时函数就是发送消息,由源码的消息表达式调用。例如:[dog run]这个表达式会调用运行时的<code>发送消息函数</code></li> </ol> </li> </ul> <p>NSObject 的方法</p> <p>其中一些方法可以简单查询运行时系统获取信息。这些方法可以让对象实现<code>自省</code></p> <blockquote> <p>+(Class)class // 获得类对象<br> -(BOOL)isKindOfClass:(Class)aClass // 是否是指定类或者其子类<br> -(BOOL)isMemberOfClass:(Class)aClass // 是否是指定类<br> -(BOOL)respondsToSelector:(SEL)aSelector // 是否实现指定方法或者其父类实现<br> +(BOOL)conformsToProtocol:(Protocol *)aProtocol // 类是否实现了指定协议<br> -(IMP)methodForSelector:(SEL)aSelector // 定位和返回接收者方法实现的地址,所以可以像函数调用一样</p> </blockquote> <p>Cocoa中大多数的类都继承于NSObject( 特例:NSProxy ),所以大多数类都拥有上述<code>自省</code>方法。在NSObject中,大多数方法只是简单地实现,例如:</p> <blockquote> <p>+(NSString *)description // 默认返回类名和地址</p> </blockquote> <p>详细实现功能还需自己重写。</p> <p>直接调用 runtime 函数</p> <p>运行时系统是一个<code>动态共享库</code>,/usr/include/objc 目录下提供了一套<code>函数</code>和<code>数据结构</code>的公共接口。</p> <p><strong><em>补充:</em></strong></p> <ul> <li> <p>什么是selector?<br> 一个对象选择一个方法执行的<code>名称</code>,又或者是源码编译后,取代这个<code>名称</code>的唯一<code>标识</code>。</p> </li> <li> <p>selector的作用:<br> 在OC<code>源码阶段</code>,selector一般当前是方法的唯一标识。而在<code>运行时</code>,selector就作为一个动态<code>函数指针</code>,根据给的方法名指向相对应类中的方法的<code>具体实现</code>。</p> </li> <li> <p><strong>获得一个selector:</strong><br> 编译好的类型是:<code>SEL</code>,有两种途径可以获得</p> <ol> <li><code>编译时</code>,使用<code>@selector</code>指令: <blockquote> <p>SEL aSelector = @selector(methodName);</p> </blockquote> </li> <li><code>运行时</code>,使用<code>NSSelectorFromString</code>函数 <blockquote> <p>SEL aSelector = NSSelectorFromString(@"methodName");</p> </blockquote> </li> </ol> </li> <li> <p><strong>调用selector:</strong><br> 使用performSelector:方法</p> <blockquote> <p>SEL aSelector = @selector(run); // 运行时会自动指向 <em>对应类</em> 的方法实现<br> [aDog performSelector:aSelector];<br> [anAthlete performSelector:aSelector];</p> </blockquote> </li> </ul> <p><strong>为了防止篇章过长,后面内容分篇章记录</strong></p> <p><br> </p> <p>文/老谭是谁(简书作者)<br> 来自:http://www.jianshu.com/p/2cb150a6caba</p>