最近app中加了很多通知,但误用通知会导致方法多次调用等各种问题,为了研究透通知的处理机制,举了几个例子来讲解。
为了深入了解通知的处理机制,首先我们要明白控制器的生命周期(调用先后顺序如下):
载入完成,可以进行自定义数据以及动态的创建其他空间:
- (void)viewDidLoad
视图将出现在屏幕之前: - (void)viewWillAppear:(BOOL)animated
视图在屏幕上渲染完成: - (void)viewDidAppear:(BOOL)animated
视图被移除之前 - (void)viewWillDisappear:(BOOL)animated
视图被移除完成 - (void)viewDisappear:(BOOL)animated
销毁视图 - (void)dealloc
值得注意的是:
-(void)viewDidLoad 只会在控制器初始化时载入一次,
-(void)dealloc也只会在控制器销毁时载入一次.
而其他四个方法可以根据多个视图控制器切换时多次调用.
所以通知的业务逻辑可以根据以上进行合理的调度。
关于通知的注册和移除
有人喜欢方法一:
- (void)viewWillAppear:(BOOL)animated注册通知
- (void)viewWillDisappear:(BOOL)animated移除通知
也有人喜欢方法二 - (void)viewDidLoad 注册通知,
- (void)dealloc移除通知.
其实这都是需要根据业务逻辑来处理的,并不能一概而论。
例如:
在大厅中监听房间的创建和销毁,可以初始化时就开启监听,作为最底层的控制器即可选择方法二。
而在一些权限界面,比如玩家达成一定条件才开启的,可以采用方法一。
甚至可以不局限于这些地方,只要方法适当可以在任何地方注册和销毁,当然注册了通知后,移除对应的通知也是必要的。
还有一些问题:
当在某个控制器不小心一次性注册几次通知:
-(void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(father)
name:@"father"
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(father)
name:@"father"
object:nil];
}
你就可能会接收到同样多的信息:
2017-08-22 15:30:32.060 MyFrameWork[10504:299552] father
2017-08-22 15:30:33.172 MyFrameWork[10504:299552] father
但是移除通知只需要移除一次即可:
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"father" object:nil];
另一方面,如果基类里面注册了通知,最好选择在基类的
-(void)viewDidLoad中注册。
其实会用通知后,开发就很方便了,特别是用于基于sokect的编程中,不断地和服务器进行交互,需要分发好服务器推送过来的信息,不然就可能造成信息错乱,内存异常等问题。