iOS中的runtime笔记

runtime:是一套底层的C语言API,包含很多强大实用的C语言数据类型和C语言函数,平时我们编写的OC代码,底层都是基于runtime实现的。

常用头文件:

#import <objc/runtime.h>

#import <objc/message.h>

objc_msgSend

Objective-C 中的方法调用,不是简单的方法调用,而是发送消息,如:

TestClass *objct = [[TestClass alloc] init];

[objctshowName:@"Tom"];

转化为:

((void (*) (id, SEL, NSString *)) objc_msgSend) (objct, sel_registerName("showName:"), 

@"Tom");

objc_msgSend 在使用时都被强制转换了一下,这是因为 objc_msgSend 函数可以传各种不同的返回值以及多个参

数,但默认情况

下是没有参数和返回值的。

class_copyIvarList:返回一个指向类的成员变量数组的指针

class_copyIPropertyList:返回一个指向类的属性数组的指针

上面两个方法返回的指针,在使用完毕之后必须free()。

开发中使用:

归档:

- (void)encodeWithCoder:(NSCoder *)aCoder{
     unsigned int outCount = 0;
     Ivar *vars = class_copyIvarList([self class], &outCount);
     for  (int i = 0; i < outCount; i ++) {
         Ivar  var  = vars[i];
         const char *name = ivar_getName( var );
         NSString *key = [NSString stringWithUTF8String:name];
         // 注意kvc的特性是,如果能找到key这个属性的setter方法,则调用setter方法
         // 如果找不到setter方法,则查找成员变量key或者成员变量_key,并且为其赋值
         // 所以这里不需要再另外处理成员变量名称的“_”前缀
         id value = [self valueForKey:key];
         [aCoder encodeObject:value forKey:key];
     }
free(vars);
}
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder{
     if  (self = [ super  init]) {
         unsigned int outCount = 0;
         Ivar *vars = class_copyIvarList([self class], &outCount);
         for  (int i = 0; i < outCount; i ++) {
             Ivar  var  = vars[i];
             const char *name = ivar_getName( var );
             NSString *key = [NSString stringWithUTF8String:name];
             id value = [aDecoder decodeObjectForKey:key];
             [self setValue:value forKey:key];
         }
free(vars);
     }
     return  self;
}
//字典转模型
+(id)objectWithKeyValues:(NSDictionary *)aDictionary{
     id objc = [[self alloc] init];
     for  (NSString *key  in  aDictionary.allKeys) {
         id value = aDictionary[key];
         /*判断当前属性是不是Model*/
         objc_property_t property = class_getProperty(self, key.UTF8String);
         unsigned int outCount = 0;
         objc_property_attribute_t *attributeList = property_copyAttributeList(property,
 &outCount);
         objc_property_attribute_t attribute = attributeList[0];
         NSString *typeString = [NSString stringWithUTF8String:attribute.value];
         if  ([typeString isEqualToString:@ "@\"TestModel\"" ]) {
             value = [self objectWithKeyValues:value];
         }
         /**********************/
         //生成setter方法,并用objc_msgSend调用
         NSString *methodName = [NSString stringWithFormat:@ "set%@%@:" ,
[key substringToIndex:1]. uppercaseString,[key substringFromIndex:1]];
         SEL setter = sel_registerName(methodName.UTF8String);
         if  ([objc respondsToSelector:setter]) {
             ((void (*) (id,SEL,id)) objc_msgSend) (objc,setter,value);
         }
free(attributeList);
     }
     return  objc;
}
//模型转字典
-(NSDictionary *)keyValuesWithObject{
     unsigned int outCount = 0;
     objc_property_t *propertyList = class_copyPropertyList([self class], &outCount);
     NSMutableDictionary *dict = [NSMutableDictionary dictionary];
     for  (int i = 0; i < outCount; i ++) {
         objc_property_t property = propertyList[i];
         //生成getter方法,并用objc_msgSend调用
         const char *propertyName = property_getName(property);
         SEL getter = sel_registerName(propertyName);
         if  ([self respondsToSelector:getter]) {
             id value = ((id (*) (id,SEL)) objc_msgSend) (self,getter);
             /*判断当前属性是不是Model*/
             if  ([value isKindOfClass:[self class]] && value) {
                 value = [value keyValuesWithObject];
             }
             /**********************/
             if  (value) {
                 NSString *key = [NSString stringWithUTF8String:propertyName];
                 [dict setObject:value forKey:key];
             }
        }
     }
free(propertyList);
     return  dict;
}

交换方法

method_exchangeImplementations(Method m1, Method m2),一般用自己写的方法(常用在自己写的框架

中,添加某些防错措施)

来替换系统的方法实现

Method orginalMethod = class_getInstanceMethod(NSStringFromClass(@__NSArray),@selector(addObject:));

Method newMethod = class_getInstanceMethod(NSStringFromClass(@__NSArray), @selector(new_addObject:));

method_exchangeImplementations(orginalMethod, newMethod);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值