博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Runtime机制之结构体及操作函数
阅读量:5048 次
发布时间:2019-06-12

本文共 7490 字,大约阅读时间需要 24 分钟。

一、动态语言

Objective-C语言是一门动态语言,它将很多静态语言在编译和链接时期做的事放到了运行时来处理。这种动态语言的优势在于:具有灵活性,比如:消息转发,方法交换等。它有一个运行时系统Objc Runtime,其实是一个Runtime库,基本上是用C和汇编写的,这个库使得C语言有了面向对象的能力。

1. runtime库主要做下面两件事:

  • 封装:用c语言把对象封装成基本的数据结构,如:类结构体,对象结构体等。这些结构体和函数被runtime函数封装后,我们就可以在程序运行时创建,检查,修改类、对象和它们的方法了。
  • 找出方法的最终执行代码:把消息机制转换为函数的调用。

 

二、基本结构体

1. 类结构体:objc_class

  • isa:指向该类对象所属类(即元类)的指针,根类的元类指向自己
  • super_class:指向父类的指针,根类的父类指针指向NULL
  • name:类名
  • version:版本
  • info:类信息
  • instance_size:改类实例的大小
  • ivars:属性链表
  • methodLists:方法链表
  • cache:方法缓存链表
  • protocols:协议链表

 

typedef struct objc_class *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;

 

2. 实例对象结构体:objc_objective 

  • isa:指向所属类的指针。(仅仅一个指针)

 

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

 

3. 缓存方法链表结构体:objc_cache

  • mask:可缓存方法的数量
  • occupied:已缓存方法的数量
  • buckets:指针数组,存储的是指针,指向已缓存的方法结构体

 

typedef struct objc_cache *cache;struct objc_cache {    unsigned int mask /* total = mask + 1 */                 OBJC2_UNAVAILABLE;    unsigned int occupied                                    OBJC2_UNAVAILABLE;    Method buckets[1]                                        OBJC2_UNAVAILABLE;};

 

4. 元类结构体(类对象所属类)

  • 同类结构体一样,只是元类的isa指针都是指向根类NSObject元类,而根类的元类的isa指针指向自己。

我们都知道,实例对象拥有一个指向所属类的isa指针。那类本身也可以看成是所属类的对象,即类对象那它自然也拥有一个指向所属类的isa指针,这个指针指向的也是该类对象的所属类,即元类。所以,当我们向一个对象发送消息时,runtime会在这个对象所属的这个类的方法列表中查找方法;而向一个类发送消息时,会在这个类的所属类,即元类meta-class的方法列表中查找。

 

5. 举例说明,看看以下代码如何执行的

NSArray *array = [[NSArray alloc] init];

 

  • runtime库向类对象NSArray发送了alloc消息,类对象根据isa指针去所属类,即元类中查找响应的方法
  • 在元类中,先查cache,再查methodLists,由于元类中没有方法alloc,便根据super_class指针去父类NSObjec中找查找
  • 在父类中,同样先查cache,再查methodLists,在methodLists找到,立即响应消息
  • 检测类NSArray中instance_size的大小,根据所需的空间大小分配内存
  • 创建objc_objective结构体以及实例变量,把结构体的isa指针指向父类
  • 把alloc方法缓存到自己的cache链表中
  • runtime库又向刚创建好的实例对象发送init消息,对象根据isa指针去所属类NSArray中查找
  • 先查cache,再查methodLists,查到后则响应
  • 把实例对象中的实例变量初始化
  • 把方法init缓存到cache链表中

 

三、类与对象操作函数

1. 类相关操作函数:以class为前缀命名

  • class_getName                          // 获取类名
  • class_getSuperclass                       // 获取父类
  • class_isMetaClass                          // 判断类是不是元类
  • class_getInstanceSize                    // 获取实例大小
  • class_getInstanceVariable              // 获取实例成员变量
  • class_getClassVariable                   // 获取类成员变量
  • class_addIvar                                // 添加实例变量
  • class_copyIvarList                         // 获取整个成员变量表
  • class_getProperty                         // 获取指定属性
  • class_copyPropertyList                  // 获取整个属性表
  • class_addProperty                         // 添加属性
  • class_replaceProperty                   // 替换属性
  • class_addMethod                         // 添加方法
  • class_getInstanceMethod             // 获取实例方法
  • class_getClassMethod                  // 获取类方法
  • class_copyMethodList                  // 获取所有方法的数组
  • class_replaceMethod                   // 替代方法的实现
  • class_getMethodImplementation  // 返回方法的具体实现
  • class_respondsToSelector            // 类实例是否响应指定的selector
  • class_addProtocol                       // 添加协议
  • class_conformsToProtocol            // 返回类是否实现指定的协议
  • class_copyProtocolList                 // 返回类实现的协议列表
  • class_getVersion                         // 获取版本号
  • class_setVersion                         // 设置版本号

 

    • 父类和元类
// 获取类的父类Class class_getSuperclass ( Class cls );// 判断给定的Class是否是一个元类BOOL class_isMetaClass ( Class cls );

 

    •  类名  
// 获取类的类名const char * class_getName ( Class cls );

 

    • 成员变量大小  
// 获取实例大小size_t class_getInstanceSize ( Class cls );

 

    • 版本  
