123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- //
- // NSObject+YYAddForKVO.m
- // YYKit <https://github.com/ibireme/YYKit>
- //
- // Created by ibireme on 14/10/15.
- // Copyright (c) 2015 ibireme.
- //
- // This source code is licensed under the MIT-style license found in the
- // LICENSE file in the root directory of this source tree.
- //
- #import "NSObject+YYAddForKVO.h"
- #import "YYKitMacro.h"
- #import <objc/objc.h>
- #import <objc/runtime.h>
- YYSYNTH_DUMMY_CLASS(NSObject_YYAddForKVO)
- static const int block_key;
- @interface _YYNSObjectKVOBlockTarget : NSObject
- @property (nonatomic, copy) void (^block)(__weak id obj, id oldVal, id newVal);
- - (id)initWithBlock:(void (^)(__weak id obj, id oldVal, id newVal))block;
- @end
- @implementation _YYNSObjectKVOBlockTarget
- - (id)initWithBlock:(void (^)(__weak id obj, id oldVal, id newVal))block {
- self = [super init];
- if (self) {
- self.block = block;
- }
- return self;
- }
- - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
- if (!self.block) return;
-
- BOOL isPrior = [[change objectForKey:NSKeyValueChangeNotificationIsPriorKey] boolValue];
- if (isPrior) return;
-
- NSKeyValueChange changeKind = [[change objectForKey:NSKeyValueChangeKindKey] integerValue];
- if (changeKind != NSKeyValueChangeSetting) return;
-
- id oldVal = [change objectForKey:NSKeyValueChangeOldKey];
- if (oldVal == [NSNull null]) oldVal = nil;
-
- id newVal = [change objectForKey:NSKeyValueChangeNewKey];
- if (newVal == [NSNull null]) newVal = nil;
-
- self.block(object, oldVal, newVal);
- }
- @end
- @implementation NSObject (YYAddForKVO)
- - (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];
- }
- - (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];
- }
- - (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];
- }
- - (NSMutableDictionary *)_yy_allNSObjectObserverBlocks {
- NSMutableDictionary *targets = objc_getAssociatedObject(self, &block_key);
- if (!targets) {
- targets = [NSMutableDictionary new];
- objc_setAssociatedObject(self, &block_key, targets, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
- }
- return targets;
- }
- @end
|