前言:
- 本文将陆续列举介绍
<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
这个类并不存在)
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_getName
和 sel_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));
具体使用场景将在介绍动态添加方法时再进行说明。