問(wèn)題
在ViewDidLoad 中注冊(cè)監(jiān)聽(tīng)者 在ViewController 中dealloc 函數(shù)中調(diào)用removeObserver移除觀察者發(fā)生崩潰栋猖。
代碼
#import "BController.h"
@interface BController ()<UIScrollViewDelegate>
@property (nonatomic, copy) NSString *name;
@end
@implementation BController
- (void)viewDidLoad {
[super viewDidLoad];
[self addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
}
- (void)dealloc{
[self removeObserver:self forKeyPath:@"name"];
}
@end
#import "AController.h"
@interface AController ()<UIScrollViewDelegate>
@property (nonatomic, copy) NSString *name;
@end
@implementation AController
- (void)viewDidLoad {
[super viewDidLoad];
[self addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
}
- (void)dealloc{
[self removeObserver:self forKeyPath:@"name"];
}
- (void)testA{
BController *bcontroller = [[BController alloc] init];
[self.navigationController pushViewController:bcontroller animated:YES];
}
- (void)testB{
BController *tempController = [[BController alloc] init];
BController *controller = [[BController alloc] init];
[self.navigationController pushViewController:controller animated:YES];
}
@end
分析
如果removeObserver 移除觀察者失敗叨咖,一般情況就是沒(méi)有注冊(cè)觀察者害碾,但是檢查代碼的時(shí)候發(fā)現(xiàn)已經(jīng)在代碼中注冊(cè)了觀察者呢矢劲??慌随?芬沉? 這是就要檢查是否真正的調(diào)用了注冊(cè)函數(shù)。
在AController中 testA 創(chuàng)建了bcontroller 控制器并跳轉(zhuǎn)阁猜,顯然已經(jīng)調(diào)用了bcontroller中的
- (void)viewDidLoad {
[super viewDidLoad];
[self addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
}
當(dāng)從bcontroller返回時(shí)調(diào)用了,移除了觀察者,這是正確的運(yùn)行正常
- (void)dealloc{
[self removeObserver:self forKeyPath:@"name"];
}
但是在testB函數(shù)中丸逸,產(chǎn)生了奔潰
- (void)testB{
BController *tempController = [[BController alloc] init];
BController *controller = [[BController alloc] init];
[self.navigationController pushViewController:controller animated:YES];
}
這是為什么呢?原來(lái)是tempController 這個(gè)控制器被創(chuàng)建后并沒(méi)有跳轉(zhuǎn)剃袍,也就是沒(méi)有調(diào)用到注冊(cè)函數(shù)
- (void)viewDidLoad {
[super viewDidLoad];
[self addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
}
但因?yàn)榛聘眨瑃empController 沒(méi)有任何東西引用它,意思就是tempController 這個(gè)對(duì)象創(chuàng)建了并沒(méi)有什么用處民效,當(dāng)執(zhí)行完testB函數(shù)后會(huì)被釋放并調(diào)用dealloc函數(shù),移除觀察者
- (void)dealloc{
[self removeObserver:self forKeyPath:@"name"];
}
沒(méi)有注冊(cè)觀察觀察者憔维,卻想要移除觀察者,自然產(chǎn)生了崩潰了??