Objective-C 的 KVO(二):NSKeyValueObserving.h 代码注释

/*
NSKeyValueObserving.h
Copyright (c) 2003-2019, Apple Inc.
All rights reserved.
*/

#import <Foundation/NSArray.h>
#import <Foundation/NSOrderedSet.h>
#import <Foundation/NSSet.h>
#import <Foundation/NSDictionary.h>

@class NSIndexSet, NSString;

NS_ASSUME_NONNULL_BEGIN

/* 
被观察者给定属性的观察配置选项,包括观察的内容与发送通知的时机
与 -addObserver:forKeyPath:options:context: 和 -addObserver:toObjectsAtIndexes:forKeyPath:options:context: 一起使用
*/
typedef NS_OPTIONS(NSUInteger, NSKeyValueObservingOptions) {
    /* 
	在通知中发送的 change 字典里是否应分别包含 NSKeyValueChangeNewKey 和 NSKeyValueChangeOldKey 的条目
    */
    NSKeyValueObservingOptionNew = 0x01,
    NSKeyValueObservingOptionOld = 0x02,

    /* 
	是否应在注册观察者的方法返回之前,立即向观察者发送一次通知
	
	如果注册观察者的方法指定了 NSKeyValueObservingOptionNew 选项,则通知中的 change 字典里将始终包含一个 NSKeyValueChangeNewKey 条目
	但是通知中的 change 字典里永远不会包含一个 NSKeyValueChangeOldKey 条目(在注册观察者时,被观察的属性的当前值可能是旧的,但是对于刚注册的观察者来说它就是一个新值)
	如果希望在注册观察者时能马上获得一次通知,则可以使用此选项。而不是在注册观察者的同时,显式地调用 -observeValueForKeyPath:ofObject:change:context:
	当此选项与 -addObserver:toObjectsAtIndexes:forKeyPath:options:context: 一起使用时,将会为 要添加观察者的每个索引处的对象发送一次通知
    */
    NSKeyValueObservingOptionInitial API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0)) = 0x04,

    /* 
	是否应在被观察的属性更改之前和更改之后分别向观察者发送单独的通知,而不是只在被观察的属性更改之后向观察者发送一次通知
	
	在被观察的属性更改之前发送的通知中的 change 字典里始终包含一个值为 [NSNumber numberWithBool:YES] 的 NSKeyValueChangeNotificationIsPriorKey 条目
	在被观察的属性更改之前发送的通知中的 change 字典里从不包含 NSKeyValueChangeNewKey 条目
	
	当观察者自身的 KVO 合规性要求其为自身的属性调用一个 -willChange... 并且 该属性的值取决于被观察者的属性的值时,可以使用此选项
	(在这种情况下,简单地调用 -willChange... 以响应被观察的属性更改之后收到的 -observeValueForKeyPath:ofObject:change:context: 消息已为时已晚)
	当指定此选项时,被观察的属性更改之后发送的通知中的 change 字典里将包含与未指定此选项时包含的相同条目,但是由 NSOrderedSets 表示的有序唯一的一对一多关系除外
	
	对于 NSKeyValueChangeInsertion 和 NSKeyValueChangeReplacement 的更改,被观察的属性更改之前的通知中的 change 字典里包含一个 NSKeyValueChangeIndexesKey 条目
	(如果在注册观察者时指定了 NSKeyValueObservingOptionOld 选项,则在 NSKeyValueChangeReplacement 的更改时,被观察的属性更改之前的通知中的 change 字典里包含一个 NSKeyValueChangeOldKey 条目)
	被观察的属性更改之前的通知中的 change 字典里给出了该操作可能会更改的索引和对象。被观察的属性更改之后的通知中的 change 字典里给出了该操作实际上更改的索引和对象
	在 NSKeyValueChangeRemoval 的更改时,使用索引是精确的
    */
    NSKeyValueObservingOptionPrior API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0)) = 0x08
};

