#import
@interface Person : NSObject
{
@public
// int _age;
// int _isAge;
// int age;
int isAge;
}
@end
#import "Person.h"
@implementation Person
/**
valueForKey会按照下面顺序寻找
*/
//-(int)getAge{
// return 10;
//}
//-(int)age{
// return 20;
//}
//-(int)isAge{
// return 30;
//}
//-(int)_age{
// return 40;
//}
/**
setValue: forKey: 会按照下面顺序寻找
*/
//-(void)setAge:(int)age{
// NSLog(@"setAge=====");
//}
//-(void)_setAge:(int)age{
// NSLog(@"_setAge=====");
//}
/*
是否允许直接返回成员变量
如果不主动实现,默认返回值就是YES
如果返回值为YES,那么久允许直接访问成员变量,反之不能
*/
+(BOOL)accessInstanceVariablesDirectly{
// return NO;
return YES;
}
/*********证明是否手动触发了KVO**********/
//KVO成员变量修改之前调用
-(void)willChangeValueForKey:(NSString *)key{
[super willChangeValueForKey:key];
NSLog(@"willChangeValueForKey - %@", key);
}
//KVO成员变量修改之后调用
-(void)didChangeValueForKey:(NSString *)key{
NSLog(@"didChangeValueForKey - begin - %@", key);
//这个内部会调用observer的observeValueForKeyPath方法
[super didChangeValueForKey:key];
NSLog(@"didChangeValueForKey - end - %@", key);
}
@end
#import "ViewController.h"
#import "Person.h"
@interface ViewController ()
@property (nonatomic,strong) Person *person;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
Person *person = [[Person alloc] init];
self.person = person;
//KVO监听
[person addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:nil];
//KVC赋值
[person setValue:@(1) forKey:@"age"];
//打印值
// NSLog(@"=====%d",person->_age);
// NSLog(@"=====%d",person->_isAge);
// NSLog(@"=====%d",person->age);
NSLog(@"=====%d",person->isAge);
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
//获取值
NSLog(@"==valueForKey===%@",[self.person valueForKey:@"age"]);
}
/**
1. 发现问题如下:
1. 即使Person没有实现setAge:方法或者没有age属性,仅仅有_age/_isAge
/age/isAge成员变量,当KVC赋值的时候,也会触发KVO。
2. KVO监听的是对象的“age”成员,但是对象即使没有age成员,或者_age成员,只有_isAge或者isAge,也会触发KVO
3. 说明KVC(setValue:forKey:)内部主动通知了KVO
//猜测内部实现
// [person willChangeValueForKey:@"age"];
// person->_age = 10;
// [person didChangeValueForKey:@"age"];
4. 因此,使用KVC修改成员变量值,不管对象内部是否实现setter方法,都会触发KVO
*/
//当监听对象的属性值发生改变的时候
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
NSLog(@"observeValueForKeyPath - %@", change);
}
- (void)dealloc{
[self.person removeObserver:self forKeyPath:@"age"];
}
@end