MPerson.h类
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface MCat : NSObject
@property (assign, nonatomic)int weight;
@end
@interface MPerson : NSObject
{
@public
int _age;
int _isAge;
int age;
int isAge;
}
//@property (assign, nonatomic)int age;
@property (strong, nonatomic) MCat *cat;
@end
NS_ASSUME_NONNULL_END
MPerson.m
#import "MPerson.h"
@implementation MPerson
//- (void)setAge:(int)age
//{
//
// NSLog(@"setAge:-%d",age);
//}
//-(void)_setAge:(int)age
//{
// NSLog(@"_setAge:-%d",age);
//}
// 默认返回值为YES
+ (BOOL)accessInstanceVariablesDirectly
{
return YES;
}
- (void)willChangeValueForKey:(NSString *)key
{
[super willChangeValueForKey:key];
NSLog(@"willChangeValueForKey");
}
-(void)didChangeValueForKey:(NSString *)key
{
NSLog(@"BEGIN:didChangeValueForKey");
[super didChangeValueForKey:key];
NSLog(@"END:didChangeValueForKey");
}
//- (int)getAge
//{
// return 11;
//}
//- (int)age
//{
// return 12;
//}
//-(int)isAge
//{
// return 13;
//}
//- (int)_age
//{
// return 14;
//}
@end
MObserver.h
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface MObserver : NSObject
@end
NS_ASSUME_NONNULL_END
MObserver.m
#import "MObserver.h"
@implementation MObserver
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
NSLog(@"--object:%@---keyPath:%@ --- change:%@",object,keyPath,change);
}
@end
ViewController.m
#import "ViewController.h"
#import "MPerson.h"
#import "MObserver.h"
@interface KVCViewController ()
@end
@implementation KVCViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
MObserver *observer = [[MObserver alloc]init];
MPerson *person = [[MPerson alloc]init];
// 添加KVO监听
[person addObserver:observer forKeyPath:@"age" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
// 通过KVC修改属性(Person类的内部即使没有setAge这个方法,即Person类中没有age这个属性而是有_age这个成员变量时,且Person的类方法+ (BOOL)accessInstanceVariablesDirectly返回YES的时候(默认返回YES)发现也走了KVO的方法,记KVC内部调用了willChangeValueForKey:和didChangeValueForKey)
[person setValue:@(5) forKey:@"age"];
/* 上面一行代码相等于
[person willChangeValueForKey:@"age"];
person->_age = 10;
[person didChangeValueForKey:@"age"];
*/
MPerson *personF = [[MPerson alloc]init];
personF->_age = 11;
personF->_isAge = 12;
personF->age = 13;
personF->isAge = 14;
NSLog(@"获取age = %@",[personF valueForKey:@"age"]);
// 移除KVO监听
[person removeObserver:observer forKeyPath:@"age"];
// keyPath
[person setValue:@(10) forKeyPath:@"cat.weight"];
}
@end