/* 
被观察者给定属性的改变类型(即 change 字典中 NSKeyValueChangeKindKey 条目的可能值)
更多的相关信息,请参考 -observeValueForKeyPath:ofObject:change:context: 的注释
*/
typedef NS_ENUM(NSUInteger, NSKeyValueChange) {
    NSKeyValueChangeSetting = 1,		// 对属性进行了设值操作(用于非集合类型和集合类型)
    NSKeyValueChangeInsertion = 2,		// 对属性进行了插入操作(仅用于集合类型)
    NSKeyValueChangeRemoval = 3,		// 对属性进行了移除操作(仅用于集合类型)
    NSKeyValueChangeReplacement = 4,	// 对属性进行了替换操作(仅用于集合类型)
};

/*
被观察者给定集合属性的事件类型 
-willChangeValueForKey:withSetMutation:usingObjects: 和 -didChangeValueForKey:withSetMutation:usingObjects: 中使用的集合事件的可能类型
这些集合事件类型的语义分别对应于 NSMutableSet 的 -unionSet:、-minusSet:、-intersectSet:、-setSet:
*/
typedef NS_ENUM(NSUInteger, NSKeyValueSetMutationKind) {
    NSKeyValueUnionSetMutation = 1,		// 对应于属性的改变类型 NSKeyValueChangeInsertion,	对应于调用方法 -[NSMutableSet unionSet]
    NSKeyValueMinusSetMutation = 2,		// 对应于属性的改变类型 NSKeyValueChangeRemoval,  	对应于调用方法 -[NSMutableSet minusSet]
    NSKeyValueIntersectSetMutation = 3,	// 对应于属性的改变类型 NSKeyValueChangeRemoval,		对应于调用方法 -[NSMutableSet intersectSet]
    NSKeyValueSetSetMutation = 4		// 对应于属性的改变类型 NSKeyValueChangeReplacement,	对应于调用方法 -[NSMutableSet setSet]
};

typedef NSString * NSKeyValueChangeKey NS_STRING_ENUM;
/* 
change 字典中所包含的键
更多的相关信息,请参考 -observeValueForKeyPath:ofObject:change:context: 的注释
NSKeyValueChangeKindKey 				== @"kind"
NSKeyValueChangeNewKey	 				== @"new"
NSKeyValueChangeOldKey 					== @"old"
NSKeyValueChangeIndexesKey 				== @"indexes"
NSKeyValueChangeNotificationIsPriorKey 	== @"notificationIsPrior"
*/
FOUNDATION_EXPORT NSKeyValueChangeKey const NSKeyValueChangeKindKey;
FOUNDATION_EXPORT NSKeyValueChangeKey const NSKeyValueChangeNewKey;
FOUNDATION_EXPORT NSKeyValueChangeKey const NSKeyValueChangeOldKey;
FOUNDATION_EXPORT NSKeyValueChangeKey const NSKeyValueChangeIndexesKey;
FOUNDATION_EXPORT NSKeyValueChangeKey const NSKeyValueChangeNotificationIsPriorKey API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));

@interface NSObject(NSKeyValueObserving)

