KVO---NSKeyValueObserving

The NSKeyValueObserving (KVO) informal protocol[非正式协议] defines a mechanism(机制) that allows objects to be notified of changes to the specified properties of other objects.

You can observe any object properties including simple attributes, to-one relationships, and to-many relationships. Observers of to-many relationships are informed of the type of change made — as well as which objects are involved in the change.

NSObject provides an implementation of the NSKeyValueObserving protocol that provides an automatic observing capability for all objects. You can further refine notifications by disabling automatic observer notifications and implementing manual notifications using the methods in this protocol.

NOTE----Key-value observing is not available for Java applications.

Change notification

- observeValueForKeyPath:ofObject:change:context:

This message is sent to the receiver when the value at the specified key path relative to the given object has changed.

DeclarationSWIFT

func observeValueForKeyPath(_ keyPath: String?,                

                        ofObject object: AnyObject?,  

                        change change: [String : AnyObject]?,      

                     context context: UnsafeMutablePointer)

OBJECTIVE-C

- (void)observeValueForKeyPath:(NSString *)keyPath        

                                    ofObject:(id)object

                                      change:(NSDictionary*)change

                                        context:(void *)context

Parameters

keyPath   The key path, relative to object, to the value that has changed.

object     The source object of the key path keyPath.

change   A dictionary that describes the changes that have been made to the value of the property at the key path keyPath relative to object. Entries are described in Change Dictionary Keys.

context   The value that was provided when the receiver was registered to receive key-value observation notifications.

Discussion

The receiver must be registered as an observer for the specified keyPath and object.


Registering for observation

- addObserver:forKeyPath:options:context:

Registers anObserver to receive KVO notifications for the specified key-path relative to the receiver.

DeclarationSWIFT

func addObserver(_ observer: NSObject,

              forKeyPath keyPath: String,  

                   options options: NSKeyValueObservingOptions,  

                   context context: UnsafeMutablePointer)

OBJECTIVE-C

- (void)addObserver:(NSObject *)anObserver

              forKeyPath:(NSString *)keyPath

                   options:(NSKeyValueObservingOptions)options

                   context:(void *)context

Parameters

anObserver    The object to register for KVO notifications. The observer must implement the key-value observing method observeValueForKeyPath:ofObject:change:context:.

keyPath The key path, relative to the receiver, of the property to observe. This value must not be nil.

options  A combination of the NSKeyValueObservingOptions values that specifies what is included in observation notifications. For possible values, see NSKeyValueObservingOptions.

context  Arbitrary data that is passed to anObserver in observeValueForKeyPath:ofObject:change:context:.

Discussion

Neither the receiver, nor anObserver, are retained. An object that calls this method must also call either the removeObserver:forKeyPath: or removeObserver:forKeyPath:context: method when participating in KVO.

- removeObserver:forKeyPath:

Stops a given object from receiving change notifications for the property specified by a given key-path relative to the receiver.

Declaration

SWIFT

func removeObserver(_ observer: NSObject,

                    forKeyPath keyPath: String)

OBJECTIVE-C

- (void)removeObserver:(NSObject *)anObserver

                   forKeyPath:(NSString *)keyPath

Parameters

anObserver   The object to remove as an observer.

keyPath     A key-path, relative to the receiver, for which anObserver is registered to receive KVO change notifications.

Discussion

It is an error to call removeObserver:forKeyPath: if the object has not been registered as an observer.

Be sure to invoke this method (or removeObserver:forKeyPath:context:) before any object specified in addObserver:forKeyPath:options:context: is deallocated.


- removeObserver:forKeyPath:context:

Stops a given object from receiving change notifications for the property specified by a given key-path relative to the receiver and a context.

DeclarationSWIFT

func removeObserver(_ observer: NSObject,

                    forKeyPath keyPath: String,

                         context context: UnsafeMutablePointer)

OBJECTIVE-C

- (void)removeObserver:(NSObject *)observer

                    forKeyPath:(NSString *)keyPath

                        context:(void *)context

Parameters

observer     The object to remove as an observer.

keyPath      A key-path, relative to the receiver, for which anObserver is registered to receive KVO change notifications.

context     Arbitrary data that more specifically identifies the observer to be removed.

Discussion

