本文首發於我的博客html
觀察者模式 屬於行爲型模式。git
觀察者模式(有時又被稱爲模型(Model)-視圖(View)模式、源-收聽者(Listener)模式或從屬者模式)是軟件設計模式的一種。在此種模式中,一個目標物件管理全部相依於它的觀察者物件,而且在它自己的狀態改變時主動發出通知。這一般透過呼叫各觀察者所提供的方法來實現。此種模式一般被用來實現事件處理系統。github
通常兩種:KVO和通知。通知比較簡單,這裏只說一下KVO編程
例如,咱們定義一個 YZPerson 類 繼承自 NSObject ,裏面有name 和 age 兩個屬性設計模式
@interface YZPerson : NSObject
@property (nonatomic ,assign) int age;
@property (nonatomic,strong) NSString *name;
@end
複製代碼
而後在ViewController中,寫以下代碼bash
- (void)viewDidLoad {
[super viewDidLoad];
//調用方法
[self setNameKVO];
}
-(void)setNameKVO{
self.person = [[YZPerson alloc] init];
// 註冊觀察者
NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld;
[self.person addObserver:self forKeyPath:@"name" options:options context:@"1111"];
}
// 當監聽對象的屬性值發生改變時,就會調用
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
NSLog(@"監聽到%@的%@屬性值改變了 - %@ - %@", object, keyPath, change, context);
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
self.person.name = @"ccc";
}
-(void)dealloc
{
// 移除監聽
[self.person removeObserver:self forKeyPath:@"name"];
}
複製代碼
執行以後結果爲app
KVOdemo[11482:141804] 監聽到<YZPerson: 0x6000004e8400>的name屬性值改變了 - {
kind = 1;
new = ccc;
old = "<null>";
} - 1111- 1111
複製代碼
須要注意的是,上面代碼中咱們已經移除了監聽,若是再次移除的話,就會crash框架
例如異步
- (void)viewDidLoad {
[super viewDidLoad];
//調用方法
[self setNameKVO];
}
-(void)setNameKVO{
self.person = [[YZPerson alloc] init];
// 註冊觀察者
NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld;
[self.person addObserver:self forKeyPath:@"name" options:options context:@"1111"];
// 移除監聽
[person removeObserver:self forKeyPath:@"name"];
// 再次移除
[person removeObserver:self forKeyPath:@"name"];
}
複製代碼
移除屢次會報錯函數
KVOdemo[9261:2171323] *** Terminating app due to uncaught exception 'NSRangeException',
reason: 'Cannot remove an observer <ViewController 0x139e07220> for the key path "name" from <YZPerson 0x281322f20> because it is not registered as an observer.'
複製代碼
若是忘記移除的話,有可能下次收到這個屬性的變化的時候,會carsh
因此,咱們要保證add和remove是成對出現的
更多關於KVO的內容,包括KVO的本質,KVO內部的流程,手動調用KVO等,能夠參考以前的一篇文章關於KVO看這篇就夠了