零. 前言
在iOS开发过程中,如果增加了KVO和通知,需要在销毁时候及时移除掉,不然的话就有可能会崩溃。为了避免同事们开发过程中忘记remove,需要写个脚本,在编译时自动监测是否有移除,将崩溃扼杀于开发阶段中。
本次脚本实现依然基于正则,去检测一个文件是否同时存在(添加通知和移除通知)、(添加KVO和移除KVO),如果只添加不移除就会报错。
一. 通知的检测
通知的通用创建为:[[NSNotificationCenter defaultCenter] addObserver:(weak)self(.param) selector:...]
,由于工程中加了个宏NOTIFICATION_CENTER
,因此需要检测以上两种格式,得正则:
(?:\[NSNotificationCenter\s*defaultCenter\]|NOTIFICATION_CENTER)\s*?addObserver:\s*?.*?[sS]elf(.*?)\s+?selector:
通知的通用移除为:[[NSNotificationCenter defaultCenter] removeObserver:(weak)self(.param) ....]
,得正则:
observer = '.*?[sS]elf' + param # 这里的param是指上面添加方法的参数
(?:\[NSNotificationCenter\s*?defaultCenter\]|NOTIFICATION_CENTER)\s*?removeObserver:\s*? + observer + r'(?:\s*name:.*?)?(?:\s*object:.*?)?\s*?\]'
如果创建能匹配,移除不能匹配,则视为没有被移除,从而报错。
二. KVO的检测
KVO的通用创建为:[xxx addObserver:(weak)self(.param) forKeyPath:xxx options:.....]
,则可以通过以下正则检测:
addObserver:\s*.*?[sS]elf(.*?)\s+?forKeyPath:\s*(.+?)\s+?options:
KVO的通用移除为:[xxx removeObserver:(weak)self(.param) forKeyPath:....]
,则可以通过以下正则检测,其中param和keypath为上述正则的匹配结果:
observer = '.*?[sS]elf' + param
'removeObserver:\s*' + observer + '\s+?forKeyPath:\s*' + keypath
如果创建能匹配,移除不能匹配,则视为没有被移除,从而报错。
三. 测试样例
- (void)dealloc {
[NOTIFICATION_CENTER removeObserver:self];
[NOTIFICATION_CENTER removeObserver:self.params];
[test3 removeObserver:self forKeyPath:@"kvo_test1"];
[test4 removeObserver:self forKeyPath:@"kvo_test2"];
[test5 removeObserver:self.params forKeyPath:@"kvo_test1"];
}
- (void)setup2 {
[NOTIFICATION_CENTER addObserver:self selector:@selector(test1) name:@"noti_test1" object:nil];
[NOTIFICATION_CENTER addObserver:self.params selector:@selector(test2) name:@"noti_test2" object:nil];
[test3 addObserver:self forKeyPath:@"kvo_test1" options:nil context:nil];
[test4 addObserver:self forKeyPath:@"kvo_test2" options:nil context:nil];
[test5 addObserver:self.params forKeyPath:@"kvo_test1" options:nil context:nil];
}
dealloc
删掉任意一行代码都会报错。
网友评论