簡體   English   中英

手動內存管理中的弱/強“跳舞”

[英]Weak/Strong “dance” in Manual Memory Management

想象一下使用手動內存管理 (又稱非ARC)的以下場景:

我有一個VC將塊傳遞給類方法。 在塊執行之前,VC會從UINavigationController彈出。 __block MyVC *weakSelf = self形式的弱引用被傳遞給塊,然后轉換為MyVC *strongSelf = weakSelf (又稱弱/強舞)。 任何干預者都不會保留該區塊。

在這種情況下,我在代碼中看到的是:

  1. 彈出VC時會調用VC的dealloc。
  2. 該塊最終被調用。
  3. 應用程序崩潰,因為我正在訪問垃圾( strongSelf指向它)。

我的問題是:我不希望我的VC在塊最終執行之前保持活動狀態,但是一旦塊被執行,我想確認strongSelf是有效的。

我已經檢查了這個( Apple的非常重要的例子 ),因為它的設計考慮了ARC,所以它不起作用。 那么我如何才能與MMM有相同的行為? 理想情況下,我希望得到__weak所做的:如果retainCount達到零,我希望它的引用指向nil而不是垃圾。


從Apple閱讀之后:

在某些情況下,如果類與__weak兼容,則可以使用__unsafe_unretained。 然而,這對於非平凡的循環來說可能變得不切實際,因為很難或不可能驗證__unsafe_unretained指針是否仍然有效並仍然指向相同的對象。

既然我無法訪問__weak ,我甚至可以做什么?

我在iOS 4.x時代就與這個問題進行了斗爭。 如果沒有弱指針可以幫到你,這並不容易!

如果你保證稍后在主線程上執行塊(即從weakSelf分配strongSelf),那么你基本上需要一個存儲“isDead”標志的地方,你在VC被解除分配時設置。 然后在使用weakSelf / strongSelf執行任何操作之前檢查此標志。 一個解決方案是:

  1. 你需要一個唯一的工作就是在成員變量中存儲這個“isDead”標志。 類似NSMutableBoolean的東西。 我不會寫出一個,它很簡單,只需要一個BOOL屬性。
  2. 在VC的-[NSObject init]方法中,您可以創建此標志對象的實例,該實例最初應設置為false
  3. 然后,您將此對象傳遞給您排隊等待以后執行的任何塊,以便塊自動保留/釋放它(即不經過弱/強舞)。 在塊中,您在使用weakSelf執行任何操作之前檢查標志是否仍為NO
  4. 關鍵當然是在VC的-[NSObject dealloc]方法中將標志設置為YES ,然后釋放它。 如果任何塊仍在等待執行,它們將自己保留標記對象,並且當它們稍后執行時,它們將查詢該標志,發現VC現在已經死亡。

這聽起來很麻煩(而且有點)但是想法是“isDead”標志位於 VC的范圍之外 ,因此不依賴於它的生命周期。 至於線程安全性,只要你只在VC的init / dealloc方法中設置/查詢標志,並且當塊執行時(在主線程上,而不是在后台線程上),它將是線程安全的。

在塊最終執行之前,我不希望我的VC保持活動狀態

但為什么這很重要? 一個VC的內存不應該那么多,如果塊在VC上執行任何UI操作,那也沒關系,因為VC無論如何都不會顯示。

基本上,如果VC不保留塊,則塊不應捕獲對VC的弱引用。 使用非歸零弱引用意味着您可以保證對象保持活動狀態,這不是這里的情況。 我建議你不要做這件弱事。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM