ios runtime重要性_iOS runtime理解

1.isa指针

Person * person = [[Person alloc]init];

[person getName];

一个Person对象person调用getName的方法,getName方法是在类中声明的,也就是对象调用的方法实际是去类中查找的,如果有接直接调用,如果该类没有此方法,那么就去父类中查找该方法,一直没有直到NSObject,再没有就报错了。那么如何能从对象找到对应的类呢,这里就引入了isa指针。

每一个对象都有一个isa指针,指向该对象的类。

其实类本身也是一个对象,它的isa指针指向元类。

元类也是一个对象,它的isa指针指向NSObject元类。

NSObject元类的isa指针指向自己。

Person类的结构

{

-(void)init;

-(NSString*)getName;

}

Person元类的结构

{

-(void)alloc;

}

2.动态绑定

有时候有这样的需求,我们需要知道类中每个属性的名字,比如字典转模型。我们就可以通过runtime机制获取类中一些信息,包括属性列表,方法列表,遵循的协议列表等。这就类似java中的反射。

因为对象调用方法和类调用方法,实际上相当于给对应的target发送消息。那么我们就可以把消息封装成一个字符串,在代码执行(不是编译时)的时候,从服务器获取不同字符串来传递不同的消息,也就是调用不同的方法了,做到动态绑定。

3.runtime应用场景

runtime是一个iOS提供开发者的C语言库。

a.字典转模型

b.对象序列化和反序列化

把对象数据存到磁盘,把磁盘数据读取为对象,也就是对象的序列化和反序列化。

iOS对象序列化的思路是:

1.需要序列化的对象模型实现NSCoding协议。

2.实现NSCoding编码和解码这两个方法

-(void)encodeWithCoder:(NSCoder*)aCoder

-(instancetype)initWithCoder:(NSCoder*)aDecoder

比如把Person类对象进行序列化和反序列化。

@interfacePerson :Human

@property(nonatomic,copy)NSString* name;

@property(nonatomic,assign)intage;

@property(nonatomic,strong)NSMutableArray* phones;

-(instancetype)initWithCoder:(NSCoder*)aDecoder

{

self.name=[aDecoder decodeObjectForKey:@"name"];

self.age=[[aDecoder decodeObjectForKey:@"age"] intValue];

self.phones=[aDecoder decodeObjectForKey:@"phones"];

}

returnself;

}

-(void)encodeWithCoder:(NSCoder*)aCoder

{

[aCoder encodeObject:self.name forKey:@"name"];

[aCoder encodeObject:@(self.age) forKey:@"age"];

[aCoder encodeObject:self.phones forKey:@"phones"];

}

那么一定会面临几个问题,如果属性太多,难道需要些很多冗余代码么?父类的属性如何序列化?属性是复杂对象类型如何处理?

使用RunTime解决第一,二个问题。

-(instancetype)initWithCoder:(NSCoder*)aDecoder

{

if(self=[superinit])

{

Classcls =self.class;

//递归该对象的属性和父类中属性

while(cls!=[NSObjectclass]) {

unsignedintcount;

//通过runtime获取成员变量列表,该方法返回值是一个Ivar数组,Ivar是一个指向成员变量的指针

Ivar* ivarsList =class_copyIvarList(cls, &count);

for(inti=0; i

Ivarivar = ivarsList[i];

constchar* name =ivar_getName(ivar);

NSString* keyName = [NSStringstringWithUTF8String:name];

NSLog(@"class:%@,ivar:%@",cls,keyName);

idobj = [aDecoderdecodeObjectForKey:keyName];

//KVC赋值数据(经测试,KVC可以实现父类成员变量的获取和赋值)

[selfsetValue:objforKey:keyName];

}

//ivarsList需要被释放

free(ivarsList);

cls =class_getSuperclass(cls);

}

}

returnself;

}

-(void)encodeWithCoder:(NSCoder*)aCoder

{

Classcls =self.class;

while(cls!=[NSObjectclass]) {

unsignedintcount;

Ivar* ivarsList =class_copyIvarList(cls, &count);

for(inti=0; i

Ivarivar = ivarsList[i];

constchar* name =ivar_getName(ivar);

NSString* keyName = [NSStringstringWithUTF8String:name];

NSString* keyValue = [selfvalueForKey:keyName];

NSLog(@"class:%@,ivar:%@",cls,keyName);

[aCoderencodeObject:keyValueforKey:keyName];

}

free(ivarsList);

cls =class_getSuperclass(cls);

}

}

c.方法交换 Method Swizzling

交换两个方法的实现,实现面向切面变成的思想,一般用于给系统方法添加自定义实现。

eg:HooK出NSURL类方法URLWithString:和实例方法initWithString:并进行打印。

@implementation NSURL (ZS)

//在类第一次装载的时候进行方法交换,调用的时候才会交换,实现runtime效果

+(void)load

{

//交换类方法

Method class_origin_Method = class_getClassMethod(self.class, @selector(URLWithString:));

Method class_swizzling_Method = class_getClassMethod(self.class, @selector(ZS_URLWithString:));

method_exchangeImplementations(class_origin_Method, class_swizzling_Method);

//交换实例方法

Method instance_origin_Method = class_getInstanceMethod(self.class, @selector(initWithString:));

Method instance_swizzling_Method = class_getInstanceMethod(self.class, @selector(ZS_initWithString:));

method_exchangeImplementations(instance_origin_Method, instance_swizzling_Method);

}

+ (nullable instancetype)ZS_URLWithString:(NSString *)URLString

{

NSLog(@"ZS_URLString:%@",URLString);

return [NSURL ZS_URLWithString:URLString];

}

-(instancetype)ZS_initWithString:(NSString *)URLString

{

NSLog(@"ZS_initWithString:%@",URLString);

return [self ZS_initWithString:URLString];

}

- (void)viewDidLoad {

[super viewDidLoad];

//NSURL * url = [NSURL URLWithString:@"http://www.baidu.com"];

NSURL * url = [[NSURL alloc]initWithString:@"http://www.qq.com"];

NSURLRequest * req = [NSURLRequest requestWithURL:url];

NSLog(@"req:%@",req);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值