[英]iOS non-arc: should I use autorelease when self.property = [[Obj alloc] init]?
[英]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時,第一行將導致崩潰。 如何避免這種情況?
這與非ARC代碼中其他地方的非歸零弱引用(例如,委托等)存在相同的問題。(MRC沒有歸零弱引用;因此,它們是MRC中唯一的弱引用。然而,人們仍然能夠在ARC之前的日子里編寫安全代碼。)
基本上,解決方案是您需要清晰的所有權圖。 self
負責使區塊保持活力; 或其他一些對象負責使該塊保持活動狀態。
例如,對於委托,通常,“父”對象是“子”對象的委托。 在這種情況下,“父”對象負責使“子”對象保持活動狀態,因此“父”對象的壽命將超過“子”對象,因此反向引用可能很弱且很安全(因為子對象的方法可以只有在父對象還活着時才可以由父對象調用)。
另一方面,如果您具有異步操作,並且將該塊作為回調提供給該操作,則通常該操作負責保留該塊。 在這種情況下, self
將無法堅持。 並且該塊會強烈引用self
,因此完成該操作后,它仍然可以安全地執行對self
所需執行的任何操作。 實際上,無論對象self
是什么,使用它的人甚至都不需要保留它,因為它是由異步操作間接保留的,它可以只是創建,觸發和遺忘某種東西。
如果您有某些東西有時使塊self
保持活動,而有時又使其他塊保持活動,那么您應該重新考慮您的設計。 您說:“釋放自身后,在執行塊時可能會有條件”; 好,您應該描述您的整個設計以及如何實現。 因為通常情況下,對於異步執行的某些事情, self
不需要抓住該塊。
您的代碼確實令人困惑,沒有任何意義。 例如,為什么要分配給參數( 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.