美文网首页
runtime使用篇: 简单函数的集合

runtime使用篇: 简单函数的集合

作者: 缔造福地 | 来源:发表于2016-12-11 13:27 被阅读118次
    前言:
    • 本文将陆续列举介绍<objc/runtime.h>中声明的比较简单的函数,相对复杂的仍然会单独成篇
      BOOL object_isClass(id obj)
      const char *object_getClassName(id obj)
      Class objc_getClass(const char *name)
      Class objc_getMetaClass(const char *name)
      BOOL class_isMetaClass(Class cls)
      Class objc_lookUpClass(const char *name)
      Class objc_getRequiredClass(const char *name)
      const char *class_getName(Class cls)
      Class class_getSuperclass(Class cls)
      int class_getVersion(Class cls)
      void class_setVersion(Class cls, int version)
      Ivar class_getClassVariable(Class cls, const char *name)
      Method class_getInstanceMethod(Class cls, SEL name)
      Method class_getClassMethod(Class cls, SEL name)
      IMP class_getMethodImplementation(Class cls, SEL name)
    1. BOOL object_isClass(id obj)

    判断传入的参数是不是一个类(或元类)
    代码示例如下:

    // 获取字符串的类
    Class stringClass = [@"ab" class];
    BOOL isClass1 = object_isClass(stringClass);
    NSLog(@"%d", isClass1);
    
    // 获取NSObject的元类
    Class nsobjectClass = object_getClass([NSObject class]);
    BOOL isClass2 = object_isClass(nsobjectClass);
    NSLog(@"%d", isClass2);
    

    打印结果如下:(其中object_getClass函数的使用见这篇

    runtime[43695:4500971] 1
    runtime[43695:4500971] 1
    
    2. const char *object_getClassName(id obj)

    获取传入参数的类的名称,返回的是C语言字符串类型
    代码示例如下:

    NSObject *obj = [[NSObject alloc] init];
    const char *className = object_getClassName(obj);
    NSLog(@"%s", className);
    

    打印结果如下:

    runtime[43889:4509715] NSObject
    

    说明:我们平时常用的是以下两种方法

    NSLog(@"%@", [obj class]);
    NSLog(@"%@", NSStringFromClass([obj class]));
    

    打印结果和用object_getClassName函数所获取的相同

    3. Class objc_getClass(const char *name)

    通过传入的字符串获取类,如果不存在名为该字符串的类则返回nil
    代码示例如下:

    Class class1 = objc_getClass("NSString");
    Class class2 = objc_getClass("SubObject"); // SubObject这个类并不存在
    NSLog(@"%@", NSStringFromClass(class1));
    NSLog(@"%@", NSStringFromClass(class2));
    

    打印结果如下:

    runtime[51697:5513088] NSString
    runtime[51697:5513088] (null)
    

    说明:我们平时常用的是以下方法

    NSClassFromString(@"NSString");
    
    4. Class objc_getMetaClass(const char *name)BOOL class_isMetaClass(Class cls)

    objc_getMetaClass :通过传入的字符串获取元类,如果不存在名为该字符串的元类则返回nil
    class_isMetaClass :判断传入的类是不是元类
    代码示例如下:

    Class metaClass = objc_getMetaClass("NSObject");
    NSLog(@"%@", NSStringFromClass(metaClass));
    

    打印结果如下:

    runtime[52100:5537089] NSObject
    

    class_isMetaClass 函数验证可知获得的是元类:

    NSLog(@"%d", class_isMetaClass(metaClass));
    
    5. Class objc_lookUpClass(const char *name)

    通过传入的字符串获取类,如果不存在名为该字符串的类则返回nil

    说明:此函数与序号3 objc_getClass 函数使用方法完全相同,作用也基本相同,不同的地方在于:当一个类还没有被注册时, objc_getClass 函数会调用类的回调然后再次检查这个类是否被注册,而 objc_lookUpClass 函数不会调用回调。

    6. Class objc_getRequiredClass(const char *name)

    通过传入的字符串获取类。

    说明:此函数与序号3 objc_getClass 函数使用方法完全相同,作用也基本相同,不同的地方在于:如果不存在名为该字符串的类则杀掉进程从而crash。

    如下图:(其中 SubObject 这个类并不存在)

    objc_getRequiredClass获取不存在的类会导致crash
    7. const char *class_getName(Class cls)

    获取传入的类的名称,返回的是C语言字符串类型
    代码示例如下:

    const char *name = class_getName([UITableView class]);
    NSLog(@"%s", name);
    

    打印结果如下:

    runtime[54133:5665180] UITableView
    

    说明:我们平时常用的是以下两种方法

    NSLog(@"%@", [UITableView class]);
    NSLog(@"%@", NSStringFromClass([UITableView class]));
    

    打印结果和用 class_getName 函数所获取的相同

    8. Class class_getSuperclass(Class cls)

    获取传入的类的父类
    代码示例如下:

    Class superclass = class_getSuperclass([UIView class]);
    NSLog(@"%s", class_getName(superclass));
    

    打印结果如下:

    runtime[54291:5672706] UIResponder
    

    说明:我们平时常用的是以下方法获取父类

    [UIView superclass];
    
    9. int class_getVersion(Class cls)void class_setVersion(Class cls, int version)

    int class_getVersion(Class cls) :获取类的版本号,默认都是0
    void class_setVersion(Class cls, int version) :修改某个类的版本号
    代码示例如下:

    int version = class_getVersion([UIColor class]);
    NSLog(@"%d", version);
    
    class_setVersion([UIColor class], 10);
    int version2 = class_getVersion([UIColor class]);
    NSLog(@"%d", version2);
    

    打印结果如下:

    runtime[54751:5693992] 0
    runtime[54751:5693992] 10
    
    10. Ivar class_getClassVariable(Class cls, const char *name)

    获取参数 cls 类的变量名为 name 的变量
    目前已知的类的变量名只有一个 isa,返回值是参数 cls 的元类。代码示例如下:

    Ivar viewIvar = class_getClassVariable([UIView class], "isa");
    id getViewIvar = object_getIvar([UIView class], viewIvar);
    NSLog(@"%d", class_isMetaClass(getViewIvar));
    NSLog(@"%@", getViewIvar);
    
    Class metaClass = objc_getMetaClass("NSObject");
    Ivar ivar = class_getClassVariable(metaClass, "isa");
    id getIvar = object_getIvar([NSObject class], ivar);
    NSLog(@"%d", class_isMetaClass(getIvar));
    NSLog(@"%@", getIvar);
    

    打印结果如下:

    runtime[60570:6123050] 1
    runtime[60570:6123050] UIView
    runtime[60570:6123050] 1
    runtime[60570:6123050] NSObject
    

    至于为什么没有与之对应的名为 class_setClassVariable 的函数,见苹果回复的邮件

    11. Method class_getInstanceMethod(Class cls, SEL name)

    获取 cls 类的名为 name 的实例方法。如果参数 name 传入 cls 类的类方法则返回空,传入其他类的方法也返回空。
    代码示例如下:其中 method_getNamesel_getName 函数的作用是获取方法名称

    Method mth1 = class_getInstanceMethod([UIButton class], @selector(setImage:forState:)); // UIButton 的实例方法
    SEL sel1 = method_getName(mth1);
    NSLog(@"%s", sel_getName(sel1));
    
    Method mth2 = class_getInstanceMethod([UIButton class], @selector(buttonWithType:)); // UIButton 的类方法
    SEL sel2 = method_getName(mth2);
    NSLog(@"%s", sel_getName(sel2));
    
    Method mth3 = class_getInstanceMethod([UIButton class], @selector(imageNamed:)); // UIImage 的类方法
    SEL sel3 = method_getName(mth3);
    NSLog(@"%s", sel_getName(sel3));
    

    打印结果如下:

    runtime[62633:6415335] setImage:forState:
    runtime[62633:6415335] <null selector>
    runtime[62633:6415335] <null selector>
    
    12. Method class_getClassMethod(Class cls, SEL name)

    获取 cls 类的名为 name 的类方法。如果参数 name 传入 cls 类的实例方法则返回空,传入其他类的方法也返回空。
    代码示例如下:

    Method mth1 = class_getClassMethod([UIColor class], @selector(colorWithWhite:alpha:)); // UIColor 的类方法
    SEL sel1 = method_getName(mth1);
    NSLog(@"%s", sel_getName(sel1));
    
    Method mth2 = class_getClassMethod([UIColor class], @selector(initWithWhite:alpha:)); // UIColor 的实例方法
    SEL sel2 = method_getName(mth2);
    NSLog(@"%s", sel_getName(sel2));
    
    Method mth3 = class_getClassMethod([UIButton class], @selector(imageNamed:)); // UIImage 的类方法
    SEL sel3 = method_getName(mth3);
    NSLog(@"%s", sel_getName(sel3));
    

    打印结果如下:

    runtime[62866:6425568] colorWithWhite:alpha:
    runtime[62866:6425568] <null selector>
    runtime[62866:6425568] <null selector>
    
    13. IMP class_getMethodImplementation(Class cls, SEL name)

    获取 cls 类的名为 name 方法的实现
    代码示例如下:

    IMP imp = class_getMethodImplementation([UIView class], @selector(animateWithDuration:animations:completion:));
    IMP imp2 = class_getMethodImplementation([UIView class], @selector(setNeedsDisplay));
    

    具体使用场景将在介绍动态添加方法时再进行说明。

    相关文章

      网友评论

          本文标题:runtime使用篇: 简单函数的集合

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