iOS之KVC和KVO

/*
 KVC是键值编码
 提供一种间接访问对象属性的机制,而不是通过getter和setter
 1.为指定属性设置值:setValue:属性值 forKey:属性名称
 2.获取指定属性值:  valueForKey:属性名称
 
 KVO是键值监听
 只有通过KVC改变对象的属性值,才能被监听到
 1.为某对象的某属性设置监听:addObserver:forKeyPath:options:context:
 2.为key路径删除指定监听:  removeObserver:forKeyPath:context:
 */
#import "ViewController.h"
#import "JYPerson.h"

@interface ViewController ()
@property(nonatomic,strong)JYPerson *person;
@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    JYPerson *person=[[JYPerson alloc]init];
    
    [person setValue:@"顾金跃" forKey:@"name"];
//    [person setName:@"顾金跃123"];
//    person.name=@"顾金跃321";
    
    
    [person setValue:@"173.5" forKey:@"height"];
    [person setValue:@"135" forKey:@"weight"];
    
    NSLog(@"姓名:%@  身高:%@  体重:%@",person.name,person.height,person.weight);
    NSLog(@"姓名:%@  身高:%@  体重:%@",[person valueForKey:@"name"],[person valueForKey:@"height"],[person valueForKey:@"weight"]);
    
    [person addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil];
    [person addObserver:self forKeyPath:@"height" options:NSKeyValueObservingOptionNew context:nil];
    [person addObserver:self forKeyPath:@"weight" options:NSKeyValueObservingOptionNew context:nil];
    
    
    self.person=person;
    
    [self addButton];
    
}

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
{
    NSLog(@"被修改的keyPath为:%@ 被修改的对象为:%@ 新被修改的属性值为:%@ 被修改的上下文为:%@",keyPath,[object class],[change objectForKey:@"new"],context);
    
    NSLog(@"%@",self.person.name);
}
-(void)dealloc
{
    [self.person removeObserver:self  forKeyPath:@"name"];
    [self.person removeObserver:self forKeyPath:@"height"];
    [self.person removeObserver:self forKeyPath:@"weight"];
}


-(void)addButton
{
    UIButton *button=[UIButton buttonWithType:UIButtonTypeContactAdd];
    button.frame=CGRectMake(100, 100, 50, 50);
    [button addTarget:self action:@selector(buttonClick) forControlEvents:UIControlEventTouchUpInside];
    
    [self.view addSubview:button];
}

-(void)buttonClick
{
    NSLog(@"点击");
    self.person.name=@"123";
}
@end
 
 
<span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">当某个类的对象第一次被观察时,</span><span style="font-family: Arial; font-size: 14px; line-height: 26px; color: rgb(255, 0, 0);">系统就会在运行期动态地创建该类的一个派生类,在这个派生类中重写基类中任何被观察属性的 setter 方法。
派生类在被重写的 setter 方法实现真正的通知机制</span><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">,就如前面手动实现键值观察那样。这么做是基于设置属性会调用 setter 方法,而通过重写就获得了 KVO 需要的通知机制。当然前提是要通过遵循 KVO 的属性设置方式来变更属性值,如果仅是直接修改属性对应的成员变量,是无法实现 KVO 的。</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">同时派生类还重写了 class 方法以“欺骗”外部调用者它就是起初的那个类。然后系统将这个对象的 isa 指针指向这个新诞生的派生类,因此这个对象就成为该派生类的对象了,因而在该对象上对 setter 的调用就会调用重写的 setter,从而激活键值通知机制。此外,派生类还重写了 dealloc 方法来释放资源。</span>


你可能感兴趣的:(iOS之KVC和KVO)