2011-08-10 46 views
0

我正在使用NSOperation來執行一些數據的大量解析,然後返回到主線程,準備好可供我的應用程序使用的對象。我將所有操作放在單例NSOperationQueue上來處理。我這樣做是爲了控制在任何時候進行多少處理,因爲每個操作都暫時使用相當高的內存佔用量。NSOperation沒有被正確取消

所以,我有一個場景,我可以在屏幕上有幾個視圖控制器。每個視圖控制器將創建一個負載分析操作並將其添加到隊列中。我通過設置maxConcurrentOperationCount允許2個併發處理操作。每個視圖控制器都會創建一個處理操作,將其放置在單例隊列中,並將操作保留爲屬性,以便處理該操作。

如果視圖控制器需要走開響應啓動刪除操作的用戶,我用我的視圖控制器的dealloc方法中的NSOperation財產取消操作:

-(void)dealloc{ 
    [self.currentOperation cancel]; 
    [super dealloc]; 
} 

在我的NSOperation子類我檢查isCancelled財產在幾個地方的isCancelled財產(主要是長時間運行工作顯著塊前),並試圖對此作出迴應:

if([self isCancelled]){ 
    // Perform cleanup 
    return; 
} 

的問題是,在isCancelled財產評估,以FAL然後繼續操作,最終調用Core Data來嘗試檢索已刪除的數據。即使在覈心數據獲取請求之前立即進行isCancelled檢查,我也會看到這種情況。

我有一個解決方法,以防止應用程序崩潰,但我想我可能會執行錯誤。有沒有其他方式可以在操作時保持操作的句柄,以便我可以在需要時取消操作?我的方法是否沒有保留正確的操作手柄並防止它被正確取消?

+0

如果您未覆蓋NSOperation中的cancel方法,則在調用cancel之後,isCancelled應計算爲true。確保self.currentOperation在你達到dealloc時不是零。 – Joe

回答

2

你不能在dealloc中做這樣的邏輯。

首先,dealloc必須調用super的dealloc作爲最後一行。一旦完成,對象就消失了,所有後續的消息傳遞行爲都是未定義的(將崩潰)。

該隊列很可能會保留該操作,因此dealloc中的取消無意義,因爲在隊列釋放之前dealloc不能被調用(除非您的內存管理已被搞砸)。

您需要將您的取消/失效邏輯與內存管理完全分開。

+0

對不起,沒有包含整個dealloc方法。我最後打電話給[super dealloc]。我試着從幾個不同的地方叫取消。最初,我試圖在調用Delete方法時調用它。我總是得到相同的結果。爲了澄清,我在視圖控制器的dealloc方法中調用了該方法,該方法將該特定操作保留爲屬性。我處理錯了嗎? –

+0

是的 - 在調用dealloc時,連接到被釋放對象的對象圖處於不確定狀態(您不知道哪些對象已經被釋放,除了那些*這個*對象已經很難保留上)。您需要將您的取消邏輯與取消分配完全分開。 – bbum

+0

可以取消(從你的nsoperation)從UI調用?也就是說,從主線程?是不是一個問題,因爲isCancel可以從2個不同的線程調用創建競爭條件?感謝您的回覆。 – Ricardo