How iOS Kvo is implemented

Source: Internet
Author: User

First of all, let us introduce the use of KVO: When a property of an object changes, we need to make corresponding processing events. For example, we customize the drop-down refresh, then how we know the user to do the drop-down refresh data operation, we can listen to the control of the frame, when the user drop the control, the control will modify the Frame.y property, we use KVO to listen to this property. When the Y value of this property is in a range, we think it is a pull-down refresh operation. We can go to the data request. Because there are so many third-party frameworks that are now being refreshed, few people are concerned with the implementation of the pull-down refresh. Another example, we often use the network request of the third-party AFN, its internal monitoring network download progress is also through the KVO implementation. Without proof, let's see the code.

Fractioncompleted is the Self.downloadprogress object that represents the download progress property

Wait a minute. So the use of KVO is still more. So, let's see what the KVO implementation principle looks like and how to implement the monitoring of the properties.

Let me introduce the official answer: When an object of a class is observed at one time, a derived class (subclass) of the class is created dynamically at run time, in which the derived class overrides the setter method of the observed property, and the derived classes implement a true notification mechanism in the overridden setter method. The derived class overrides the class method to deceive the external caller that it is the first listener. The system then points the ISA pointer of the object to the newly-born derived class, so that the object becomes an object of that derived class, so that the call to the setter on that object invokes the overridden setter, activating the key-value notification mechanism. In addition, derived classes override the Dealloc method to free resources.

I do not know if you read this passage, the mind is still awake. Here's a sentence to explain:

Create a person class, define an age property, and then we listen for the Age property

@interface Person:nsobject @property (nonatomic, assign) int age; @end

@implementation Viewcontroller {person    *_p;} -(void) viewdidload {    [super viewdidload];        Create Person object    _p = [[Person alloc] init];        Add a listener to the age property of the person object    [_p addobserver:self forkeypath:@ "age" options:nskeyvalueobservingoptionnew Context:nil] ;        Modify the Age property of P    _p.age = ten;    } Kvo callback method,-(void) Observevalueforkeypath: (NSString *) KeyPath Ofobject: (ID) object change: (nsdictionary< nskeyvaluechangekey,id> *) Change context: (void *) Context {    NSLog (@ "%@ object's%@ attribute changed%@", Object,keypath,change);} When the controller is destroyed, remove kvo-(void) dealloc {    [_p removeobserver:self forkeypath:@ ' age '];}

This time, it will print out

This is the step used by KVO.

Next, let's take a look at this piece of code.

1. Create an instance object of the person class P

2. Add a key-value listener to the age property of the object P

3. Modify the Age property of the object P

4. Implementing the Kvo callback method

5. Remove KVO Monitor

From the output, we can normally hear the change of the Age property of P.

According to the official explanation: When an object of a class is observed at one time, a derived class (subclass) of the class is created dynamically at run time by the system

So, let's see what kind of sub-class this is:

To see where the breakpoint breaks, I have not kvo the object p when I print this result. Some people will ask, Objc_getclass () is what, OBJC beginning function is basically the function inside the runtime. So this is the type of dynamic get object.

When the age property of the object P is listened to, the true type of the object P becomes Nskvonotifying_person. So why is PO _p still a <Person> type, which is that ' a derived class overrides the class method to deceive the outside caller that it is the first listener. '

Next, let's take a step further. Now that we have this sub-class, we again this sub-class setter method inside the hands and feet, is it possible to start KVO callback, will output the results of monitoring? So how do we get the P object of the person type to execute the setter method inside the Nskvonotifying_person class? The system points the ISA pointer of this object (P) to the newly-born derived class (Nskvonotifying_person). How much do you know about the ISA pointer? All OC classes have a common attribute, which is ISA. There is a picture of the truth:

So. What is this ISA pointer for?

ISA: Is a class-type pointer. Each instance object has a pointer to Isa, which points to the class of the object, and the class also has a pointer to Isa, pointing to Meteclass (the Meta Class). The Meta class holds a list of class methods. When a class method is called, the implementation of the class method is looked up first from itself, and if not, the meta-class looks for the method to his parent class. Also note that the meta-class (Meteclass) is also a class, and it is also an object. The Meta class also has an Isa pointer, and its ISA pointer eventually points to a root class (root meteclass). The ISA pointer to the root class points to itself, which forms a closed inner loop.

So as soon as we modify the class that the ISA pointer points to. Will go to the class it points to find setter method, that is, will go to (Nskvonotifying_person) class inside to find setter method, this time we then Nskvonotifying_person class setter method inside to do something, Thus triggering the KVO callback method, which is

-(void) Observevalueforkeypath: (NSString *) KeyPath Ofobject: (ID) object change: (Nsdictionary<nskeyvaluechangekey ,id> *) Change context: (void *) Context {    NSLog (@ "%@ object's%@ attribute changed%@", Object,keypath,change);}

is not successful, the next introduction, we then setter method inside concrete how to do, can trigger this method?

#import "Person.h" @implementation person-(void) test {    [self willchangevalueforkey:@ ' age '];        [Self didchangevalueforkey:@ ' age '];} @end

Add a test method to the person class. This time, I modified the code inside the Viewcontroller

@implementation Viewcontroller {person    *_p;} -(void) viewdidload {    [super viewdidload];        Create Person object    _p = [[Person alloc] init];        Add a listener to the age property of the person object    [_p addobserver:self forkeypath:@ "age" options:nskeyvalueobservingoptionnew Context:nil] ;    Call the test method    [_p test];    } Kvo callback method,-(void) Observevalueforkeypath: (NSString *) KeyPath Ofobject: (ID) object change: (nsdictionary< nskeyvaluechangekey,id> *) Change context: (void *) Context {    NSLog (@ "%@ object's%@ attribute changed%@", Object,keypath,change);} When the controller is destroyed, remove kvo-(void) dealloc {    [_p removeobserver:self forkeypath:@ ' age '];}

At this point, run the code and you'll see that it also triggers the KVO callback usage. But I didn't change the value of the age property at all. How can it be triggered? In the final analysis, the problem arises in the implementation of test, which is

[Self willchangevalueforkey:@ ' age '];    [Self didchangevalueforkey:@ ' age '];

These two lines of code are the key to triggering the KVO callback method. So, let's just rewrite the Setage method inside the Nskvonotifying_person class. You can implement KVO monitoring. This is known as the "setter method that overrides the observed attribute in this derived class, and the derived class implements the true notification mechanism in the overridden setter method";

-(void) Setage: (int) Age {        [self willchangevalueforkey:@ ' age '];        Self.age = age;        [Self didchangevalueforkey:@ ' age '];}

After reading this article, if everyone has not understood the place, can leave a message to discuss together. Thank you.

How iOS Kvo is implemented

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.