// 获取版本号int class_getVersion ( Class cls );// 设置版本号void class_setVersion ( Class cls, int version );

 

    • 成员变量  
/** 成员变量操作函数 */ // 获取类中指定名称实例成员变量的信息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 );

 

    •   属性 
/** 属性操作函数 */// 获取指定的属性objc_property_t class_getProperty ( Class cls, const char *name );// 获取属性列表objc_property_t * class_copyPropertyList ( Class cls, unsigned int *outCount );// 为类添加属性BOOL class_addProperty ( Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount );// 替换类的属性void class_replaceProperty ( Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount );

 

    • 方法  
// 添加方法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 );

 

    • 协议  
// 添加协议BOOL class_addProtocol ( Class cls, Protocol *protocol );// 返回类是否实现指定的协议BOOL class_conformsToProtocol ( Class cls, Protocol *protocol );// 返回类实现的协议列表Protocol * class_copyProtocolList ( Class cls, unsigned int *outCount );

 

2. 对象相关的操作函数,以object为前缀命名

  • object_copy                                    // 返回指定对象的一份拷贝
  • object_dispose                                // 释放指定对象占用的内存
  • object_setInstanceVariable              // 修改类实例的实例变量的值
  • object_getInstanceVariable              // 获取对象实例变量的值
  • object_getIndexedIvars                   // 返回指向给定对象分配的任何额外字节的指针
  • object_getIvar                                // 返回对象中实例变量的值
  • object_setIvar                                // 设置对象中实例变量的值
  • object_getClassName                      // 返回给定对象的类名
  • object_getClass                              // 返回对象的类
  • object_setClass                              // 设置对象的类

 

    •   针对整个对象进行操作的函数
// 返回指定对象的一份拷贝id object_copy ( id obj, size_t size );// 释放指定对象占用的内存id object_dispose ( id obj );

 

 

    •   针对对象实例变量进行操作的函数
// 修改类实例的实例变量的值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 );

 

 

    •   针对对象的类进行操作的函数
// 返回给定对象的类名const char * object_getClassName ( id obj );// 返回对象的类Class object_getClass ( id obj );// 设置对象的类Class object_setClass ( id obj, Class cls );

 

四、动态创建类和对象 

1. 动态创建类

 

  • objc_allocateClassPair  // 创建一个新类和元类
  • objc_disposeClassPair  // 销毁一个类及其相关联的类
  • objc_registerClassPair // 在应用中注册由objc_allocateClassPair创建的类

 

// 创建一个新类和元类Class objc_allocateClassPair ( Class superclass, const char *name, size_t extraBytes );// 销毁一个类及其相关联的类void objc_disposeClassPair ( Class cls );// 在应用中注册由objc_allocateClassPair创建的类void objc_registerClassPair ( Class cls );

 

 

2. 动态创建对象

  • class_createInstance       // 创建类实例
  • objc_constructInstance   // 在指定位置创建类实例
  • objc_destructInstance    // 销毁类实例

 

// 创建类实例id class_createInstance ( Class cls, size_t extraBytes );// 在指定位置创建类实例id objc_constructInstance ( Class cls, void *bytes );// 销毁类实例void * objc_destructInstance ( id obj );

 

 

五、获取类定义

 1. Objective-C动态运行库会自动注册我们代码中定义的所有的类。我们也可以在运行时创建类定义并使用objc_addClass函数来注册它们。

// 获取已注册的类定义的列表int objc_getClassList ( Class *buffer, int bufferCount );// 创建并返回一个指向所有已注册类的指针列表Class * objc_copyClassList ( unsigned int *outCount );// 返回指定类的类定义Class objc_lookUpClass ( const char *name );Class objc_getClass ( const char *name );Class objc_getRequiredClass ( const char *name );// 返回指定类的元类Class objc_getMetaClass ( const char *name );

 

转载于:https://www.cnblogs.com/gzhu-lkun/p/5928904.html

你可能感兴趣的文章
UI_搭建MVC
查看>>
一个样例看清楚JQuery子元素选择器children()和find()的差别
查看>>
代码实现导航栏分割线
查看>>
Windows Phone开发(7):当好总舵主 转:http://blog.csdn.net/tcjiaan/article/details/7281421...
查看>>
VS 2010打开设计器出现错误
查看>>
SQLServer 镜像功能完全实现
查看>>
Vue-详解设置路由导航的两种方法
查看>>
一个mysql主从复制的配置案例
查看>>
大数据学习系列(8)-- WordCount+Block+Split+Shuffle+Map+Reduce技术详解
查看>>
dvwa网络渗透测试环境的搭建
查看>>
Win8 安装VS2012 和 Sql Server失败问题
查看>>
过点(2,4)作一直线在第一象限与两轴围成三角形,问三角形面积的最小值?...
查看>>
java aes CBC的填充方式发现
查看>>
使用ionic cordova build android --release --prod命令打包报有如下错误及解决方法
查看>>
BZOJ 2338 HNOI2011 数矩形 计算几何
查看>>
关于页面<!DOCTYPE>声明
查看>>
【AS3代码】播放FLV视频流的三步骤!
查看>>
C++标准库vector使用(更新中...)
查看>>
cocos2d-x 2.2.6 之 .xml文件数据读取
查看>>
枚举的使用
查看>>