runtime 消息机制
runtime 可以为类动态添加方法,属性,监听类的属性改变
一.下面 演示动态为分类添加属性
// 定义一个person类 Person.h #import <Foundation/Foundation.h> @interface Person : NSObject @property (nonatomic, copy)NSString * name; @end
为Person添加分类
#import "Person.h" @interface Person (hobby) //分类中能够定义属性,但是没有自动生成getter&setter方法,对应的成员变量也不生成 @property(nonatomic,copy) NSString *hobby; //- (NSString *)hobby; //- (void)setHobby:(NSString *)hobby; @end
#import "Person+hobby.h" #import <objc/runtime.h> const char * KEY = "hobby"; @implementation Person (hobby) - (NSString *)hobby{ /* 1.要求关联的对象 2.关联的key */ return objc_getAssociatedObject(self, KEY); } - (void)setHobby:(NSString *)hobby{ /* 关联对象 1. 要求关联的对象 2. 关联的key 3. 关联的值 4. 关联策略- 属性关键字 */ objc_setAssociatedObject(self, KEY, hobby, OBJC_ASSOCIATION_COPY_NONATOMIC); } @end
在主程序中调用
// MARK: - 在分类中添加的 hobby 属性 Person * p = [[Person alloc] init]; self.p = p; p.name = @"张三"; [p setHobby:@"打篮球"]; //在分类中动态添加属性 NSLog(@"姓名:%@,爱好:%@",p.name,p.hobby);
打印结果
2016-08-06 23:20:58.655 runtimeDemo[2879:382062] 姓名:张三,爱好:打篮球
属性 其实就是get/set 方法。我们可以使用 objc_setAssociatedObject/objc_getAssociatedObject 实现 动态向类中添加 方法
二.监听属性的值的改变
// MARK: - 监听对象属性的改变 NSLog(@"isa:%@",[p valueForKeyPath:@"isa"]); [p addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:NULL]; NSLog(@"isa:%@",[p valueForKeyPath:@"isa"]); p.name = @"李四";
打印信息
2016-08-06 23:20:58.656 runtimeDemo[2879:382062] isa:Person 2016-08-06 23:20:58.656 runtimeDemo[2879:382062] isa:NSKVONotifying_Person
KVO 的原理就是 为p类添加监听的时候 ,重新生成了一个类,这个类继承p,重写了p属性的setter方法
代码在Github上面:https://github.com/Amuxiaomu/runtimeDemo