runtime理解

什么是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];
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值