JHHK

欢迎来到我的个人网站
行者常至 为者常成

Runtime(八):API

目录

@implementation ViewController

void run(id self,SEL _cmd){
    printf("run\n");
}


-(void)run{
    NSLog(@"run");
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    Person * person = [[Person alloc] init];
    
    //获取isa指向的类
    Class cls = object_getClass(person);//类对象
    Class cls1 = object_getClass(cls);//元类对象
    Class cls2 = object_getClass([Person class]);//元类对象
    
    //判断一个对象是否是Class
    BOOL isCls  = object_isClass(person);
    BOOL isCls1 = object_isClass([Person class]);
    BOOL isCls2 = object_isClass(object_getClass([person class]));
    
    //判断一个对象是否是meta-class
    BOOL isMetaCls  =  class_isMetaClass(person);
    BOOL isMetaCls1 =  class_isMetaClass([Person class]);
    BOOL isMetaCls2 =  class_isMetaClass(object_getClass([Person class]));
    
    
    //获取父类
    Class cls3 = class_getSuperclass([Person class]);
    
    
    //修改实例对象的isa指向
    object_setClass(person, [Student class]);
    [person run];
    
    
    //动态创建一个类
    Class Dog = objc_allocateClassPair([NSObject class], "Dog", 0);
    
    //添加成员变量 (添加成员变量应该在注册类之前)
    class_addIvar(Dog, "_number", 4, 1, @encode(int));
    class_addIvar(Dog, "_age", 4, 1, @encode(int));


    //添加方法(添加方法可在注册类之前也可在之后)
    //class_addMethod(Dog, @selector(run), (IMP)run, "v@:");//添加c语言方法
    IMP methodImp = class_getMethodImplementation([self class], @selector(run));
    class_addMethod(Dog, @selector(run), methodImp, "v@:");

    //注册类
    objc_registerClassPair(Dog);
    
    //查看该类的实例对象需要的空间大小
    int size = class_getInstanceSize(Dog);

    //创建一个实例对象
    id dog = [[Dog alloc] init];
    
    [dog setValue:@10 forKey:@"number"];
    [dog setValue:@3 forKey:@"age"];
    
    NSLog(@"number=%@,name=%@",[dog valueForKey:@"number"],[dog valueForKey:@"age"]);
        
    [dog run];

//    objc_disposeClassPair(Dog);//销毁一个类
}

成员变量

//获取成员变量的信息 注意name是属性名 _name 才是成员变量
Ivar nameIvar = class_getInstanceVariable([Person class], "_name");
const char * name   = ivar_getName(nameIvar);
const char * encode = ivar_getTypeEncoding(nameIvar);
NSLog(@"%s,%s",name,encode);
//获取一个类的成员变量列表
unsigned int outCount = 0;
Ivar * iVarList = class_copyIvarList([Person class], &outCount);
NSLog(@"outCount = %d",outCount);//outCount = 2

for (int i=0; i<outCount; i++) {
    Ivar instanceVar = iVarList[i];
    const char * name   = ivar_getName(instanceVar);
    const char * encode = ivar_getTypeEncoding(instanceVar);
    NSLog(@"%s,%s",name,encode);
}
//copy 最后需要释放
free(iVarList);
Person * person = [[Person alloc] init];
person.name = @"小明";

//获取成员变量的值
id personName = object_getIvar(person, nameIvar);
NSLog(@"personName = %@",personName);//personName = 小明

//设置成员变量的值
object_setIvar(person, nameIvar, @"Tom");
personName = object_getIvar(person, nameIvar);
NSLog(@"personName = %@",personName);//personName = Tom

属性

//获取属性信息
objc_property_t nameProperty = class_getProperty([Person class], "name");
const char * name = property_getName(nameProperty);
const char * attribute = property_getAttributes(nameProperty);
NSLog(@"%s,%s",name,attribute);// name,T@"NSString",&,N,V_name
//获取一个类的属性列表
unsigned int outCount;
objc_property_t * propertyList = class_copyPropertyList([Person class], &outCount);
for (int i=0; i<outCount; i++) {
    objc_property_t property = propertyList[i];
    const char * name = property_getName(property);
    const char * attribute = property_getAttributes(property);
    NSLog(@"%s,%s",name,attribute);
}

//最后需要释放
free(propertyList);

方法

//获取方法信息
//class_getClassMethod(Class  _Nullable __unsafe_unretained class, SEL  _Nonnull name);
Method runMethod = class_getInstanceMethod([Person class], @selector(run));
SEL run = method_getName(runMethod);
const char * type = method_getTypeEncoding(runMethod);
IMP imp = method_getImplementation(runMethod);
//获取方法列表
unsigned int  outCount;
//获取对象方法类表
Method * methodList = class_copyMethodList([Person class], &outCount);
//获取类方法类表
//Method * methodList = class_copyMethodList(object_getClass([Person class]), &outCount);
for (int i=0; i<outCount; i++) {
    Method method = methodList[i];
    SEL run = method_getName(method);
    const char * type = method_getTypeEncoding(method);
    IMP imp = method_getImplementation(method);
    NSLog(@"%s,%s",run,type);
}
//动态替换方法
void test(void){
    printf("test\n");
}

- (void)viewDidLoad {
    [super viewDidLoad];
    class_replaceMethod([Person class], @selector(run), (IMP)test, "v");
    Person * person = [[Person alloc] init];
    [person run];
}

class_replaceMethod([Person class], @selector(run), imp_implementationWithBlock(^{
    NSLog(@"123");
}), "v");

[[[Person alloc] init] run];//123
//交换方法
- (void)viewDidLoad {
    [super viewDidLoad];
    
    //交换方法:不仅可以交换类内还可以与其他类交换
    //Method runMethod = class_getInstanceMethod([Person class], @selector(run));
    Method runMethod = class_getInstanceMethod([Student class], @selector(run));
    Method printMethod = class_getInstanceMethod([Person class], @selector(print));

    method_exchangeImplementations(printMethod, runMethod);
    
    Person * person = [[Person alloc] init];
    [person print];//-[Student run]
}

具体应用

1、利用关联对象给分类添加属性。

2、遍历类的所有成员变量

  • 修改textField的占位文字
  • 字典转模型
  • 自动归档解档

3、交换方法实现(交换系统方法)

4、利用消息转发机制,解决方法找不到的异常问题。


行者常至,为者常成!





R
Valine - A simple comment system based on Leancloud.