Key value Observation KVO

Source: Internet
Author: User
Tags notification center

Key-value Observing Programming Guide

1, Register Key-value observing: To achieve this goal, you need:

1) The observed class to the attribute you want to observe must be subject to key-value observing

2) You must register the observed objects of the observed object, using AddObserver:forKeyPath:options:context:.

3) The Observer class must implement ObserveValueForKeyPath:ofObject:change:context:

Important NOTE: Not all classes are subject to KVO for all properties. You have to make sure that the class you have is subject to KVO.

2, register as an observer: Use AddObserver:forKeyPath:options:context:.

Use the option nskeyvalueobservingoptionold To specify the initial object value to be provided to the observer in the Change dictionary .

Use the nskeyvalueobservingoptionnew option to provide a new value through the change dictionary.

To get these two values, you need the bitwise OR of the two option constants.

When you register an object as an observer, you can also provide a context pointer. When ObserveValueForKeyPath:ofObject:change:context is called, the context pointer is provided to the observer. A context pointer can be a C pointer or an object reference. A context pointer can be used as a unique identifier to determine the observed change, or to provide some other data to the observer.

Tip: KVO AddObserver:forKeyPath:options:context: The method does not maintain a strong reference to the observer, the observed object, or the context. You should make sure that you maintain strong references to observations, observations, objects, and contexts, if necessary.

3. Receive change notifications:

When the properties of the object being observed change, the Observer receives a OBSERVEVALUEFORKEYPATH:OFOBJECT:CHANGE:CONTEXT: message. All observers must implement this method.

The Change dictionary entry Nskeyvaluechangekindkey provides information about the types of changes that occur. If the value of the observed object has changed, the Nskeyvaluechangekindkey entry returns nskeyvaluechangesetting. Based on the Observer-registered options, the Nskeyvaluechangeoldkey and Nskeyvaluechangenewkey entries are the values before and after the property changes. If the value is scalar, it is automatically wrapped with Nsvalue and nsnumber.

If the property being observed is a multivalued attribute, the Nskeyvaluechangekindkey entry still indicates that the object is being added, removed, or replaced by returning nskeyvaluechangeinsertion, Nskeyvaluechangeremoval or nskeyvaluechangereplacement to identify.

The entry Nskeyvaluechangeindexeskey of the Change dictionary is a Nsindexset object that specifies the indexes of the changes. If Nskeyvalueobservingoptionvew or nskeyvalueobservingoptionold is registered, The Nskeyvaluechangeoldkey and nskeyvaluechangenewkey entrances are arrays values that contain the changes before the related objects and the changed values.

Listing 2 Implementation of ObserveValueForKeyPath:ofObject:change:context:

-(void) Observevalueforkeypath: (NSString *) keypath

Ofobject: (ID) object

Change: (nsdictionary *) change

Context: (void *) Context {

if ([KeyPath isequal:@ "Openingbalance"]) {

[Openingbalanceinspectorfield Setobjectvalue:

[Change Objectforkey:nskeyvaluechangenewkey]];

}

/*

Be sure to call the superclass ' s implementation *if it implements it*.

NSObject does not implement the method.

*/

[Super Observevalueforkeypath:keypath

Ofobject:object

Change:change

Context:context];

}

4. To remove the Observer object:

Removeobserver:forkeypath: The message is given to the observed object. Example:

[Observedobject removeobserver:inspector forkeypath:@ "Openingbalance"];

If the context is an object, you must keep a strong reference to it until you remove the observer.

5,KVO Compliance:

1) class must be compliant with KVC

2) class to issue KVO change notifications for properties

3) The keys to be based are properly registered.

There are two mechanisms to ensure that change notifications are emitted. NSObject automatically supports and is used by default for all classes that follow the KVC property.

When notifications are emitted, manual change notifications provide additional control and require additional code. You can control the automatic notification properties, subclass and implement Automaticallynotifiesobserversforkey: methods.

6, Automatic change notification:

For example, the following method raises a KVO change notification issue.

Call access Method

[Account setname:@ "Savings"];

Use Setvalue:forkey:.

[Account setvalue:@ "Savings" forkey:@ "name"];

Using key path, where ' account ' is a kvc-compliant the property of ' document '.

[Document Setvalue:@ "Savings" forkeypath:@ "Account.name"];

Use mutablearrayvalueforkey:to retrieve a relationship proxy object.

Transaction *newtransaction = < #Create a new Transaction for the account#>;

Nsmutablearray *transactions = [Account mutablearrayvalueforkey:@ "transactions"];

[Transactions addobject:newtransaction];

7, Manual change notification:

A class that implements a manual change notification must implement the Automaticallynotifiesobserversforkey: method. It may use both automatic notifications and manual notifications. For the property whose manual notification is to be made, he should set it to No in the Automaticallynotifiesobserversforkey: method. As shown below:

Listing 2 Example implementation of Automaticallynotifiesobserversforkey:

+ (BOOL) Automaticallynotifiesobserversforkey: (NSString *) Thekey {

BOOL automatic = NO;

if ([Thekey isequaltostring:@ "Openingbalance"]) {

automatic = NO;

}

else {

automatic = [Super Automaticallynotifiesobserversforkey:thekey];

}

return automatic;

}

To implement a manual notification, before the change you call Willchangevalueforkey:, after the change, call Didchangevalueforkey:.

Listing 3 Example Accessor method implementing manual notification

