今天发现一个老问题引起的崩溃,记录一下。
先有问题的代码:
@implementation LogicHandle
- (instancetype)init
{
if (self = [super init]) {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(onNotification)
name:@"kLogicNotification" object:nil];
}
return self;
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)onNotification
{
[self showLog];
[self showLog];
[self showLog];
[self showLog];
}
- (void)showLog
{
NSLog(@"%@", self);
}
@end
//Post通知代码
- (void)postNotificationInBackground
{
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:kLogicNotification object:nil];
});
}
常规的通知接收模型大致都是这样格式,但是这种方式在处理多线程的调用时会有问题。
由于PostNotification是在另一个线程的,所以 onNotification
也会在另一个线程执行。 这个时候很多人会认为是不是多线程访问对象引起的崩溃?那加个锁可以解决问题吗?
- (void)onNotification
{
@synchronized (self) {
xxx;
xxx;
}
}
没错, 多线程访问数据时会有问题,但很明显这里只是输出一下 self, 并没有涉及到数据的修改,所以这种方式的加锁是不能解决问题的。
原因:
当后台线程在执行 onNotification
方法的时候,执行到一半,其他线程把对象释放了。
解决方法:
- 保证在同一线程发通知
- 如果要支持多线程调用,可以用 "强引用" 确保对象不被释放。
- (void)mutithread_message
{
__strong __typeof(self) strongSelf = self;
[strongSelf op];
}
这种其实就是 block 里面常规的 weak-strong 的写法,只是很少会直接写到函数里面。