Original blog, reproduced please indicate the source
Blog.csdn.net/hello_hwc
KVC and KVO are tools that help us navigate the objective C dynamic feature. KVO is built on the basis of KVC, so do not know KVC's classmates can see my blog. I will not repeat the KVC here.
http://blog.csdn.net/hello_hwc/article/details/43769765
The contents of this article
Definition of KVO
Typical usage scenarios for KVO.
Manual KVO
What time KVO to say the place
the definition of a KVO
KVO provides a mechanism for key-value-observing, which means that the value can be changed by listening for key. Used to listen for state changes between objects. Classes that use KVO follow the protocol, and in fact any class that inherits from NSObject follows this protocol. In Object C, almost all of the classes originate from NSObject
Using KVO is usually divided into three steps
1.1 Subscribe to the keypath you want to listen to
with function
- (void)addObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context
Registration Notice
- Observer: The Observer, the subscriber of the KVO notification. Subscribe to the need to implement
ObserveValueForKeyPath:ofObject:change:context: Method
- KeyPath: Describes the property to be observed, relative to the observer.
- Some of the OPTIONS:KVO properties are configured; There are four options.
- Context: This will be passed to the subscribed function to distinguish the message, so it should be different.
What is included in the options
- Nskeyvalueobservingoptionnew:change dictionary includes changed values
- Nskeyvalueobservingoptionold:change dictionary includes the value before the change
- Nskeyvalueobservingoptioninitial: Trigger KVO notification immediately after registration
- Nskeyvalueobservingoptionprior: Whether the value will be notified before changing it (this key determines whether or not to notify two times before the change)
1.2 Response status changes
Whenever the keypath of a listener changes, it is recalled in this function.
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
- KeyPath: The keypath to be monitored to distinguish between different KVO monitors.
- Object: Observed modified objects (can get modified values via object)
- Change: A dictionary that holds information changes (possibly old values, new values, etc.)
- Context: Contextual, used to distinguish between different kvo listeners.
1.3 Unsubscribe at the right time
Typically two functions are used
- (void)removeObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath context:(void *)context
This is usually the case when you remove it, because when you remove it, you can't read it.
@try { [object removeObserver:self forKeyPath:keyPath]; } @catch (NSException *exception) { NSLog(@"%@",exception); }
Typical usage scenarios for two KVO-synchronization of model and view
Here, you will see an example of a complete kvo. Like the previous KVC, I wrote a similar demo. Clicking Random Changes the user's age, and then the UI is synchronized to show the new and old age.
The implementation process is as follows:
Defines a user class to be used as the model
@interface User : NSObject@property (strong,nonatomicNSString * name;@property (nonatomic) NSUInteger age;@end
Define two static variables, one as KeyPath, and one as context
static NSString * observename = @"age";staticvoid0;
Then register (subscribe) KVO in Viewwillappear, delete KVO in viewwilldisappear
-(void ) Viewwillappear: (bool ) animated{[self .user addobserver:self Forkeypath:observenam E Options:nskeyvalueobservingoptionold | Nskeyvalueobservingoptionnew Context:privatecontext];} -(void ) Viewwilldisappear: (bool ) animated{ Span class= "Hljs-keyword" > @try {[self .user< /span> removeobserver:self Forkeypath:observename]; } @catch (nsexception *exception) {nslog (@ "%@" , exception); }}
When you click on random, age changes
- (IBAction)random:(id)sender { self.user.age = arc4random()%100 +1;}
Then, the model and view are synchronized in the function mentioned above
-(void) Observevalueforkeypath: (NSString*) KeyPath Ofobject: (ID) Object change: (nsdictionary*) Change Context: (void*) context{if(context = = Privatecontext) {if([KeyPath Isequaltostring:observename]) {NSNumber* old = [change Objectforkey:nskeyvaluechangeoldkey];NSNumber* new = [change Objectforkey:nskeyvaluechangenewkey]; Self. Lastvalue. Text= [NSStringstringwithformat:@"%@", old]; Self. NewValue. Text= [NSStringstringwithformat:@"%@", new]; } }}
Three-hand KVO
KVO implementation, is to register the keypath automatically implemented two functions, in the setter, automatically called.
- (void)willChangeValueForKey:(NSString *)key- (void)didChangeValueForKey:(NSString *)key
There may be times when we want to implement manual KVO
This time need to turn off the automatic generation of KVO notifications, and then manual calls, the advantage of manual notification is that you can flexibly add the judgment conditions you want. For example
+(BOOL)automaticallyNotifiesObserversOfAge{ returnNO;}-(void)setAge:(NSUInteger)age{ if22) { return; } [self willChangeValueForKey:@"age"]; _age = age; [self didChangeValueForKey:@"age"];}
Four kvo to mention a few kvo and context
Because the context is often used to differentiate between different kvo, the uniqueness of the context is important. In general, I use a static variable defined in the current. m file.
staticvoid0;
KVO and threading
KVO response and KVO observed value changes are on a thread, so, most of the time, don't mix kvo with multithreading. Unless you can ensure that all observers are thread-safe to handle KVO
Listen for changing values
Changes before and after changes are
id oldValue = change[NSKeyValueChangeOldKey];id newValue = change[NSKeyValueChangeNewKey];
IOS SDK Detailed KVO