2010-09-13 120 views
1

NSOperation調用.navigationController popViewControllerAnimated:YES時出現一個奇怪的問題,屏幕沒有正確更新,並且使彈出的視圖可見但顯然已解除分配。iPhone/iOS popViewControllerAnimated不刷新屏幕

詳細信息:我有一個列表視圖,訪問本地的sqlite數據庫。當在記錄上點擊時,它會顯示該記錄的詳細視圖,並啓動一個異步NSOperation(在主線程上)來檢查XML後端數據庫,以查看該記錄是否在數據庫中仍然可用。由於架構的原因,我不會進入,我不能在列表視圖上運行此操作,它必須在詳細視圖中。如果記錄自上次同步以來被刪除,它會通知用戶記錄已被刪除,並在共享應用程序委託上調用popViewControllerAnimated。理想情況下,這會彈出當前詳細視圖並返回到先前的列表視圖。

錯誤:正確的視圖實際上是彈出在內存中(它已被釋放),但它仍然顯示在屏幕上。導航欄是空白的,但我可以點擊「後退」按鈕的位置,然後導航到列表視圖之前的開始屏幕,這意味着至少導航欄能夠理解它應該在的位置,甚至是如果它沒有正確顯示標題或返回按鈕。主要問題是詳細信息視圖仍然可見並且可以與之交互,從而導致應用程序崩潰。例如,在詳細視圖中也有UITableView顯示的數據,如果用戶滾動表中的向下,則拋出異常「-[xAccountDetailController tableView:cellForRowAtIndexPath:]:消息發送到釋放的實例」

這使我相信,細節控制器已經被解除分配通過調用popViewControllerAnimated正確,但顯然仍有一些內存駐留在內存中,如果該表實際調用cellForRowAtIndexPath,即使它的視圖控制器已經從navigationController中彈出。

在Detail視圖中手動推回按鈕(對於未在後端刪除的記錄)完美地工作。

解決方法嘗試:當我向NSOperation傳遞對詳細視圖控制器的引用時,我試圖直接從共享應用程序委託中調用該視圖的navigationController屬性中的popViewControllerAnimated。我也嘗試彈出兩個視圖,並重新將列表視圖推送到navigationController上,但這會導致更令人不安的界面效果,其中根和列表視圖控制器似乎在導航欄中同時存在(標題相互覆蓋而不是不存在)。我試着將NSOperation中存在的詳細視圖控制器的引用設置爲零,但是它什麼都不做。我曾嘗試在彈出之前調用[detailView release],但正如預期的那樣,它在彈出窗口上失敗,因爲它在發佈之前僅保留1。我也試過popToViewControllerpopToRootViewController,似乎沒有任何工作。舊的視圖總是在那裏,導航欄是唯一的界面元素,似乎做任何事情,即使如此,它的顯示不正確。我也嘗試重新加載表,因爲我不介意視圖是否可見(不彈出),我只想清除數據 - 但由於某種原因,表不會重載數據。

想法:因爲正在運行NSOperation的operationQueue是有問題的詳細視圖的一個屬性,所以我確保在詳細視圖的dealloc中取消所有操作並將對operationQueue的引用設置爲nil。我還試圖確保在其他對象中對該視圖的所有引用都設置爲零。直接從詳細視圖上的按鈕調用popViewControllerAnimated完美工作,所以它必須是我從NSOperation調用該方法,運行在NSOperationQueue上,這是我想要彈出的詳細視圖屬性。某些地方的引用必須保持部分活動的視圖,但我似乎無法找到任何仍在調用彈出窗口時引用該視圖的內容。

太多的地方有太多的代碼發佈在這裏。

有什麼想法?

對不起,提前如此長的問題,謝謝,

格雷格


編輯1: 我可以重現這個問題的NSOperation外面用新鮮的UIViewController容易。

tableView:didSelectRowAtIndexPath方法我稱之爲以下幾點:

xBaseViewController * vc = [[xBaseViewController alloc] initWithStyle:UITableViewStyleGrouped]; 
[self.navigationController pushViewController:vc animated:YES]; 
[vc performSelectorOnMainThread:@selector(popView) withObject:nil waitUntilDone:YES]; 

在VC中,popView方法:

[self.navigationController popViewControllerAnimated:YES]; 

我不認爲這有保留計數或的NSOperation做。以這種方式彈出視圖,我在做一些根本性錯誤?

回答

2

你的問題是你正試圖刷新不是主線程的線程上的屏幕。在iOS中,只能使用主線程更新屏幕上正在發生的事情。

你需要這樣的代碼:

[self performSelectorOnMainThread:@selector(mymethod) withObject:nil waitUntilDone:YES modes:nil]; 

它應該只是花花公子。

+0

感謝您的回答。我試過這個,但我似乎無法運行選擇器。通過調試器,它到達這條線並跳過它。選擇器調用過程中的斷點永遠不會被觸發。正如預料的那樣,將選擇器名稱更改爲不存在的情況會導致程序崩潰,但使用正確的過程名稱,它不會運行它。有任何想法嗎? G – Greg 2010-09-13 17:50:41

+0

這對我一直都很有用,所以我不知道會出現什麼問題,也許你應該拿掉模式部分,只使用'performSelectorOnMainThread:withObject:waitUntilDone:',但這只是一個可能的解決方案,因爲我不知道你的代碼中究竟做了什麼。 – 2010-09-13 18:04:25

+0

再次感謝。離開'模式:'工作。但是,不幸的是沒有解決問題。後退按鈕向右移動,遺忘,我可以點擊新的後退按鈕,它會返回另一個視圖,但導航欄是空白的,並且釋放的視圖仍然存在。 G – Greg 2010-09-14 10:21:59