簡體   English   中英

在非弧形環境中的塊內使用self和self屬性

[英]Using self and self properties inside a block in non-arc environment

Non-ARC環境中使用self內部塊時,我一直在使用塊並熟悉內存管理。

但是我有兩個具體問題:

1)我知道我可以使用__block來避免保留循環,而保留循環又可以使用self來創建,如下所示:

__block MyClass *blockSelf = self; 
self.myBlock = ^{  
     blockSelf.someProperty = abc;  
     [blockSelf someMethod]; 
};

這肯定會避免保留周期,但是通過這樣做,我為自我釋放創建了一個范圍,並最終被其他人釋放。 因此,當這種情況發生時,self消失了,而blockSelf指向了一個垃圾值。 在某些情況下,將自身釋放后執行該塊時,該塊將在嘗試使用釋放實例時崩潰。 我們如何避免這種情況? 如何在執行塊時檢查blockSelf是否有效,或者在釋放self時停止執行塊。

2)在類似的行上,假設我使用如下所示的代碼塊:

__block MyClass *blockSelf = self; 
self.myBlock = ^{  
         [blockSelf someMethod:blockSelf.someProperty]; 
    };

// I am taking someProperty in an method argument
-(void) someMethod:(datatype*)myClassProperty
{
  myClassProperty = abc;
}

現在可能存在一些情況,其中self未被釋放,但是someProperty在someMethod的執行開始之前被釋放(當有多個線程時,可能會發生這種情況)。 即使我做self.someProperty = nil; 當發布時,myClassProperty不是nil並指向一些垃圾,因此當執行someMethod時,第一行將導致崩潰。 如何避免這種情況?

  1. 這與非ARC代碼中其他地方的非歸零弱引用(例如,委托等)存在相同的問題。(MRC沒有歸零弱引用;因此​​,它們是MRC中唯一的弱引用。然而,人們仍然能夠在ARC之前的日子里編寫安全代碼。)

    基本上,解決方案是您需要清晰的所有權圖。 self負責使區塊保持活力; 或其他一些對象負責使該塊保持活動狀態。

    例如,對於委托,通常,“父”對象是“子”對象的委托。 在這種情況下,“父”對象負責使“子”對象保持活動狀態,因此“父”對象的壽命將超過“子”對象,因此反向引用可能很弱且很安全(因為子對象的方法可以只有在父對象還活着時才可以由父對象調用)。

    另一方面,如果您具有異步操作,並且將該塊作為回調提供給該操作,則通常該操作負責保留該塊。 在這種情況下, self將無法堅持。 並且該塊會強烈引用self ,因此完成該操作后,它仍然可以安全地執行對self所需執行的任何操作。 實際上,無論對象self是什么,使用它的人甚至都不需要保留它,因為它是由異步操作間接保留的,它可以只是創建,觸發和遺忘某種東西。

    如果您有某些東西有時使塊self保持活動,而有時又使其他塊保持活動,那么您應該重新考慮您的設計。 您說:“釋放自身后,在執行塊時可能會有條件”; 好,您應該描述您的整個設計以及如何實現。 因為通常情況下,對於異步執行的某些事情, self不需要抓住該塊。

  2. 您的代碼確實令人困惑,沒有任何意義。 例如,為什么要分配給參數( myClassProperty )? 無論如何,要傳遞參數時傳遞參數的意義何在? 為什么要命名局部變量“ myClassProperty ”?

    我想您要問的是訪問一個可以在不同線程上更改的屬性,以及如何處理該內存的管理。 (此問題與塊或ARC / MRC無關。在ARC中同樣是一個問題。)

    答案是您需要一個原子屬性。 您可以將同步屬性atomic ,或者如果知道如何手動實現atomic屬性。 對象指針類型的原子屬性需要做的是它的getter不僅需要返回基礎變量,還需要保留並自動釋放它,並返回結果。 在getter中的檢索和保留發生在與setter的關鍵部分同步的關鍵部分中,包括釋放舊值和保留新值。 基本上,這種同步保證了在檢索值並將其保留在getter中之間不會在setter中釋放該值。 從getter返回的值將保留並自動釋放,因此可以保證在作用域內該值仍然有效。

解決方案2)

__block MyClass *blockSelf = self; 
self.myBlock = ^{
         datatype* p = [blockSelf.someProperty retain];
         [blockSelf someMethod:p]; 
         [p release];
    };

// I am taking someProperty in an method argument
-(void) someMethod:(datatype*)myClassProperty
{
  myClassProperty = abc;
}

1)不知道如何使用myBlock 如果僅由self ,那么一切都會好的。 如果它是被一些其他的對象,那么它也應該保持在參考self再有就是也都將被罰款。

暫無
暫無

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

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