iOS Runtime笔记

作者: Stark_Dylan | 来源:发表于2015-02-17 21:25 被阅读2483次

    Objective-C语言是一门动态语言,它将很多静态语言在编译和链接时期做的事放到了运行时来处理。这种动态语言的优势在于:我们写代码时更具灵活性,如我们可以把消息转发给我们想要的对象,或者随意交换一个方法的实现等。

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

    typedef struct objc_class *Class;
    

    查看objc/runtime.h中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;
    

    1、

    常用举例

    Class newClass = objc_allocateClassPair([NSError class], "TestClass", 0); // 创建新的类
    

    参数1: 父类
    参数2: 子类名
    参数3: extraBytes

    class_addMethod(newClass, @selector(testMetaClass), (IMP)TestMetaClass, "v@:"); // 为新的类添加方法
    

    参数1: 类名
    参数2: 方法名称
    参数3: 方法(IMP)你写的方法名
    参数4: 一个定义该函数返回值类型和参数类型的字符串 根据返回值和参数
    动态的确定
    查看返回值类型表达方法
    这里可以查看对应返回值类型的表达方法 v表示void 后边的:后边表示参数 比如说 定义 int:(id self, SEL _cmd,NSString * name) 那么就是 i@:@这样的。

    objc_registerClassPair(newClass); // 注册创建的类
    id instance = [[newClass alloc] initWithDomain:@"some domain" code:0 userInfo:nil]; // 实例化对象
    [instance performSelector:@selector(testMetaClass)]; // 调用方法
    
    // 获取类的类名
    const char * class_getName ( Class cls );
    
    
    // 获取类的父类
    Class class_getSuperclass ( Class cls );
    
    // 判断给定的Class是否是一个元类
    BOOL class_isMetaClass ( Class cls );
    
    // 获取实例大小
    
    size_t class_getInstanceSize ( Class cls );
    

    在objc_class中,所有的成员变量、属性的信息是放在链表ivars中的。ivars是一个

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

    class_copyIvarList函数,它返回一个指向成员变量信息的数组,数组中每个元素是指向该成员变量信息的objc_ivar结构体的指针。这个数组不包含在父类中声明的变量。outCount指针返回数组的大小。需要注意的是,我们必须使用free()来释放这个数组

    // 获取指定的属性
    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 );
    
    // 类实例是否响应指定的selector
    BOOL class_respondsToSelector ( Class cls, SEL sel );
    

    class_addMethod的实现会覆盖父类的方法实现,但不会取代本类中已存在的实现,如果本类中包含一个同名的实现,则函数会返回NO。如果要修改已存在实现,可以使用method_setImplementation。一个Objective-C方法是一个简单的C函数,它至少包含两个参数—self和_cmd。所以,我们的实现函数(IMP参数指向的函数)至少需要两个参数,如下所示:

    void myMethodIMP(id self, SEL _cmd)
    {
    // implementation ....
    }
    
    
    // 添加协议
    BOOL class_addProtocol ( Class cls, Protocol *protocol );
    
    // 返回类是否实现指定的协议
    BOOL class_conformsToProtocol ( Class cls, Protocol *protocol );
    
    // 返回类实现的协议列表
    Protocol * class_copyProtocolList ( Class cls, unsigned int *outCount );
    
    
    // 获取版本号
    int class_getVersion ( Class cls );
    
    // 设置版本号
    void class_setVersion ( Class cls, int version );
    
    // 创建一个新类和元类
    Class objc_allocateClassPair ( Class superclass, const char *name, size_t extraBytes );
    
    // 销毁一个类及其相关联的类
    void objc_disposeClassPair ( Class cls );
    
    // 在应用中注册由objc_allocateClassPair创建的类
    void objc_registerClassPair ( Class cls );
    
    // 创建类实例
    id class_createInstance ( Class cls, size_t extraBytes );
    
    // 在指定位置创建类实例
    id objc_constructInstance ( Class cls, void *bytes );
    
    // 销毁类实例
    void * objc_destructInstance ( id obj );
    
    
    // 返回指定对象的一份拷贝
    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 );
    
    
    // 获取已注册的类定义的列表
    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 );
    

    _iOS.Dev GoodMood.

    相关文章

      网友评论

      • FengxinLi:请问一下楼主 class_addMethod(newClass, @selector(testMetaClass), (IMP)TestMetaClass, "v@:"); // 为新的类添加方法 TestMetaClass 这个需要引入什么不?为什么我这报错呢?
        Stark_Dylan:@Fengxinliju 要引入 objc/runtime
      • iOS_愛OS:解决了我的问题,谢啦哈
        Stark_Dylan:@iOS_愛OS 😋荣幸

      本文标题:iOS Runtime笔记

      本文链接:https://www.haomeiwen.com/subject/mpyyxttx.html