YYKit源码探究(四十三) —— NSObject分类之KVO(二)

版本记录

版本号 时间
V1.0 2018.03.30

前言

iOS圈内有几个人大家基本都知道,比如说王巍、唐巧,还有YYKit框架的作者现任职于滴滴的郭曜源 - ibireme等。这里有一篇唐巧对他的专访,还有他的 GitHub - Yaoyuan博客,这里贴出来框架YYKit 框架。接下来几篇我们就一起来看一下这个框架。感兴趣的可以看上面写的几篇。
1. YYKit源码探究(一) —— 基本概览
2. YYKit源码探究(二) —— NSString分类之Hash(一)
3. YYKit源码探究(三) —— NSString分类之Encode and decode(二)
4. YYKit源码探究(四) —— NSString分类之Drawing(三)
5. YYKit源码探究(五) —— NSString分类之Regular Expression(四)
6. YYKit源码探究(六) —— NSString分类之NSNumber Compatible(五)
7. YYKit源码探究(七) —— NSString分类之Utilities(六)
8. YYKit源码探究(八) —— NSNumber分类(一)
9. YYKit源码探究(九) —— UIFont分类之架构分析和Font Traits(一)
10. YYKit源码探究(十) —— UIFont分类之Create font(二)
11. YYKit源码探究(十一) —— UIFont分类之Load and unload font(三)
12. YYKit源码探究(十二) —— UIFont分类之Dump font data(四)
13. YYKit源码探究(十三) —— UIImage分类之框架结构和Create image部分(一)
14. YYKit源码探究(十四) —— UIImage分类之Image Info(二)
15. YYKit源码探究(十五) —— UIImage分类之Modify Image(三)
16. YYKit源码探究(十六) —— UIImage分类之Image Effect(四)
17. YYKit源码探究(十七) —— UIImageView分类之架构和image部分(一)
18. YYKit源码探究(十八) —— UIImageView分类之highlight image部分(二)
19. YYKit源码探究(十九) —— UIScreen分类(一)
20. YYKit源码探究(二十) —— UIScrollView分类(一)
21. YYKit源码探究(二十一) —— UITableView分类(一)
22. YYKit源码探究(二十二) —— UITextField分类(一)
23. YYKit源码探究(二十三) —— UIView分类(一)
24. YYKit源码探究(二十四) —— UIPasteboard分类(一)
25. YYKit源码探究(二十五) —— UIGestureRecognizer分类(一)
26. YYKit源码探究(二十六) —— UIDevice分类框架及Device Information(一)
27. YYKit源码探究(二十七) —— UIDevice分类之Network Information(二)
28. YYKit源码探究(二十八) —— UIDevice分类之Disk Space(三)
29. YYKit源码探究(二十九) —— UIDevice分类之Memory Information(四)
30. YYKit源码探究(三十) —— UIDevice分类之CPU Information(五)
31. YYKit源码探究(三十一) —— UIControl分类(一)
32. YYKit源码探究(三十二) —— UIColor分类之Create a UIColor Object(一)
33. YYKit源码探究(三十三) —— UIColor分类之Get color's description(二)
34. YYKit源码探究(三十四) —— UIColor分类之Retrieving Color Information(三)
35. YYKit源码探究(三十五) —— UIButton分类之image(一)
36. YYKit源码探究(三十六) —— UIButton分类之background image(二)
37. YYKit源码探究(三十七) —— UIBezierPath分类(一)
38. YYKit源码探究(三十八) —— UIBarButtonItem分类(一)
39. YYKit源码探究(三十九) —— UIApplication分类(一)
40. YYKit源码探究(四十) —— NSTimer分类(一)
41. YYKit源码探究(四十一) —— NSParagraphStyle分类(一)
42. YYKit源码探究(四十二) —— NSObject分类之YYModel(一)

回顾

上一篇主要介绍了NSObject分类YYModel部分,这一篇主要看一下NSObject分类KVO部分。


API