Examining the value in context you are able to determine precisely which addObserver:forKeyPath:options:context: invocation was used to create the observation relationship(观察关系,监听关系). When the same observer is registered for the same key-path multiple times, but with different context pointers, an application can determine specifically which object to stop observing. It is an error to call removeObserver:forKeyPath:context: if the object has not been registered as an observer.

Be sure to invoke this method (or removeObserver:forKeyPath:) before any object specified in addObserver:forKeyPath:options:context: is deallocated.


Notifying observers of changes(通知 观察者 的变化)

- willChangeValueForKey:

Invoked(唤起) to inform(通知) the receiver that the value of a given property is about to change.

Declaration

SWIFT

func willChangeValueForKey(_ key: String)

OBJECTIVE-C

- (void)willChangeValueForKey:(NSString *)key

Parameters

key   The name of the property that will change.

Discussion

You should invoke this method when implementing key-value observer compliance manually.

The change type of this method is NSKeyValueChangeSetting.

IMPORTANT

After the values have been changed, a corresponding didChangeValueForKey: must be invoked with the same parameter.

Special Considerations

You should not override this method in subclasses.


See Also

– didChangeValueForKey:

– willChange:valuesAtIndexes:forKey:

- didChangeValueForKey:

Invoked to inform the receiver that the value of a given property has changed.

Declaration

SWIFT

func didChangeValueForKey(_ key: String)

OBJECTIVE-C

- (void)didChangeValueForKey:(NSString *)key

Parameters

key     The name of the property that changed.

Discussion

You should invoke this method when implementing key-value observer compliance manually.

Special Considerations

You should not override this method in subclasses.

See Also

– willChangeValueForKey:

– didChange:valuesAtIndexes:forKey:

- willChange:valuesAtIndexes:forKey:

Invoked to inform the receiver that the specified change is about to be executed at given indexes for a specified ordered to-many relationship.

Declaration

SWIFT

func willChange(_ changeKind: NSKeyValueChange,

        valuesAtIndexes indexes: NSIndexSet,

                             forKey key: String)

OBJECTIVE-C

- (void)willChange:(NSKeyValueChange)change

   valuesAtIndexes:(NSIndexSet *)indexes

                  forKey:(NSString *)key

Parameters

change    The type of change that is about to be made.

indexes     The indexes of the to-many relationship that will be affected by the change.

key    The name of a property that is an ordered to-many relationship.

Discussion

You should invoke this method when implementing key-value-observing compliance manually.

IMPORTANT

After the values have been changed, a corresponding didChange:valuesAtIndexes:forKey: must be invoked with the same parameters.

Special Considerations

You should not override this method in subclasses.


See Also

– didChange:valuesAtIndexes:forKey:

– willChangeValueForKey:

- didChange:valuesAtIndexes:forKey:

Invoked to inform the receiver that the specified change has occurred on the indexes for a specified ordered to-many relationship.

Declaration

SWIFT

func didChange(_ changeKind: NSKeyValueChange,

       valuesAtIndexes indexes: NSIndexSet,

                             forKey key: String)

OBJECTIVE-C

- (void)didChange:(NSKeyValueChange)change

   valuesAtIndexes:(NSIndexSet *)indexes

                  forKey:(NSString *)key

Parameters

change     The type of change that was made.

indexes    The indexes of the to-many relationship that were affected by the change.

key   The name of a property that is an ordered to-many relationship.

Discussion

You should invoke this method when implementing key-value-observing compliance manually.

Special Considerations

You should not override this method in subclasses.


See Also

– willChange:valuesAtIndexes:forKey:

– didChangeValueForKey:

- willChangeValueForKey:withSetMutation:usingObjects:

Invoked to inform the receiver that the specified change is about to be made to a specified unordered to-many relationship.

DeclarationSWIFT

func willChangeValueForKey(_ key: String,

      withSetMutation mutationKind: NSKeyValueSetMutationKind,                                usingObjects objects: Set)

OBJECTIVE-C

- (void)willChangeValueForKey:(NSString *)key

                      withSetMutation:(NSKeyValueSetMutationKind)mutationKind

                          usingObjects:(NSSet *)objects

Parameters

key    The name of a property that is an unordered to-many relationship

mutationKind     The type of change that will be made.

