zoukankan      html  css  js  c++  java
  • iOS Runtime笔记

    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: 一个定义该函数返回值类型和参数类型的字符串 根据返回值和参数动态的确定 https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html 这里可以查看对应返回值类型的表达方法 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 );
     
  • 相关阅读:
    C# 图片与Base64的相互转化
    LeetCode 303. Range Sum Query – Immutable
    LeetCode 300. Longest Increasing Subsequence
    LeetCode 292. Nim Game
    LeetCode 283. Move Zeroes
    LeetCode 279. Perfect Squares
    LeetCode 268. Missing Number
    LeetCode 264. Ugly Number II
    LeetCode 258. Add Digits
    LeetCode 257. Binary Tree Paths
  • 原文地址:https://www.cnblogs.com/Dylan-Alice/p/iOSRuntime.html
Copyright © 2011-2022 走看看