下面我们一起来看一下API文档。

/**
 Observer with block (KVO).
 */
@interface NSObject (YYAddForKVO)

/**
 Registers a block to receive KVO notifications for the specified key-path 
 relative to the receiver.
 
 @discussion The block and block captured objects are retained. Call
 `removeObserverBlocksForKeyPath:` or `removeObserverBlocks` to release.
 
 @param keyPath The key path, relative to the receiver, of the property to 
 observe. This value must not be nil.
 
 @param block   The block to register for KVO notifications.
 */
- (void)addObserverBlockForKeyPath:(NSString*)keyPath block:(void (^)(id _Nonnull obj, _Nullable id oldVal, _Nullable id newVal))block;

/**
 Stops all blocks (associated by `addObserverBlockForKeyPath:block:`) from
 receiving change notifications for the property specified by a given key-path 
 relative to the receiver, and release these blocks.
 
 @param keyPath A key-path, relative to the receiver, for which blocks is 
 registered to receive KVO change notifications.
 */
- (void)removeObserverBlocksForKeyPath:(NSString*)keyPath;

/**
 Stops all blocks (associated by `addObserverBlockForKeyPath:block:`) from
 receiving change notifications, and release these blocks.
 */
- (void)removeObserverBlocks;

@end

下面我们一起详细的看一下这个API文档。

1. - (void)addObserverBlockForKeyPath:(NSString*)keyPath block:(void (^)(id _Nonnull obj, _Nullable id oldVal, _Nullable id newVal))block;

该方法的作用就是根据接受者指定的key - path注册block接收KVO通知。

block和block捕获的对象都被引用,调用 removeObserverBlocksForKeyPath: 或者 removeObserverBlocks进行释放。

  • block:注册KVO通知的block

方法实现

- (void)addObserverBlockForKeyPath:(NSString *)keyPath block:(void (^)(__weak id obj, id oldVal, id newVal))block {
    if (!keyPath || !block) return;
    _YYNSObjectKVOBlockTarget *target = [[_YYNSObjectKVOBlockTarget alloc] initWithBlock:block];
    NSMutableDictionary *dic = [self _yy_allNSObjectObserverBlocks];
    NSMutableArray *arr = dic[keyPath];
    if (!arr) {
        arr = [NSMutableArray new];
        dic[keyPath] = arr;
    }
    [arr addObject:target];
    [self addObserver:target forKeyPath:keyPath options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:NULL];
}

2. - (void)removeObserverBlocksForKeyPath:(NSString*)keyPath;

对于指定的key - path指定的属性,停止所有接收改变的通知的所有block(通过addObserverBlockForKeyPath:block:指派)。

方法实现

- (void)removeObserverBlocksForKeyPath:(NSString *)keyPath {
    if (!keyPath) return;
    NSMutableDictionary *dic = [self _yy_allNSObjectObserverBlocks];
    NSMutableArray *arr = dic[keyPath];
    [arr enumerateObjectsUsingBlock: ^(id obj, NSUInteger idx, BOOL *stop) {
        [self removeObserver:obj forKeyPath:keyPath];
    }];
    
    [dic removeObjectForKey:keyPath];
}

3. - (void)removeObserverBlocks;

停止所有的block(由addObserverBlockForKeyPath:block:指派)接收更改的通知,并释放这些block。

方法实现

- (void)removeObserverBlocks {
    NSMutableDictionary *dic = [self _yy_allNSObjectObserverBlocks];
    [dic enumerateKeysAndObjectsUsingBlock: ^(NSString *key, NSArray *arr, BOOL *stop) {
        [arr enumerateObjectsUsingBlock: ^(id obj, NSUInteger idx, BOOL *stop) {
            [self removeObserver:obj forKeyPath:key];
        }];
    }];
    
    [dic removeAllObjects];
}

后记

本篇主要介绍了NSObject的分类的KVO相关部分,喜欢的给个赞和关注,谢谢~~~

推荐阅读更多精彩内容