=======================================================
Original article, reproduced please indicate the program small Weng @ Blog Park, mail [email protected], welcome you and I in the c/c++/objective-c/machine vision and other fields to start communication!
=======================================================
KVO, all called Key-value observing, is a design pattern in iOS that detects and responds to real-time changes in certain properties of an object. An example of widespread popularity on the internet is the use of KVO to detect changes in stock prices, such as here. This example can be used as an entry point for literacy, but when the scenario is complicated, some of the details still need to be improved, and there are several places where there is a danger of crash. The aim of this paper is to gradually explore a more robust and stable KVO scheme to make up for the shortage of most of the online tutorials.
First, suppose our goal is to monitor the contentoffset of TableView in real time within a uitableviewcontroller, and it is easy to use KVO to achieve:
In the initialization method, add: [_tableview addobserver:self forkeypath:@ "Contentoffset" Options:nskeyvalueobservingoptionnew Context: NIL];
Remove notification in dealloc: [_tableview removeobserver:self forkeypath:@ "Contentoffset" context:nil];
Add the default response callback method:
-(void) Observevalueforkeypath: (NSString *) KeyPath Ofobject: (ID) object Change : (nsdictionary *) Change context: ( void *) context{ [self dosomethingwhencontentoffsetchanges];}
Well, it's the perfect end to the KVO, bye ... A joke, certainly not so simple, such a code is too coarse, when you add multiple KVO in the controller, all callbacks are to go with the above function, it is necessary to trigger the callback function of the source to judge. The judgment is as follows:
-(void) Observevalueforkeypath: (NSString *) KeyPath Ofobject: (ID) object Change : (nsdictionary *) Change context: ( void *) context{ if (object = = _tableview && [keypath isequaltostring:@ "Contentoffset"]) {
[Self dosomethingwhencontentoffsetchanges];
} }
Do you think it's over? The answer is NO! We assume that the current class (Uitableviewcontroller in the example) also has a parent class, and that the parent class has its own bindings for some other kvo? We see that there is only one judgment in the body of the callback function above, and if this if is not true, the trigger of this KVO event will be interrupted. But in fact, if the current class can't capture the KVO, it's probably in his superclass, or super-superclass ... , the above treatment cuts off the chain. The proper way to deal with this should be:
-(void) Observevalueforkeypath: (NSString *) KeyPath Ofobject: (ID) object Change : (nsdictionary *) Change context: ( void *) context{ if (object = = _tableview && [keypath isequaltostring:@ "Contentoffset"]) {
[Self dosomethingwhencontentoffsetchanges];
}
}
Is this the end of it? The answer is still negative. Potential problems may arise in the dealloc of the KVO on the logoff. A flaw in KVO (which is not actually called a flaw, which should be called an attribute) is that when removeobserver the same keypath two times it causes the program to crash, which often occurs when the parent class has a kvo, and the parent removes it once in Dealloc, The subclass is again in the case of a remove. Don't think this is a rare occurrence! It is possible when you encapsulate the framework open source for others or collaborative development with multiple people, and this crash is hard to find. I don't know if you found out, the current code in the context field is nil, that can be used to identify whether the KVO is superclass registered, or self-registered. Not to be continued ...
"Original" iOS Kvo in the process of using traps