-(void) Setopeningbalance: (double) Thebalance {

[Self willchangevalueforkey:@ "openingbalance"];

_openingbalance = thebalance;

[Self didchangevalueforkey:@ "openingbalance"];

}

You can minimize the sending of unnecessary notifications by first checking to see if the values have changed.

Listing 4 Testing the value for change before providing notification

-(void) Setopeningbalance: (double) Thebalance {

if (thebalance! = _openingbalance) {

[Self willchangevalueforkey:@ "openingbalance"];

_openingbalance = thebalance;

[Self didchangevalueforkey:@ "openingbalance"];

}

}

If a single operation causes multiple key values to change, you must nest (Nest) change notifications, like this:

Listing 5 Nesting change notifications for multiple keys

-(void) Setopeningbalance: (double) Thebalance {

[Self willchangevalueforkey:@ "openingbalance"];

[Self willchangevalueforkey:@ "itemchanged"];

_openingbalance = thebalance;

_itemchanged = _itemchanged+1;

[Self didchangevalueforkey:@ "itemchanged"];

[Self didchangevalueforkey:@ "openingbalance"];

}

For an ordered multivalued association, in addition to specifying the changed key, you also need to specify the type of change and the associated indexes. The type of change is a nskeyvaluechange to identify nskeyvaluechangeinsertion, Nskeyvaluechangeremoval, or nskeyvaluechangereplacement. The affected indexes are passed through Nsindexset.

Listing 6 Implementation of manual observer notification in a To-many relationship

-(void) Removetransactionsatindexes: (Nsindexset *) Indexes {

[Self Willchange:nskeyvaluechangeremoval

Valuesatindexes:indexes forkey:@ "Transactions"];

Remove the transaction objects at the specified indexes.

[Self Didchange:nskeyvaluechangeremoval

Valuesatindexes:indexes forkey:@ "Transactions"];

}

8, Register Dependent Keys:

There are times when a property's value is based on one or more properties of another object. If the value of one property changes, then the derived property should also be marked as changed. How will you make sure that when these properties change, the properties that are based on it are published via KVO notification?

1) for a single association:

You need to overload the Keypathsforvaluesaffectingvalueforkey: or implement an appropriate method

For example, a person's full name is based on first name and last name. A method returns its full name:

-(NSString *) FullName {

return [NSString stringwithformat:@ "%@%@", FirstName, LastName];

}

An application observes the FullName property and must be notified when changes to the FirstName and LastName properties occur.

One workaround is to overload Keypathsforvaluesaffectingvalueforkey: To specify that the FullName property is based on LastName and FirstName. As shown below:

+ (Nsset *) Keypathsforvaluesaffectingvalueforkey: (NSString *) Key {

Nsset *keypaths = [Super Keypathsforvaluesaffectingvalueforkey:key];

if ([Key isequaltostring:@ "FullName"]) {

Nsarray *affectingkeys = @[@ "LastName", @ "FirstName"];

keypaths = [Keypaths Setbyaddingobjectsfromarray:affectingkeys];

}

return keypaths;

}

Your overload needs to call the Super method and return a set.

You can also get the same result by implementing a class method Keypathsforvaluesaffecting<key>,<key> is the name of the property, the first letter is uppercase, as follows:

+ (Nsset *) Keypathsforvaluesaffectingfullname {

return [Nsset setwithobjects:@ "LastName", @ "FirstName", nil];

}

When you use the category to add a computed property to an existing class, you cannot overload the Keypathsforvaluesaffectingvalueforkey: Method because you cannot overload the method in the category. In this case, a conforming Keypathsforvaluesaffecting<key> class method is implemented to obtain the benefits of this mechanism.

2) for multi-value associations:

Keypathsforvaluesaffectingvalueforkey: Method does not support key-paths that contain multivalued associations. For example, suppose you have a Department object, a lot of staff (employees), and the employee has a pay attribute. You might want the Department object to have a Totalsalary attribute, based on the salary of all employees. You cannot keypathsforvaluesaffectingtotalsalary and return to Employees.salary.

Here are two possible workarounds:

A) Use KVO to register the observer of its parent (in this case, the department) as the related property of all its children (here are staff) objects. You must add or remove the parent object as an observer when you add or remove child objects. In its ObserveValueForKeyPath:ofObject:change:context: method, you need to update the corresponding value to respond to the notification and to issue a notification. As shown below:

-(void) Observevalueforkeypath: (NSString *) KeyPath Ofobject: (ID) object change: (nsdictionary *) Change context: (void *) Context {

if (context = = Totalsalarycontext) {

[Self updatetotalsalary];

}

Else

Deal with other observations and/or invoke super ...

}

-(void) Updatetotalsalary {

[Self settotalsalary:[self valueforkeypath:@ "[email protected]"];

}

-(void) Settotalsalary: (NSNumber *) newtotalsalary {

if (totalsalary! = newtotalsalary) {

[Self willchangevalueforkey:@ "totalsalary"];

_totalsalary = newtotalsalary;

[Self didchangevalueforkey:@ "totalsalary"];

}

}

-(NSNumber *) totalsalary {

return _totalsalary;

}

b) If you are using core Data, you can register the parent object to application's notification Center as the context watcher for its managed objects. The parent object should respond to the corresponding change notification published by the child object.

Original URL: http://supershll.blog.163.com/blog/static/37070436201263111521695/

Key value Observation KVO

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.