"Basic Concepts"
Key-value observation is a notification mechanism that enables an object to obtain changes to specific properties of other objects. The binding technique of the controller layer is to obtain the change notification of the model layer and the controller layer by heavily relying on the key value. For applications that do not rely on the Controller layer class, key-value observations provide a simplified way to implement the inspector and update the user interface face value.
Unlike Nsnotification, key-value observations do not have the so-called central object to provide change notification to all observers. Instead, when a change occurs, the notification is sent directly to the object in the observation state. NSObject provides this basis for the implementation of key-value observations, and you hardly need to rewrite the method.
You can look at arbitrary object attributes, including simple attributes, to one or to multiple relationships. The observer of a many-to-many relationship will be informed of the type of change-that is, any object that changes. Key-value observations provide automatic observation compatibility for all objects. You can filter notifications by disabling automatic observation notifications and implementing manual notifications.
"Registered observer"
In order to properly receive notification of changes to a property, the observer must first send a addObserver:forKeyPath:options:context: message to the observed object, which transmits the critical path of the observed object and the attribute to be observed in order to register with it. The option parameter specifies the information that is provided to the observer when the change notification is sent. You can use the Nskeyvalueobservingoptionold option to provide an initial object value to the observer in the form of an item in the Change dictionary. Specify the nskeyvalueobservingoptionnew option to add a new value as an item to the change dictionary. You can use a bitwise "|" These two constants to specify that both types of values are accepted.
Below I take a few examples to bring you to realize the KVO notification mechanism:
"Instance one" to observe the properties of the underlying data type
(1) I built an OC based iOS project, dragging a button in the storyboard and using Ibaction implementation button clicks in Viewcontroller.
(2) Declare an attribute of type int in the VIEWCONTROLLER.M file:
@interface Viewcontroller ()
@property (assign,nonatomic) int count;
@end
(3) Then implement an initialization method to initialize the value of Count:
-(instancetype) init
{
self = [super init];
if (self) {
self.count = 1;
}
return self;
}
(4) In the button click Response to do the self operation, I will listen to click on the button count values change this event:
-(Ibaction) clicked: (ID) sender {
self.count++;
}
(5) Registering observation events in the Viewdidload method:
-(void) viewdidload {
[super viewdidload];
[Self addobserver:self forkeypath:@ ' count ' options:nskeyvalueobservingoptionnew | Nskeyvalueobservingoptionold Context:nil];
}
(6) Finally rewrite a method Observevalueforkeypath as follows:
-(void) Observevalueforkeypath: (NSString *) KeyPath Ofobject: (ID) object change: (nsdictionary<nsstring *,id> *) Change context: (void *) context{
if ([KeyPath isequal: @ ' count ']) {
NSLog (@ "Count =%d", self.count);
}
}
(7) The output is as follows: Whenever I click on a button, the event will call the registration method.
。
"Instance two" to observe objects
(1) On the basis of the above, create a new other class, declare a variable in h header file:
#import <Foundation/Foundation.h>
@interface other:nsobject
@property (assign,nonatomic) int number;
@end
(2) Implement the initialization method in the OTHER.M file to initialize the number variable:
#import "Other.h"
@implementation other
-(instancetype) init
{
self = [super init];
if (self) {
self.number = +;
}
return self;
}
@end
(3) implemented as follows in VIEWCONTROLLER.M:
#import "ViewController.h"
#import "Other.h"
@interface viewcontroller ()
@property (strong,nonatomic) Other *other;
@end
@implementation Viewcontroller
-(void) viewdidload {
[super viewdidload];
Monitor other classes;
self.other = [[Other alloc] init];
[Self.other addobserver:self forkeypath:@ "number" options:nskeyvalueobservingoptionnew | Nskeyvalueobservingoptionold Context:nil];
}
-(Ibaction) clicked: (ID) sender {
_other.number++;
}
-(void) Observevalueforkeypath: (NSString *) KeyPath Ofobject: (ID) object change: (nsdictionary<nsstring *,id> *) Change context: (void *) context{
//I assume that the output is divisible by 2, noting that I am using KeyPath to match;
if ([KeyPath isequal: @ "number") && _other.number% 2 = 0) {
NSLog (@ "Other.number =%d", _other.number);
}
@end
(4) The output results are as follows:
。
"Instance three" to observe multiple objects at the same time
On the basis of "instance one" and "instance two" above, I observe two variables at the same time, the implementation in other classes is unchanged, and the implementation in VIEWCONTROLLER.M is as follows:
#import "ViewController.h" #import "Other.h" @interface Viewcontroller () @property (assign,nonatomic) int count;
@property (strong,nonatomic) other *other;
@end @implementation Viewcontroller-(void) viewdidload {[Super viewdidload]; [Self addobserver:self forkeypath:@ ' count ' options:nskeyvalueobservingoptionnew |
Nskeyvalueobservingoptionold Context:nil];
Monitor other classes; self.other = [[Other alloc] init]; [Self.other addobserver:self forkeypath:@ "number" options:nskeyvalueobservingoptionnew |
Nskeyvalueobservingoptionold Context:nil];
}-(Instancetype) init {self = [super init];
if (self) {self.count = 1;
return self;
}-(Ibaction) clicked: (ID) sender {_other.number++;
self.count++; }-(void) Observevalueforkeypath: (NSString *) KeyPath Ofobject: (ID) object change: (nsdictionary<nsstring *,id> *)
Change context: (void *) context{if (object = = Self.other) {NSLog (@ "number =%d", _other.number); } else if (object = = Self && self.count% 2 = 0) {NSLog (@ "Count =%d", self.count); }} @end
The output results are as follows:
。
"Instance four" using change parameters to observe parameter changes in real time
The implementation in VIEWCONTROLLER.M is as follows:
#import "ViewController.h"
#import "Other.h"
@interface viewcontroller ()
@property (assign,nonatomic) int count;
@property (strong,nonatomic) other *other;
@end
@implementation Viewcontroller
-(void) viewdidload {
[super viewdidload];
[Self addobserver:self forkeypath:@ ' count ' options:nskeyvalueobservingoptionnew | Nskeyvalueobservingoptionold Context:nil];
}
-(instancetype) init
{
self = [super init];
if (self) {
self.count = 1;
}
return self;
}
-(Ibaction) clicked: (ID) sender {
_other.number++;
self.count++;
}
-(void) Observevalueforkeypath: (NSString *) KeyPath Ofobject: (ID) object change: (nsdictionary<nsstring *,id> *) Change context: (void *) context{
//The observation variable is printed here;
NSLog (@ "%@", change);
}
@end
The output results are as follows:
.
GitHub home: https://github.com/chenyufeng1991. You are welcome to visit.