简述:在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