最近在学习ReactCocoa,学习前,首先需要了解的几种编程思想,包括面向对象,面向过程,链式编程,响应式编程,函数式编程思想等,这里主要介绍一下响应式编程,其他的几种会一一介绍。
`响应式编程思想`:不需要考虑调用顺序,只需要知道考虑结果,类似于蝴蝶效应,产生一个事件,会影响很多东西,这些事件像流一样的传播出去,然后影响结果,借用面向对象的一句话,万物皆是流。
了解了上面的概念,可能还是不是很清楚,下面举例说明一下,最典型的就是我们开发过程中常见的KVO,下面详细讲解一下KVO的底层实现:
首先,当为一个对象添加一个观察者,即调用 [p addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew context:nil]这个方法的时候,其实OC的底层会做一下操作
1.只要p的age属性一改变,就会调用观察者的observeValueForKeyPath
KVO底层实现:
1.动态创建NSKVONotifying_Person,NSKVONotifying_Person是Person子类,做KVO
2.修改当前对象的isa指针->NSKVONotifying_Person
3.只要调用对象的set,就会调用NSKVONotifying_Person的set方法
4.重写NSKVONotifying_Person的set方法,(1).[super set:] (2).通知观察者,告诉你属性改变
其实,底层实现的实质就是去判断有没有调用一个对象的set方法,如果你改变一个对象的属性的值,不通过set方法,那么KVO就会失效,就不会观察到。
自己仿造苹果的KVO实现代码如下:
1.为NSObject添加一个分类
#import <Foundation/Foundation.h>
@interface NSObject (KVO)
- (void)xmg_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context;
@end
#import "NSObject+KVO.h"
#import "XMGKVONotifying_Person.h"
#import <objc/runtime.h>
@implementation NSObject (KVO)
- (void)xmg_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context
{
// 1.动态创建NSKVONotifying_Person,NSKVONotifying_Person是Person子类,做KVO
// 2.修改当前对象的isa指针->NSKVONotifying_Person
// 3.只要调用对象的set,就会调用NSKVONotifying_Person的set方法
// 4.重写NSKVONotifying_Person的set方法,1.[super set:] 2.通知观察者,告诉你属性改变
// 修改isa,本质就是改变当前对象的类名
object_setClass(self, [XMGKVONotifying_Person class]);
// 把观察者保存到当前对象里
// 添加关联
// id object:给哪个对象添加关联属性
// key:属性名
// value:关联值
objc_setAssociatedObject(self, @"observer", observer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end
2.创建一个Person的子类--> XMGKVONotifying_Person,并且重写 XMGKVONotifying_Person的setAge方法,即可
#import "Person.h"
@interface XMGKVONotifying_Person : Person
@end
#import "XMGKVONotifying_Person.h"
#import <objc/runtime.h>
@implementation XMGKVONotifying_Person
- (void)setAge:(int)age
{
[super setAge:age];
// 通知观察者,属性改变
id observer = objc_getAssociatedObject(self, @"observer");
[observer observeValueForKeyPath:@"age" ofObject:self change:nil context:nil];
}
@end
,至此,就用自己的一套替代了苹果底层的KVO的实现,同样的效果。
其中在为NSObject添加的分类的过程中,用到了一些运行时的东西,也就是在给NSObject动态的添加一个属性observe来保存观察者的时候,运行时真的是一个很牛逼的东西,很多东西需要潜心的去探索,这里重点不在运行时,后续会有专门的文章来叙述。