objects    The objects that are involved in the change (see NSKeyValueSetMutationKind).

Discussion

You invoke this method when implementing key-value observer compliance manually.

IMPORTANT

After the values have been changed, a corresponding didChangeValueForKey:withSetMutation:usingObjects: must be invoked with the same parameters.

Special Considerations

You should not override this method in subclasses.

See Also

– didChangeValueForKey:withSetMutation:usingObjects:

- didChangeValueForKey:withSetMutation:usingObjects:

Invoked to inform the receiver that the specified change was made to a specified unordered to-many relationship.

DeclarationSWIFT

func didChangeValueForKey(_ key: String,        

     withSetMutation mutationKind: NSKeyValueSetMutationKind,                             usingObjects objects: Set)

OBJECTIVE-C

- (void)didChangeValueForKey:(NSString *)key

                     withSetMutation:(NSKeyValueSetMutationKind)mutationKind

                         usingObjects:(NSSet *)objects

Parameters

key    The name of a property that is an unordered to-many relationship

mutationKind    The type of change that was made.

objects   The objects that were involved in the change (see NSKeyValueSetMutationKind).

Discussion

You invoke this method when implementing key-value observer compliance manually.

Special Considerations

You should not override this method in subclasses.


Observing customization----自定义观察机制

+ automaticallyNotifiesObserversForKey:

Returns a Boolean value that indicates whether the receiver supports automatic key-value observation for the given key.

DeclarationSWIFT

class func automaticallyNotifiesObserversForKey(_ key: String) -> Bool

OBJECTIVE-C

+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)keyReturn ValueYES if the key-value observing machinery should automatically invoke willChangeValueForKey:/didChangeValueForKey: and willChange:valuesAtIndexes:forKey:/didChange:valuesAtIndexes:forKey: whenever instances of the class receive key-value coding messages for the key, or mutating key-value-coding-compliant methods for the key are invoked; otherwise NO.

Discussion

The default implementation returns YES. Starting in OS X 10.5, the default implementation of this method searches the receiving class for a method whose name matches the pattern

+automaticallyNotifiesObserversOf, and returns the result of invoking that method if it is found. Any found methods must return BOOL. If no such method is found YES is returned.

+ keyPathsForValuesAffectingValueForKey:

Returns a set of key paths for properties whose values affect the value of the specified key.

DeclarationSWIFT

class func keyPathsForValuesAffectingValueForKey(_ key: String) -> Set

OBJECTIVE-C

+ (NSSet*)keyPathsForValuesAffectingValueForKey:(NSString *)keyParameterskey

The key whose value is affected by the key paths.Return ValueDiscussionWhen an observer for the key is registered with an instance of the receiving class, key-value observing itself automatically observes all of the key paths for the same instance, and sends change notifications for the key to the observer when the value for any of those key paths changes.The default implementation of this method searches the receiving class for a method whose name matches the pattern +keyPathsForValuesAffecting, and returns the result of invoking that method if it is found. Any such method must return an NSSet. If no such method is found, an NSSet that is computed from information provided by previous invocations of the now-deprecated setKeys:triggerChangeNotificationsForDependentKey: method is returned, for backward binary compatibility.You can override this method when the getter method of one of your properties computes a value to return using the values of other properties, including those that are located by key paths. Your override should typically invoke super and return a set that includes any members in the set that result from doing that (so as not to interfere with overrides of this method in superclasses).

NOTE

You must not override this method when you add a computed property to an existing class using a category, overriding methods in categories is unsupported. In that case, implement a matching +keyPathsForValuesAffectingto take advantage of this mechanism.

Availability

Available in iOS 2.0 and later.

- observationInfo

Sets the observation info for the receiver.

DeclarationSWIFT

var observationInfo: UnsafeMutablePointer

OBJECTIVE-C

@property void *observationInfo

Parameters

observationInfo    The observation info for the receiver.

Discussion

The observationInfo is a pointer that identifies information about all of the observers that are registered with the receiver. The default implementation of this method stores observationInfo in a global dictionary keyed by the receiver’s pointers.

For improved performance, this method and observationInfo can be overridden to store the opaque data pointer in an instance variable. Classes that override this method must not attempt to send Objective-C messages to observationInfo, including retain and release.

推荐阅读更多精彩内容