KVO explain the underlying principle

The basic principle -> to add the properties of an object will trigger the listener when the listener listens when property values ​​change approach

#import "ViewController.h"
#import "Person.h"
@interface ViewController ()
@property (nonatomic, strong) Person *p;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.p=[[Person alloc]init];
    self.p.age=5;
    [self.p addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:@"额外信息"];
    // Do any additional setup after loading the view.
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    self.p.age=10;
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
    NSLog(@"\n%@\n%@\n%@\n%@",keyPath,object,change,context);
    /*
     age
     <Person: 0x600001390970>
     {
         kind = 1;
         new = 10;
         old = 5;
     }
     extra information
     */
}
-(void)dealloc{
    [self.p removeObserver:self forKeyPath:@"age"];
}

2, after adding the listener to the person, in fact, run by Apple underlying dynamic person to add a subclass NSKVONotifying_Person

   NSLog(@"%s",object_getClassName(self.p)); // Person
    [self.p addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:@"额外信息"];
    NSLog(@"%s",object_getClassName(self.p)); //NSKVONotifying_Person

3, the production of the new class in the newly generated four methods will

- (void)viewDidLoad {
    [super viewDidLoad];
    self.p=[[Person alloc]init];
    self.p.age=5;
    [self printMethodNamesOfClass:object_getClass(self.p)]; // Person age, setAge:
    [self.p addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:@"额外信息"];
    [self printMethodNamesOfClass:object_getClass(self.p)];//NSKVONotifying_Person setAge:, class, dealloc, _isKVOA,
}
- (void)printMethodNamesOfClass:(Class)cls
{
    unsigned int COUNT;
     // get the array method 
    Method, the methodList * = class_copyMethodList (CLS, & COUNT);
    
    // store method name 
    the NSMutableString methodNames * = [the NSMutableString String ];
    
    // loop through all methods 
    for ( int I = 0 ; I <COUNT; I ++ ) {
         // get method 
        Method, Method = the methodList [I];
         // get method name 
        NSString * methodName = NSStringFromSelector (method_getName (Method));
         / / splicing method name 
        [methodNames appendString: methodName];
        [methodNames appendString:@", "];
    }
    
    // release 
    free (methodList);
    
    // print method name 
    NSLog ( @ " % @% @ " , CLS, methodNames);
}

4 method described

- (void)setAge:(int)age
{
    _NSSetIntValueAndNotify();
}

// inside of the screen to achieve, to hide the existence of NSKVONotifying_Person class 
- (Class) class
{
    return [MJPerson class];
}

- (void)dealloc
{
    // finishing work 
}

- (BOOL)_isKVOA
{
    return YES;
}

4, modify the properties of an object in a new generation of this class -> actually will override the Set method similar - calls the Foundation framework  

_NSSetXXXValueAndNotify function:

  • willChangeValueForKey:
  • The original parent setter
  • didChangeValueForKey:
  • Monitor internal method will trigger the listener (Oberser) of (observeValueForKeyPath: ofObject: change: context :)

5. If you want to manually trigger a listener method listener KVO

  • Invokes this object willChangeValueForKey
  • Invokes this object didChangeValueForKey
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//    self.p.age=10;
    [self.p willChangeValueForKey:@"age"];
    [self.p didChangeValueForKey:@"age"];
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
    NSLog(@"\n%@\n%@\n%@\n%@",keyPath,object,change,context);
    /*
    age
     <Person: 0x6000019947f0>
     {
         kind = 1;
         new = 5;
         old = 5;
     }
     extra information
     */
}

 6, modify the object's member variables are not trigger the KVO, KVC assignment is able to trigger KVO

Guess you like

Origin www.cnblogs.com/ZhangShengjie/p/12094434.html