Objective-C Runtime

来源:互联网 发布:实时量角器软件 编辑:程序博客网 时间:2024/06/05 04:53

Objective-C是一门动态语言,它可以在运行时添加方法,删除方法、消息转发、变换方法实现等。Objective-C具有相当多的动态特性,如动态类型(Dynamic typing),动态绑定(Dynamic binding)和动态加载(Dynamic loading),底层也提供了相当丰富的运行时的特性,即提供基于C和汇编写的Runtime库。

一、类与对象基础数据结构

在Runtime库,类和对象都是由C语言中的结构体表示,方法则用C函数来实现。

(一)对象id

 id可以用来表示任意一个对象,它是一个 objc_object 结构类型的指针, 它只有一个成员即objc_class 结构类型的指针isa, 指向该对象所属的类。objc_object是表示一个类的实例的结构体,它的定义如下:

struct objc_object {    Class isa  OBJC_ISA_AVAILABILITY;}; typedef struct objc_object *id;

备注:id,NSObject,id<NSObject>的区别:id类型是运行时的动态类型,编译器无法知道它的真实类型,可以发送任何信息给id类型的对象,本质是指向任意对象的指针。而Objective-C并不是所有的Cocoa对象都继承NSObject,比如NSProxy就不从NSObject继承,所以NSObejct *指向的对象是id指向对象的子集。

NSObject类属于根类。根类在层级结构中处于最高级,也就是说除此以外没有更高层级。而且Objective-c中还有其他根类,不像Java里只有一个java.lang.Object根类,其他所有的类都直接或间接的继承于它。因此,Java代码可以依据任何对象来实现它的基本方法。Cocoa有多个根类,除了NSObject还有NSProxy等其他等级的根类。

NSObject协议定义了一套所有的根类都可以实现的基础方法,比如包含了hash,isEqual:,description等方法。

(二) 类Class:

Objective-C类是由Class类型来表示的,它实际上是一个指向objc_class结构体的指针。

struct objc_class {    Class isa  OBJC_ISA_AVAILABILITY; #if !__OBJC2__    Class super_class                       OBJC2_UNAVAILABLE;  // 父类    const char *name                        OBJC2_UNAVAILABLE;  // 类名    long version                            OBJC2_UNAVAILABLE;  // 类的版本信息,默认为0    long info                               OBJC2_UNAVAILABLE;  // 类信息,供运行期使用的一些位标识    long instance_size                      OBJC2_UNAVAILABLE;  // 该类的实例变量大小    struct objc_ivar_list *ivars            OBJC2_UNAVAILABLE;  // 该类的成员变量链表    struct objc_method_list **methodLists   OBJC2_UNAVAILABLE;  // 方法定义的链表    struct objc_cache *cache                OBJC2_UNAVAILABLE;  // 方法缓存    struct objc_protocol_list *protocols    OBJC2_UNAVAILABLE;  // 协议链表#endif } OBJC2_UNAVAILABLE;

Class定义中,几个字段是我们感兴趣的:

1.isa:在Objective-C中,所有的类自身也是一个对象,这个对象的Class里面也有一个isa指针,它指向metaClass(元类), Object-C对类对象与实例对象中的 isa 所指向的类结构作了不同的命名:类对象中的 isa 指向类结构被称作 metaclass,metaclass 存储类的static类成员变量与static类成员方法(+开头的方法);实例对象中的 isa 指向类结构称作 class(普通的),class 结构存储类的普通成员变量与普通成员方法(-开头的方法).

2.指向该类的父类,如果该类已经是最顶层的根类(如NSObject或NSProxy),则super_class为NULL。

3.cache:用于缓存最近使用的方法。

二、Runtime库中相关函数

(一)类操作相关的函数

const char * class_getName ( Class cls );// 获取类的类名Class class_getSuperclass ( Class cls );// 获取类的父类 BOOL class_isMetaClass ( Class cls );// 判断给定的Class是否是一个元类size_t class_getInstanceSize ( Class cls );// 获取实例大小Ivar class_getInstanceVariable ( Class cls, const char *name );// 获取类中指定名称实例成员变量的信息 Ivar class_getClassVariable ( Class cls, const char *name );// 获取类成员变量的信息 BOOL class_addIvar ( Class cls, const char *name, size_t size, uint8_t alignment, const char *types );// 添加成员变量 Ivar * class_copyIvarList ( Class cls, unsigned int *outCount );// 获取整个成员变量列表// 添加方法BOOL class_addMethod ( Class cls, SEL name, IMP imp, const char *types ); // 获取实例方法Method class_getInstanceMethod ( Class cls, SEL name ); // 获取类方法Method class_getClassMethod ( Class cls, SEL name ); // 获取所有方法的数组Method * class_copyMethodList ( Class cls, unsigned int *outCount ); // 替代方法的实现IMP class_replaceMethod ( Class cls, SEL name, IMP imp, const char *types ); // 返回方法的具体实现IMP class_getMethodImplementation ( Class cls, SEL name );IMP class_getMethodImplementation_stret ( Class cls, SEL name ); // 类实例是否响应指定的selectorBOOL class_respondsToSelector ( Class cls, SEL sel );

(二)对象操作相关的函数

// 修改类实例的实例变量的值Ivar object_setInstanceVariable ( id obj, const char *name, void *value ); // 获取对象实例变量的值Ivar object_getInstanceVariable ( id obj, const char *name, void **outValue ); // 返回指向给定对象分配的任何额外字节的指针void * object_getIndexedIvars ( id obj ); // 返回对象中实例变量的值id object_getIvar ( id obj, Ivar ivar ); // 设置对象中实例变量的值void object_setIvar ( id obj, Ivar ivar, id value );

三、关联对象(Associated Object)

       Objective-C不支持往已存在的类中添加实例变量,因此不管是系统库提供的提供的类,还是我们自定义的类,都无法运行时动态添加成员变量。(但如果我们通过运行时来创建一个类的话,可以使用class_addIvar函数添加成员变量) Objective-C针对这一问题,提供了一个解决方案:即关联对象(Associated Object)。

通过关联,我们可以把一个对象通过给定的key连接到类的一个实例上,同时指定一个内存管理策略,以告诉Runtime如何管理这个对象的内存,内存管理的策略可以由以下值指定:

OBJC_ASSOCIATION_ASSIGN OBJC_ASSOCIATION_RETAIN_NONATOMIC OBJC_ASSOCIATION_COPY_NONATOMIC OBJC_ASSOCIATION_RETAIN OBJC_ASSOCIATION_COPY 

当宿主对象被释放时,会根据指定的内存管理策略来处理关联对象。如果指定的策略是assign,则宿主释放时,关联对象不会被释放;而如果指定的是retain或者是copy,则宿主释放时,关联对象会被释放。

associative机制提供了三个方法:

OBJC_EXPORT void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)OBJC_EXPORT id objc_getAssociatedObject(id object, const void *key)OBJC_EXPORT void objc_removeAssociatedObjects(id object)

参考文章:

http://blog.devtang.com/blog/2013/10/15/objective-c-object-model/

0 0