KVO - NSKeyValueObserving

作者: 居然是村长 | 来源:发表于2016-02-17 00:04 被阅读1904次

    简述:在KVC 的基础上,对属性值的监听。注意KVC的使用。

    一般类的 KVO

    主要分为三个步骤

    • 1 注册监听:
    // 使用UITextField 的 text 属性,示例。
        self.testField = [[UITextField alloc] initWithFrame:CGRectMake(0, 100, CGRectGetWidth(self.view.bounds), 40)];
        self.testField.backgroundColor = [UIColor yellowColor];
        [self.view addSubview:self.testField];
        
    // 需要监听的对象 add 观察者 forkey 观察属性 描述内容
        [self.testField addObserver:self forKeyPath:@"text" options:(NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew) context:@"输入框的 输入控制"];
    
    
    • 此处的options 有4种选择
        NSKeyValueObservingOptionNew = 0x01,  新值
        NSKeyValueObservingOptionOld = 0x02,    旧值
        NSKeyValueObservingOptionInitial = 0x04,  初始化的值? 还请指导。谢谢。
        NSKeyValueObservingOptionPrior = 0x08    2次回调,变化前后。
    
    • 2 使用回调,对监听对象处理
    // 当监听对象key 的属性值,变化时,就会有这个回调。
    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{
        
        if ([keyPath isEqualToString:@"text"]) {
            NSString *oldStr = change[NSKeyValueChangeOldKey];
            NSString *newStr = change[NSKeyValueChangeNewKey];
            
            if (newStr.length == 0) {
                NSLog(@"输入长度不能为0");
            } else if (newStr.length > 8) {
                NSLog(@"输入长度不能大于8");
            } else {
                NSLog(@"cool : %@ 变为 %@",oldStr,newStr);
            }
        }
    }
    
    • 此处获取变化值时,使用的是对于的 key
    FOUNDATION_EXPORT NSString *const NSKeyValueChangeNewKey;
    FOUNDATION_EXPORT NSString *const NSKeyValueChangeOldKey;
    FOUNDATION_EXPORT NSString *const NSKeyValueChangeNotificationIsPriorKey; 是否优先回调key。使用 NSKeyValueObservingOptionPrior 时 ,2次回调,第一次返回值1.
    
    FOUNDATION_EXPORT NSString *const NSKeyValueChangeKindKey;
    FOUNDATION_EXPORT NSString *const NSKeyValueChangeIndexesKey;
    
    • 3 移除监听
    // 注意不要重复移除。注册-移除 一对一。
        [self.testField removeObserver:self forKeyPath:@"text"];
    

    集合类的 KVO

    其他

    typedef NS_ENUM(NSUInteger, NSKeyValueChange) {
        NSKeyValueChangeSetting = 1,
        NSKeyValueChangeInsertion = 2,
        NSKeyValueChangeRemoval = 3,
        NSKeyValueChangeReplacement = 4,
    };
     
    typedef NS_ENUM(NSUInteger, NSKeyValueSetMutationKind) {
        NSKeyValueUnionSetMutation = 1,
        NSKeyValueMinusSetMutation = 2,
        NSKeyValueIntersectSetMutation = 3,
        NSKeyValueSetSetMutation = 4
    };
    
    @interface NSObject(NSKeyValueObserving)
     
    - (void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionary<NSString*, id> *)change context:(nullable void *)context;
    
    @end
    
    @interface NSArray<ObjectType>(NSKeyValueObserverRegistration)
    
    - (void)addObserver:(NSObject *)observer toObjectsAtIndexes:(NSIndexSet *)indexes forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context;
    - (void)removeObserver:(NSObject *)observer fromObjectsAtIndexes:(NSIndexSet *)indexes forKeyPath:(NSString *)keyPath context:(nullable void *)context NS_AVAILABLE(10_7, 5_0);
    - (void)removeObserver:(NSObject *)observer fromObjectsAtIndexes:(NSIndexSet *)indexes forKeyPath:(NSString *)keyPath;
    
    - (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context;
    - (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath context:(nullable void *)context NS_AVAILABLE(10_7, 5_0);
    - (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;
    
    @end
    
    @interface NSOrderedSet<ObjectType>(NSKeyValueObserverRegistration)
    
    - (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context;
    - (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath context:(nullable void *)context NS_AVAILABLE(10_7, 5_0);
    - (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;
    
    @end
    
    @interface NSSet<ObjectType>(NSKeyValueObserverRegistration)
    
    - (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context;
    - (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath context:(nullable void *)context NS_AVAILABLE(10_7, 5_0);
    - (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;
    
    @end
    
    @interface NSObject(NSKeyValueObserverNotification)
    
    - (void)willChangeValueForKey:(NSString *)key;
    - (void)didChangeValueForKey:(NSString *)key;
    - (void)willChange:(NSKeyValueChange)changeKind valuesAtIndexes:(NSIndexSet *)indexes forKey:(NSString *)key;
    - (void)didChange:(NSKeyValueChange)changeKind valuesAtIndexes:(NSIndexSet *)indexes forKey:(NSString *)key;
    - (void)willChangeValueForKey:(NSString *)key withSetMutation:(NSKeyValueSetMutationKind)mutationKind usingObjects:(NSSet *)objects;
    - (void)didChangeValueForKey:(NSString *)key withSetMutation:(NSKeyValueSetMutationKind)mutationKind usingObjects:(NSSet *)objects;
    
    @end
    
    @interface NSObject(NSKeyValueObservingCustomization)
    + (NSSet<NSString *> *)keyPathsForValuesAffectingValueForKey:(NSString *)key NS_AVAILABLE(10_5, 2_0);
    + (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key;
    @property (nullable) void *observationInfo NS_RETURNS_INNER_POINTER;
    
    @end
    

    相关文章

      网友评论

      • feng_dev:我监听的ScrollView 的 contentSize ,change 字典里面key 获取到的是NSConcrete 类型,可以直接 CGSizeValue 获取 CGSize
      • 随风风流:我的QQ是727151289能否加个q,谢谢
      • 随风风流:最近想使用kvo监听某个view的子控件是否全部移除,请问能否给个demo看看如何实现,谢谢。
        居然是村长:@随风风流 KVO不能监听subviews这样的数组。你可以使用通知,告知子控件全部移除。

      本文标题:KVO - NSKeyValueObserving

      本文链接:https://www.haomeiwen.com/subject/kbypkttx.html