观察者模式(通知、kvo)

KVC:  key values coding   键值编码,间接通过字符串对应的key取出、修改其对应的属性。

作用: 可以访问和修改私有成员变量、readOnly成员变量的值。(替换系统自带的导航栏、替换系统自带的Tabbar等)

Person *person = [[Person alloc] init];
[person setValue:@"张三" forKey:@"name"];

这仅仅只是一个示例,KVC当然是强大的,UIKit框架里面很多属性是readOnly、私有的,往往我们在开发中会觉得有一些属性不好用,想改变吧,要么是readOnly,要是是私有的,难道重新写一套?但是耗时耗力,又不一定有系统的效果好。这个时候,KVC的作用就大了,我们可以自定义那些特定需求的控件,然后用KVC将系统自带的换掉,换成自定义的,简单快速轻松就可以搞定了。


KVO是用来做属性监听的,用完后必须要移除它。

实现原理:KVO是基于runtime机制实现的,当某个类的对象第一次被观察时,系统就会在运行期动态的创建一个该类的一个派生类,在这个派生类中重写基类中任何被观察属性的setter方法,派生类在重写基类的setter方法中实现真正的通知机制。
kvo详细原理:KVO的原理_想名真难的博客-CSDN博客_kvo

如此,来看看代码里面KVO怎么实现监听一个对象值的改变:

#import "SecondViewController.h"
#import "Person.h"

@interface SecondViewController ()
@property (weak, nonatomic) IBOutlet UILabel *secondLabel;
@property (nonatomic, strong) Person *person;
@end

@implementation SecondViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    [self.person addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:nil];

}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    if (object == self.person && [keyPath isEqualToString:@"name"]) {
        NSLog(@"change: %@",change);
        NSLog(@"旧值是:%@", change[NSKeyValueChangeOldKey]);
        NSLog(@"新值是:%@", change[NSKeyValueChangeNewKey]);
        self.secondLabel.text = change[NSKeyValueChangeNewKey];
    }
}

- (void)dealloc {
    [self.person removeObserver:self forKeyPath:@"name"];
    NSLog(@"%s",__func__);
}


@end

 上述,就是一个KVO的完整实现,但事实上,还是有问题的,潜在的问题有可能出现在dealloc中对KVO的注销上。KVO的一种缺陷是,当对同一个keypath进行两次removeObserver时会导致程序crash,如果忘记了remove, 又会导致内存泄漏(在iOS12上测试了几次, 在dealloc中没有调用removeObserver:forKeyPath:, 并没有发生内存泄漏, 不确定是不是系统已经优化了KVO的实现方式)


观察者模式

观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

在设计模式中观察者模式是这样的, 具体到OC中, 系统以为帮我们实现, KVO、NSNotification、委托都可以说是OC里面的监听者模式,NSNotification更重量级一些,除了监听外,还需负责传递信息等。

什么时候使用观察者模式:

  • 有两种抽象类型相互依赖,将他们封装在各自的对象中,就可以对它们单独进行改变和复用。
  • 对一个对象的改变需要同时改变其他对象,而不知道具体有多少对象有待改变。
  • 一个对象必须通知其他对象,而它又不关心其他对象是什么。

MVC是由各种复杂的设计模式组合而成的复合结构,观察者是其中的设计模式之一。视图与控制器联系在一起,等待会影响应用程序表现的事件发生。例如,当用户单击视图上的排序按钮时,事件会传递给控制器,模型在后台排序完毕后,会通知所有相关的控制器,让它们用新的数据更新视图。

在MVC中使用观察者模式,每个组件都能够被独立复用与扩展,而对关系中的其他组件没有太多干扰。所得到的高度可复用性与可扩展性,是把其全部逻辑放入一个类中所无法得到的。MVVM所使用的双向绑定, 通过KVO可以由更简单,有效的实现.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值