/* 
如果此消息的接受者已经被注册为给定对象(object)中给定关键路径(keyPath)所指定的属性的观察者
则当该属性的值发生更改时,通过此方法通知观察者(即此消息的接受者,即重写了此方法的对象)

change 字典始终包含一个 NSKeyValueChangeKindKey 条目,其值是包装了 NSKeyValueChange 的 NSNumber 对象(使用 -[NSNumber unsignedIntegerValue])
NSKeyValueChange 的含义取决于键路径所标识的属性类型:
	- 对于任何类型的属性(简单的属性、一对一关系的属性、有序或无序的一对多关系的属性),NSKeyValueChangeSetting 用于标识
			1.被观察者收到了一条 -setValue:forKey: 消息
			2.KVC 兼容对象中给定 key 对应的 set 方法被调用了
			3.-willChangeValueForKey: 与 -didChangeValueForKey: 方法对被调用了
	- 对于有序的一对多关系的属性,NSKeyValueChangeInsertion、NSKeyValueChangeRemoval、NSKeyValueChangeReplacement 用于标识
			1.集合事件的消息已经发送到由 -[object mutableArrayValueForKey:] 所返回的 mutable array
			2.集合事件的消息已经发送到由 -[object mutableOrderedSetValueForKey:] 所返回的 ordered set
			3.KVC 兼容对象(array 或者 ordered set)给定 key 对应的集合事件被调用了
			4.-willChange:valuesAtIndexes:forKey: 与 -didChange:valuesAtIndexes:forKey: 方法对被调用了
	- 对于无序的一对多关系的属性(在 MacOS 10.4 中引入),NSKeyValueChangeInsertion、NSKeyValueChangeRemoval、NSKeyValueChangeReplacement 用于标识
			1.集合事件的消息已经发送到由 -[object mutableSetValueForKey:] 所返回的 mutable set
			2.KVC 兼容对象(set)给定 key 对应的集合事件被调用了
			3.-willChangeValueForKey:withSetMutation:usingObjects: 与 -didChangeValueForKey:withSetMutation:usingObjects: 方法对被调用了

对于任何类型的属性:
如果在注册观察者时指定了 NSKeyValueObservingOptionNew 选项,则 change 字典里会包含一个 NSKeyValueChangeNewKey 条目,这是一个正确的更改,而不是被观察的属性更改之前的通知(NSKeyValueChangeNotificationIsPriorKey)
如果在注册观察者时指定了 NSKeyValueObservingOptionOld 选项,则 change 字典里会包含一个 NSKeyValueChangeOldKey 条目,这是一个正确的更改
有关 change 字典中这些条目对应的值,请参见 NSKeyValueObserverNotification 非正式协议中方法的注释

对于有序的一对多关系的属性
除非它的 NSKeyValueChangeKindKey 是 NSKeyValueChangeSetting 类型
否则它的 change 字典始终包含一个 NSKeyValueChangeIndexesKey 条目,其值为 NSIndexSet 类型的对象,包含 插入、删除、替换 的元素的索引

(在 MacOS 10.5 中引入)如果在注册观察者时指定了 NSKeyValueObservingOptionPrior 选项
则在被观察的属性更改之前发送的通知中的 change 字典里会包含一个 NSKeyValueChangeNotificationIsPriorKey 条目,其值是包装了 YES 的 NSNumber 对象(使用 -[NSNumber boolValue])

这里的 context 参数与在注册观察者时传入的 context 参数是相同的
*/
- (void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionary<NSKeyValueChangeKey, id> *)change context:(nullable void *)context;

@end

@interface NSObject(NSKeyValueObserverRegistration)

