11

在我目前的項目中,幾個視圖控制器(如vc)產生在靜態NSOperationQueue上執行的NSOperation對象(如operation)。當操作正在等待或運行時,它將通過委派報告給視圖控制器(operation.delegate = vc,分配未保留)。如何正確處理一個排隊代理的排隊nsoperation

雖然這些操作可能需要一段時間,但同時應用程序可以通過彈出導航控制器的堆棧來釋放視圖控制器。

到目前爲止,一切都是故意的。包含靜態NSOperationQueue的類有辦法恢復操作,因此視圖控制器不保留它們。他們只是alloc/init/autoreleased並放在隊列中。

現在,這也會導致問題。在視圖控制器釋放後,任何對NSOperation的激進委託的調用都會導致訪問衝突。據我所知,不可能檢查指針上的對象是否已被釋放,as stated in this question

我能想到的一個修復方法是保留操作並將操作設置爲dealloc。但那是我最不喜歡的解決方案,因爲它會引入很多額外的ivars /屬性來跟蹤。

因此,我的問題是,還有其他方法來解決這個問題,如果是的話,你能在這裏畫一個嗎?

乾杯,
EP。

SOLUTION:制定出最適合我的方法是朱利安諾的回答略有變化:

  • 實現隊列管理器每個代表協議是不可行的(20個+不同的協議與50+方法),所以我保留了直接委託分配。我所做的改變是讓班級進行分配。這曾經是創建請求的類(和委託),但現在它被卸載到隊列管理器。

  • 隊列管理器在將委託分配給操作旁邊還包含輔助可變字典以跟蹤委託/操作對。

  • 每個委託實例在釋放時調用[QueueManager invalidateDelegate:self]方法,然後查找屬於該委託的請求並將其刪除。然後字典操作/委託對也被刪除,以允許適當地釋放該操作。

  • 最後,在KVO觀察每個操作的isFinished屬性後,可變字典保持清晰,以確保所有操作保留計數實際上在完成後釋放。

感謝Guiliano提供了使用KVO來解決這個問題的提示!

回答

7

我建議檢查您的架構和移動委託類(假設的QueueManager)管理,而不必在每個操作的代表隊:

  • 創建QueueManagerDelegate是 實現方法()你需要 通知viewControllers

  • 在的QueueManager添加志願觀察員每個的NSOperation(的isFinished屬性來完成這個添加操作到前隊列;))

  • 在國際志願者組織的回調調用的委託方法()你只需要當代表是=零

  • 添加無效的方法的QueueManager和調用這個方法! UIViewController中(一個或多個)的dealloc方法

    - (無效)無效 { 自>委託=零; }

的情況下,你需要對志願刷新:Kvo programming guide

+0

+1其次。它還可以更容易地「重新連接」到vc,以防再次出現並需要響應隊列(及其內容)中的更改。 – Toastor 2011-05-06 17:04:29

+0

非常有趣的方法。它將使QueueManager(確實存在)更加複雜一點,但它也將使代表團更加健壯。我會讓它醃一下,但聽起來像是要走的路。 – epologee 2011-05-06 17:24:59

+1

如果您需要一些示例代碼,請參閱Apple文檔中的FetchedImageLinker示例代碼。有一個名爲WatchedOperationQueue的類(或類似的東西,這裏沒有文檔)實現了描述的行爲。 – 2011-05-06 19:48:32

0

這裏最好的建議是查看應用程序的架構以避免這種情況。但是,如果當前代碼無法更改,請使用NSNotificationCenter。每次你的視圖控制器被釋放,你可以發佈通知,這個通知必須通過NSOperationQueue持有者,在通知處理程序中的簡單foreach循環到解除分配視圖控制器的代表。應該做的伎倆。

+0

真棒建議! – epologee 2011-05-06 16:35:22

0

您還應該檢查以確保任何代表(如果非零)也能夠響應操作完成中的消息。您可以使用所有NSObject子類所提供的respondsToSelector函數執行此操作。

在我的項目,我已經抽象該檢查到上NSObject的一個類別,讓我安全地調用代表與對象參數的任意數目:

- (void) dispatchSelector:(SEL)selector target:(id)target objects:(NSArray*)objects onMainThread:(BOOL)onMainThread {

if(target && [target respondsToSelector:selector]) { // Do your delegate calls here as you please } }

你可以在這裏看到完整的例子: https://github.com/chaione/ChaiOneUtils/blob/master/Categories/NSObject-Dispatch.m

+0

如果一切都正常完成,協議應該到位,無論如何,委託符合... – Toastor 2011-05-06 17:02:26

+0

不是我的問題的答案,但我只是讓你知道,所有的委託協議都已到位,並具有所需的方法只要。因此不需要檢查。 – epologee 2011-05-06 17:20:01