使用Block实现KVO

而且如果在这个时候打印观察者list,则会输出:

SJKVOController[80499:4242749] SJKVOLog:There is no observers obserbing object:<Model: 0x60000003b700>

需要注意的是,这里的移除可以有多种选择:可以移某个对象的某个key,也可以移除某个对象的几个keys,为了验证,我们可以结合list方法来验证一下移除是否成功:

验证1:在添加number和color的观察后,移除nunber的观察:

- (IBAction)removeAllObservingItems:(UIButton *)sender {
    [self.model sj_removeObserver:self forKey:@"number"];
}

在移除以后,我们调用list方法,输出:

SJKVOController[80850:4278383] SJKVOLog:==================== Start Listing All Observers: ====================
SJKVOController[80850:4278383] SJKVOLog:observer item:{observer: <ViewController: 0x7ffeec408560> | key: color | setter: setColor:}

现在只有color属性被观察了。看一下实际的效果:

使用Block实现KVO
只观察颜色的变化

我们可以看到,现在只有color在变,而数字没有变化了,验证此移除方法正确。

验证2:在添加number和color的观察后,移除number和color的观察:

- (IBAction)removeAllObservingItems:(UIButton *)sender {

    [self.model sj_removeObserver:self forKeys:@[@"number",@"color"]];
}

在移除以后,我们调用list方法,输出:

SJKVOController[80901:4283311] SJKVOLog:There is no observers obserbing object:<Model: 0x600000220fa0>

现在color和number属性都不被观察了。看一下实际的效果:

使用Block实现KVO
颜色和数字的变化都不再被观察

我们可以看到,现在color和number都不变了,验证此移除方法正确。

OK,现在知道了怎么用SJKVOController,我下面给大家看一下代码:

SJKVOController代码解析

先大致讲解一下SJKVOController的实现思路:

  1. 为了减少侵入性,SJKVOController被设计为NSObject的一个分类。
  2. SJKVOController仿照了KVO的实现思路,在添加观察以后在运行时动态生成当前类的子类,给这个子类添加被观察的属性的set方法并使用isa swizzle的方式将当前对象转换为当前类的子类的实现。
  3. 同时,这个子类还使用了关联对象来保存一个“观察项”的set,每一个观察项封装了一次观察的行为(有去重机制):包括观察自己的对象,自己被观察的属性,以及传进来的block。
  4. 在当前类,也就是子类的set方法被调用的时候做三件事情:
    • 第一件事情是使用KVC来找出当前属性的旧值。
    • 第二件事情是调用父类(原来的类)的set方法(设新值)。
    • 第三件事是根据当前的观察对象和key,在观察项set里面找出对应的block并调用。

再来看一下这个小轮子的几个类:

  • SJKVOController:实现KVO主要功能的类。
  • SJKVOObserverItem:封装观察项的类。
  • SJKVOTool:setter和getter的相互转换和相关运行时查询方法等。
  • SJKVOError:封装错误类型。
  • SJKVOHeader:引用了运行时的头文件。

下面开始一个一个来讲解每个类的源码:

SJKVOController

再看一下头文件:

#import <Foundation/Foundation.h>
#import "SJKVOHeader.h"

@interface NSObject (SJKVOController)

//============== add observer ===============//
- (void)sj_addObserver:(NSObject *)observer forKeys:(NSArray <NSString *>*)keys withBlock:(SJKVOBlock)block;
- (void)sj_addObserver:(NSObject *)observer forKey:(NSString *)key withBlock:(SJKVOBlock)block;


//============= remove observer =============//
- (void)sj_removeObserver:(NSObject *)observer forKeys:(NSArray <NSString *>*)keys;
- (void)sj_removeObserver:(NSObject *)observer forKey:(NSString *)key;
- (void)sj_removeObserver:(NSObject *)observer;
- (void)sj_removeAllObservers;

//============= list observers ===============//
- (void)sj_listAllObservers;

@end

每个方法的意思相信读者已经能看懂了,现在讲一下具体的实现。从sj_addObserver:forKey withBlock:开始:

sj_addObserver:forKey withBlock:方法:

上一页
1 2 3 4 
下一页