/* 
将给定的 observer 注册为或者注销为,方法调用者中给定 keyPath 所标识的属性的观察者
options 参数用于确定观察者收到的通知中所包含的内容,以及通知的发送时间
context 参数用于在通知触发时传递给观察者

开发者应该尽可能使用 -removeObserver:forKeyPath:context: 而不是 -removeObserver:forKeyPath:
因为 -removeObserver:forKeyPath:context: 允许开发者更准确地指定自己的意图
例如:
同一个观察者(observer)多次注册相同的键路径(keyPath),但是每次注册时传递的上下文指针(context)都不同
如果调用 -removeObserver:forKeyPath: 去注销观察者,则开发者必须去猜测要注销哪个上下文指针对应的观察者,并且开发者可能会猜错
*/
- (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 API_AVAILABLE(macos(10.7), ios(5.0), watchos(2.0), tvos(9.0));
- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;

@end

@interface NSArray<ObjectType>(NSKeyValueObserverRegistration)

/* 
将给定的 observer 注册为或者注销为,数组(NSArray、NSMutableArray)中由给定的 indexes 所标识的元素中给定 keyPath 所指定的属性的观察者
options 参数用于确定观察者收到的通知中所包含的内容,以及通知的发送时间
context 参数用于在通知触发时传递给观察者

NSArray(NSKeyValueObserverRegistration) 提供的不仅仅是针对数组元素来说的更方便的方法
调用 NSArray(NSKeyValueObserverRegistration) 的方法可能比重复调用 NSObject(NSKeyValueObserverRegistration) 方法要快得多

开发者应该尽可能使用 -removeObserver:fromObjectsAtIndexes:forKeyPath:context: 而不是 -removeObserver:fromObjectsAtIndexes:forKeyPath:
因为 -removeObserver:fromObjectsAtIndexes:forKeyPath:context: 允许开发者更准确地指定自己的意图
*/
- (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 API_AVAILABLE(macos(10.7), ios(5.0), watchos(2.0), tvos(9.0));
- (void)removeObserver:(NSObject *)observer fromObjectsAtIndexes:(NSIndexSet *)indexes forKeyPath:(NSString *)keyPath;

/* 
不可变数组(NSArray)是不可观察的,因此这些方法在不可变数组(NSArray)上调用时会引发异常
与其单纯地去观察一个数组的属性是否更改,不如去观察数组中所包含的元素的属性是否更改
*/
- (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 API_AVAILABLE(macos(10.7), ios(5.0), watchos(2.0), tvos(9.0));
- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;

@end

@interface NSOrderedSet<ObjectType>(NSKeyValueObserverRegistration)

/* 
不可变有序集合(NSOrderedSets)是不可观察的,因此这些方法在不可变有序集合(NSOrderedSets)上调用时会引发异常
与其单纯地去观察一个不可变有序集合的属性是否更改,不如去观察不可变有序集合中所包含的元素的属性是否更改
*/
- (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 API_AVAILABLE(macos(10.7), ios(5.0), watchos(2.0), tvos(9.0));
- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;

@end

@interface NSSet<ObjectType>(NSKeyValueObserverRegistration)

/*
不可变集合(NSSet)是不可观察的,因此这些方法在不可变集合(NSSet)上调用时会引发异常
与其单纯地去观察一个不可变集合类型的属性是否更改,不如去观察不可变集合中所包含的元素是否更改
*/
- (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 API_AVAILABLE(macos(10.7), ios(5.0), watchos(2.0), tvos(9.0));
- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;

@end

@interface NSObject(NSKeyValueObserverNotification)

/*
给定用于标识(简单的属性、一对一关系的属性、有序或无序的一对多关系的属性)的 key
向该属性的所有观察者发送一个 NSKeyValueChangeSetting 类型的 -observeValueForKeyPath:ofObject:change:context: 通知消息
包括那些在其他对象中注册的,通过键路径(keyPath)监听该属性的观察者

注意:以下两个方法必须始终成对地调用

由于调用以下两个方法而触发的通知中的 change 字典里,会根据注册观察者时使用的选项(options)的不同,而包含不同的条目:
	- 如果存在 NSKeyValueChangeOldKey 条目,则包含调用 -willChangeValueForKey: 时,由 -valueForKey: 返回的值(如果被观察的属性值为 nil,则 -valueForKey: 获取到的返回值为 NSNull 对象)
	- 如果存在 NSKeyValueChangeNewKey 条目,则包含调用 -didChangeValueForKey: 时,由 -valueForKey: 返回的值(如果被观察的属性值为 nil,则 -valueForKey: 获取到的返回值为 NSNull 对象)
*/
- (void)willChangeValueForKey:(NSString *)key;
- (void)didChangeValueForKey:(NSString *)key;

/* 
给定用于标识(有序的一对多关系的属性)的 key
向该属性的所有观察者发送一个 changeKind 类型的 -observeValueForKeyPath:ofObject:change:context: 通知消息
包括那些在其他对象中注册的,通过键路径(keyPath)监听该属性的观察者
参数 changeKind 的类型必须是:NSKeyValueChangeInsertion、NSKeyValueChangeRemoval、NSKeyValueChangeReplacement 其中的一种
参数 indexes 必须是那些要:插入(inserted)、移除(removed)、替换(replaced) 的对象的索引

注意:以下两个方法必须始终成对地调用,并具有相同的调用参数

由于调用以下两个方法而触发的通知中的 change 字典里,会根据注册观察者时使用的选项(options)的不同,而包含不同的条目:
	- 如果存在 NSKeyValueChangeOldKey 条目(仅适用于 NSKeyValueChangeRemoval 和 NSKeyValueChangeReplacement),则包含调用 -willChangeValueForKey:valuesAtIndexes:forKey: 时,由 -valueForKey: 返回的数组(该数组由给定索引 indexes 处的元素组成)
	- 如果存在 NSKeyValueChangeNewKey 条目(仅适用于 NSKeyValueChangeInsertion 和 NSKeyValueChangeReplacement),则包含调用 -didChangeValueForKey:valuesAtIndexes:forKey: 时,由 -valueForKey: 返回的数组(该数组由给定索引 indexes 处的元素组成)
*/
- (void)willChange:(NSKeyValueChange)changeKind valuesAtIndexes:(NSIndexSet *)indexes forKey:(NSString *)key;
- (void)didChange:(NSKeyValueChange)changeKind valuesAtIndexes:(NSIndexSet *)indexes forKey:(NSString *)key;

/* 
给定用于标识(无序的一对多关系的属性)的 key
向该属性的所有观察者发送一个 mutationKind 类型的 -observeValueForKeyPath:ofObject:change:context: 通知消息
包括那些在其他对象中注册的,通过键路径(keyPath)监听该属性的观察者
参数 mutationKind 的类型必须是:NSKeyValueUnionSetMutation、NSKeyValueMinusSetMutation、NSKeyValueIntersectSetMutation、NSKeyValueSetSetMutation 其中的一种,用于调用 NSMutableSet 相应的方法
参数 objects 用于传递给 NSMutableSet 相应的方法

注意:以下两个方法必须始终成对地调用,并具有相同的调用参数

由于调用以下两个方法而触发的通知中的 change 字典里,NSKeyValueChangeKindKey 条目的值取决于传入的参数 mutationKind:
    - NSKeyValueUnionSetMutation 		-> NSKeyValueChangeInsertion
    - NSKeyValueMinusSetMutation 		-> NSKeyValueChangeRemoval
    - NSKeyValueIntersectSetMutation 	-> NSKeyValueChangeRemoval
    - NSKeyValueSetSetMutation 			-> NSKeyValueChangeReplacement

由于调用以下两个方法而触发的通知中的 change 字典里,可能还包含以下可选的条目:
	- 如果存在 NSKeyValueChangeOldKey 条目(仅适用于 NSKeyValueChangeRemoval 和 NSKeyValueChangeReplacement),则包含被删除的元素的集合
	- 如果存在 NSKeyValueChangeNewKey 条目(仅适用于 NSKeyValueChangeInsertion 和 NSKeyValueChangeReplacement),则包含被添加的元素的集合
*/
- (void)willChangeValueForKey:(NSString *)key withSetMutation:(NSKeyValueSetMutationKind)mutationKind usingObjects:(NSSet *)objects;
- (void)didChangeValueForKey:(NSString *)key withSetMutation:(NSKeyValueSetMutationKind)mutationKind usingObjects:(NSSet *)objects;

@end

@interface NSObject(NSKeyValueObservingCustomization)

/* 
返回一个用于标识其他属性的键路径的集合,集合里键路径所标识的属性的值会影响参数 key 所标识的属性的值

当参数 key 所标识的属性的观察者向被观察者注册 KVO 监听时,KVO 本身会自动在被观察者中观察 集合里键路径所标识的其他属性
当集合里键路径所标识的其他属性的值更改时,将向 key 所标识的属性的观察者发送更改的通知

此方法的默认实现会在被观察者所属的类中搜索名称为 +keyPathsForValuesAffecting<Key> 的方法
如果在被观察者所属的类中搜索到名称为 +keyPathsForValuesAffecting<Key> 的方法,则返回 +keyPathsForValuesAffecting<Key> 方法的调用结果。因此 +keyPathsForValuesAffecting<Key> 方法必须与此方法一样返回一个字符串的集合(NSSet<NSString *>*)
如果在被观察者所属的类中搜索不到名称为 +keyPathsForValuesAffecting<Key> 的方法,则为了向后的二进制兼容性,返回根据之前已弃用的 +setKeys:triggerChangeNotificationsForDependentKey: 方法的调用提供的信息计算出的结果

此方法和 KVO 的自动触发,包含了一个依赖机制,开发者可以使用它,而不是为 dependent 和 computed 的属性发送 -willChangeValueForKey: 和 -didChangeValueForKey: 消息

当某个属性的 getter 方法依赖于其他属性的值来计算要返回的值时,可以通过重写此方法来提供被依赖的属性的键路径(keyPath)
为了避免干扰到父类对此方法的重写,在当前类中重写此方法时,通常应该调用 [super keyPathsForValuesAffectingValueForKey:key] 来获取一个 NSSet<NSString *>* 类型的对象,该 NSSet<NSString *>* 类型的对象包含所有由父类产生的键路径(keyPath)

当使用分类将一个需要计算的属性添加到现有类中时,不能真正地重写此方法。因为不应该在分类中重写此方法
在这种情况下,可以在分类中实现一个匹配的 +keyPathsForValuesAffecting<Key> 来利用该机制
*/
+ (NSSet<NSString *> *)keyPathsForValuesAffectingValueForKey:(NSString *)key API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));

/* 
(在 MacOS 10.5 中引入)
如果 KVO 机制可以在被观察者的(参数 key 所标识的)属性,接受到 KVC 消息,或者被 KVC 兼容的方法调用时,自动调用以下方法,则返回 YES:
-willChangeValueForKey: 和 -didChangeValueForKey:
-willChange:valuesAtIndexes:forKey: 和 -didChange:valuesAtIndexes:forKey:
-willChangeValueForKey:withSetMutation:usingObjects: 和 -didChangeValueForKey:withSetMutation:usingObjects: 
否则,返回 NO

此方法的默认实现会在被观察者所属的类中搜索名称为 +automaticallyNotifiesObserversOf<Key> 的方法
如果在被观察者所属的类中搜索到名称为 +automaticallyNotifiesObserversOf<Key> 的方法,则返回 +automaticallyNotifiesObserversOf<Key> 方法的调用结果。因此 +automaticallyNotifiesObserversOf<Key> 方法必须与此方法一样返回一个布尔值(BOOL)
如果在被观察者所属的类中搜索不到名称为 +automaticallyNotifiesObserversOf<Key> 的方法,则返回 YES
*/
+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key;

/* 
获取或返回一个指针,以标识在当前被观察者中注册的所有观察者的相关信息,包括:注册的观察者(observer)、使用的选项(options)、指定的关键路径(keyPath)、传递的上下文(context)
此方法的默认实现会将当前被观察者中所有观察者的相关信息存储在一个全局字典中,并以当前被观察者的指针作为 key 进行编码

为了提高性能,可以用不透明的数据指针覆盖此变量,以达到将自定义的观察者信息存储在当前被观察者中的目的
当使用不透明的数据指针覆盖此变量时,不能对传递进来的不透明的数据指针发送任何 Objective-C 消息,包括 -retain 和 -release
*/
@property (nullable) void *observationInfo NS_RETURNS_INNER_POINTER;

@end

#if TARGET_OS_OSX

@interface NSObject(NSDeprecatedKeyValueObservingCustomization)

/* 
在 MacOS 10.5 中弃用的方法,建议使用 +keyPathsForValuesAffectingValueForKey: 代替
向传入的 keys 数组中任意 key 所标识的属性调用以下方法时,都应该触发 dependentKey 所标识的属性发生更改的通知
-willChangeValueForKey: 和 -didChangeValueForKey:
-willChange:valuesAtIndexes:forKey: 和 -didChange:valuesAtIndexes:forKey:
-willChangeValueForKey:withSetMutation:usingObjects: 和 -didChangeValueForKey:withSetMutation:usingObjects: 
*/
+ (void)setKeys:(NSArray *)keys triggerChangeNotificationsForDependentKey:(NSString *)dependentKey API_DEPRECATED("Use +keyPathsForValuesAffectingValueForKey instead", macos(10.0,10.5), ios(2.0,2.0), watchos(2.0,2.0), tvos(9.0,9.0));

@end 

#endif

NS_ASSUME_NONNULL_END
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值