以KVO为例做了一个简单的响应式编程demo,特此记。
KVO的底层实现就是监听属性值set方法的改变。
需要创建一下几个文件。
Person
Person.h
#import <Foundation/Foundation.h>
@interface Person : NSObject
/** age */
@property(nonatomic,assign)NSInteger age;
@end
Person.m
#import "Person.h"
@implementation Person
@end
KVO_Person
KVO_Person.h
#import "Person.h"
@interface KVO_Person : Person
@end
KVO_Person.m
#import "KVO_Person.h"
#import "NSObject+zw_Kvo.h"
#import <objc/runtime.h>
@implementation KVO_Person
-(void)setAge:(NSInteger)age
{
[super setAge:age];
//发通知
id obsver = objc_getAssociatedObject(self, @"obsever");
id keypath = objc_getAssociatedObject(self, @"keyPath");
[obsver observeValueForKeyPath:keypath ofObject:nil change:nil context:nil];
}
@end
NSObject+zw_Kvo
NSObject+zw_Kvo.h
#import <Foundation/Foundation.h>
@interface NSObject (zw_Kvo)
- (void)zw_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context;
@end
NSObject+zw_Kvo.m
#import "NSObject+zw_Kvo.h"
#import "KVO_Person.h"
#import <objc/runtime.h>
@implementation NSObject (zw_Kvo)
- (void)zw_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context
{
//修改对象指针
object_setClass(self, [KVO_Person class]);
//保存可以
objc_setAssociatedObject(self, @"obsever", observer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
objc_setAssociatedObject(self, @"keyPath", keyPath, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end
ZWKVOViewController
ZWKVOViewController.m
#import "ZWKVOViewController.h"
#import "Person.h"
#import "NSObject+zw_Kvo.h"
@interface ZWKVOViewController ()
@property(nonatomic,strong) Person *person;
@end
@implementation ZWKVOViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"响应式编程实现KVO";
[self method2];
}
-(void)method2
{
//实现KVO 就是监听set方法
Person *person = [[Person alloc]init];
[person zw_addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew context:nil];
self.person = person;
}
-(void)method1
{
//实现KVO 就是监听set方法
Person *person = [[Person alloc]init];
[person addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew context:nil];
self.person = person;
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
{
NSLog(@"age==>");
}
-(void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[self.person removeObserver:self forKeyPath:@"age"];
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
self.person.age ++;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end