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