你好,歡迎來到IOS教程網

 Ios教程網 >> IOS訊息 >> 關於IOS >> iOS 通知觀察者的被調函數不一定運行在主線程

iOS 通知觀察者的被調函數不一定運行在主線程

編輯:關於IOS
[收起] 文章目錄
  • 問題描述
  • 分析 & 解決
  • WHY?

今天修復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,可以這麼理解麼?),結合上述所遇到的情況,我的理解是,通知觀察者的被調函數總是運行在發送通知者的線程中,如下圖所示:

iOS 通知觀察者的被調函數不一定運行在主線程

這個結論告訴我們,通知的被調函數不一定運行在主線程中,如果需要做UI相關操作,需要手動切換到主線程。

有空再嘗試看看通知的實現原理,應該會有更透徹的理解。

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved