iOS 通知观察者的被调函数不一定运行在主线程
2015-03-09 22:14
253 查看
Tony in iOS | 08/08/2013
iOS 通知观察者的被调函数不一定运行在主线程
今天修复Bug时候发现的一个小细节,记录下。问题描述
事情是这样的:我在A视图(UITableView)注册了一个通知,当接收到此通知时,就重新读取数据并调用[tableView reloadData]。但是视图有时刷新后的显示的内容不对,再重新切换下视图又正常了。
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | //A视图在初始化时注册通知 - (void)viewDidLoad { //... [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reloadFavDBData:) name:@"refreshMyFavortieData" object:nil]; } //接收通知后的被调函数 - (void)reloadFavDBData:(NSNotification*)sender { [_dataArray release]; _dataArray = [MusicCollectedDataOperate getSongCollectedInfoWithKeyword:nil]; //重新获取数据 [tableView reloadData]; } //调用者在一个线程中运行,调用通知告诉A视图刷新数据 [[NSNotificationCenter defaultCenter] postNotificationName:@"refreshMyFavortieData" object:nil]; |
分析 & 解决
经过一番调试,在被调函数reloadFavDBData打了断点后意外发现,它并不是在主线程运行的!而我们在这里做了与UI相关的[tableView reloadData]操作——在非主线程做UI刷新操作,导致了显示异常的问题。
解决办法也很简单,在被调函数中切换到主线程再做操作就行啦。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | - (void)reloadFavDBData:(NSNotification*)sender { @synchronized(self) //保证线程安全 { //获取新数据,请注意这里和上述代码的区别,由于获取数据操作耗时相对较长, //原实现方式可能导致TableView获取数据时崩溃 NSArray *tmpArray = [MusicCollectedDataOperate getSongCollectedInfoWithKeyword:nil]; //切换到主线程 dispatch_async(dispatch_get_main_queue(), ^{ [_dataArray release]; _dataArray = [tmpArray retain]; [self.refreshTableView.myTableView reloadData]; }); } } |
WHY?
测试得来的结论还是不够完整。翻了翻官方文档,在NSNotificationCenter部分看到这样一段话:In a multithreaded application, notifications are always delivered in the thread in which the notification was posted, which may not be the same thread in which an observer registered itself.
在多线程程序中,通知总是在发送通知者的线程中调用(delivered,可以这么理解么?),结合上述所遇到的情况,我的理解是,通知观察者的被调函数总是运行在发送通知者的线程中,如下图所示:
这个结论告诉我们,通知的被调函数不一定运行在主线程中,如果需要做UI相关操作,需要手动切换到主线程。
有空再尝试看看通知的实现原理,应该会有更透彻的理解。
相关文章推荐
- iOS 通知观察者的被调函数不一定运行在主线程
- iOS 通知观察者的被调函数不一定运行在主线程
- iOS 接收通知的线程一定是主线程吗?
- “iOS 推送通知”详解:从创建到设置到运行
- iOS多线程的初步研究(五)-- 如何让NSURLConnection在子线程中运行
- ios学习--“iOS 推送通知”详解:从创建到设置到运行
- iOS 推送通知”详解:从创建到设置到运行
- “iOS 推送通知”详解:从创建到设置到运行
- IOS观察者模式与通知中心
- ios运行时替换函数
- ios后台申请运行一定的时间
- iOS多线程的初步研究(五)-- 如何让NSURLConnection在子线程中运行
- 怎样在线程中运行类的成员函数
- iOS 多线程初步研究-NSURLConnection在子线程中运行
- iOS多线程的初步研究(五)-- 如何让NSURLConnection在子线程中运行
- “iOS 推送通知”详解:从创建到设置到运行
- ios中观察者模式与通知机制,及KVO
- vb.net shell线程执行完成后再运行以后处理 函数
- 多线程,线程创建及关闭句柄存在的问题,终止线程的运行的几个函数
- “iOS 推送通知”详解:从创建到设置到运行