runtime理解

来源:互联网 发布:java版dvd碟片出租系统 编辑:程序博客网 时间:2024/05/22 04:24

什么是runtime

runtime是一套C语言API,我们编写的OC代码在运行的时候会转化为C代码执行。 OC中一切都被设计成对象,其实类也是对象,在runtime中是用结构体来标示的。

  typedef struct objc_method * Method;//描述类中的一个方法  typedef struct objc_ivar * Ivar;//实例变量  typedef struct objc_category * Category;//类别  typedef struct objc_property * objc_property_t;//类中声明的属性

类在runtime中的表示

//类在runtime中的表示struct objc_class {    Class isa;//指针,顾名思义,表示是一个什么,    //实例的isa指向类对象,类对象的isa指向元类#if !__OBJC2__    Class super_class;  //指向父类    const char *name;  //类名    long version;    long info;    long instance_size    struct objc_ivar_list *ivars //成员变量列表    struct objc_method_list **methodLists; //方法列表    struct objc_cache *cache;//缓存    //一种优化,调用过的方法存入缓存列表,下次调用先找缓存    struct objc_protocol_list *protocols //协议列表    #endif} OBJC2_UNAVAILABLE;

runtime有什么作用

能动态的产生一个类,能动态的修改一个类,能动态的删除一个类

常用的runtime方法

class_copyIvarList()//返回一个指向类的成员变量数组的指针class_copyPropertyList()//返回一个指向类的属性数组的指针ivar_getName()//获取成员变量名-->C类型的字符串property_getName()//获取属性名-->C类型的字符串class_getInstanceMethod()//获取动态方法 class_getClassMethod()//获取静态方法method_exchangeImplementations()//交换两个方法的实现  hook

runtime在开发中的使用

  • 动态遍历所有类的成员变量,获取成员变量,主要用于字典转模型,归档解档操作(这个用的比较少)
 unsigned int count = 0;    /** Ivar:表示成员变量类型 */      Ivar *ivars = class_copyIvarList([BDPerson class], &count);//获得一个指向该类成员变量的指针    for (int i =0; i < count; i ++) {        //获得Ivar        Ivar ivar = ivars[i];        //根据ivar获得其成员变量的名称--->C语言的字符串        const char *name = ivar_getName(ivar);          NSString *key = [NSString stringWithUTF8String:name];        NSLog(@"%d----%@",i,key);}   
  • 获取类的全部属性名
unsigned int count = 0;objc_property_t * properties = class_copyPropertyList([Person class],&count);for(int i =0;i<count;i++){  objc_property_t  property = properties[i];  //根据objc_property_t 获得其属性的名称---->C语言的字符串  const char * name = property_getName(property);  NSString * key = [NSString stringWithUTF8String:name];}

应用的场景:字典转模型,归档解档(这个用的比较多)

//注意:归档解档需要遵守<NSCoding>协议,实现以下两个方法- (void)encodeWithCoder:(NSCoder *)encoder{        //归档存储自定义对象        unsigned int count = 0;      //获得指向该类所有属性的指针       objc_property_t *properties =     class_copyPropertyList([BDPerson class], &count);       for (int i =0; i < count; i ++) {            //获得            objc_property_t property = properties[i];        //根据objc_property_t获得其属性的名称--->C语言的字符串          const char *name = property_getName(property);      NSString *key = [NSString   stringWithUTF8String:name];          //      编码每个属性,利用kVC取出每个属性对应的数值               [encoder encodeObject:[self valueForKeyPath:key] forKey:key];  }}- (instancetype)initWithCoder:(NSCoder *)decoder{          //归档存储自定义对象            unsigned int count = 0;        //获得指向该类所有属性的指针          objc_property_t *properties = class_copyPropertyList([BDPerson class], &count);          for (int i =0; i < count; i ++) {              objc_property_t property = properties[i];        //根据objc_property_t获得其属性的名称--->C语言的字符串              const char *name = property_getName(property);          NSString *key = [NSString stringWithUTF8String:name];        //解码每个属性,利用kVC取出每个属性对应的数值             [self setValue:[decoder decodeObjectForKey:key] forKeyPath:key];  }    return self;}
  • 动态交换方法
    通过runtime的method_exchangeImplementations(Method m1, Method m2)方法,实现两个方 法的交换,例如替换系统的(NSMutableArray)数组的addObject方法。
Method orginalMethod = class_getInstanceMethod(NSClassFromString(@"_NSArrayM"),@selector(addObject:));Method newMethod = class_getInstanceMethod(NSClassFromString(@"_NSArrayM"),@selector(custom_addObject:));method_exchangeImplementations(orginalMethod, newMethod) - (void)custom_addObject:(id)object{   //注意 这里必须要回调一下,因为方法的实现已经交换了不会出现死循环    [self  custom_addObject:object];}