[英]Objective-C ARC: strong vs retain and weak vs assign
ARC為屬性引入了兩個新的內存管理屬性,即strong
和weak
。
除了copy
,這顯然是完全不同的, strong
和retain
之間以及weak
和assign
之間是否存在差異?
根據我的理解,這里唯一的區別是, weak
函數會將nil
分配給指針,而assign
不會,這意味着程序一旦釋放后將消息發送給指針,程序就會崩潰。 但是,如果我使用weak
,那將永遠不會發生,因為發送到nil
消息不會做任何事情。
我不知道strong
和retain
之間有什么區別。
有什么原因為什么我應該在新項目中使用assign
和retain
,還是被棄用?
在閱讀了許多Stackoverflow帖子和演示應用程序以檢查可變屬性屬性的文章之后,我決定將所有屬性信息放在一起:
以下是詳細的文章鏈接,您可以在其中找到上述所有屬性,這些絕對會對您有所幫助。 非常感謝在這里給出最佳答案的所有人!!
1.strong(iOS4 =保留)
例:
@property (strong, nonatomic) ViewController *viewController;
@synthesize viewController;
2.弱 -
范例:
@property (weak, nonatomic) IBOutlet UIButton *myButton;
@synthesize myButton;
強弱解釋, 多虧了BJ Homer :
想象我們的對象是一只狗,那只狗想逃跑(被釋放)。
強壯的指針就像拴在狗身上的皮帶。 只要您將皮帶拴在狗上,狗就不會跑開。 如果有五個人將皮帶拴在一只狗上(五個強力指針指向一個物體),則只有將所有五個皮帶分開后,狗才會逃跑。
另一方面,弱指針就像小孩指着狗說:“看!狗!” 只要那只狗仍系在皮帶上,小孩子仍然可以看見它,他們仍會指向它。 但是,一旦所有的皮帶都松開了,無論有多少小孩指向它,狗都會跑開。
一旦最后一個強指針(皮帶)不再指向對象,該對象將被釋放,所有弱指針將被清零。
什么時候用弱?
您唯一想使用弱函數的情況是,如果您想避免保留周期(例如,父母保留了孩子,而孩子保留了父母,因此都不會被釋放)。
3.保留=強
例:
@property (nonatomic, retain) NSString *name;
@synthesize name;
4.分配
例:
@property (nonatomic, assign) NSString *address;
@synthesize address;
從過渡到ARC發行說明 (有關屬性屬性的部分中的示例)。
// The following declaration is a synonym for: @property(retain) MyClass *myObject;
@property(strong) MyClass *myObject;
如此strong
與retain
在屬性聲明中一樣。
對於ARC項目我會用strong
,而不是retain
,我會用assign
對於C原始性能和weak
的,以Objective-C對象的弱引用。
據我所知, strong
和retain
是同義詞,因此它們的作用完全相同 。
然后, weak
幾乎就像assign
一樣,但是在它所指向的對象被釋放后自動設置為nil。
這意味着,您可以簡單地替換它們。
但是 ,我遇到一種特殊情況,我必須使用assign
而不是weak
。 假設我們有兩個屬性delegateAssign
和delegateWeak
。 在這兩者中都存儲了我們的代表,即通過擁有唯一的強引用來擁有我們。 委托正在釋放,因此我們的-dealloc
方法也被調用。
// Our delegate is deallocating and there is no other strong ref.
- (void)dealloc {
[delegateWeak doSomething];
[delegateAssign doSomething];
}
委托已經在釋放過程中,但是仍然沒有完全釋放。 問題在於, 對他的weak
引用已被廢除! 屬性delegateWeak
包含nil,但是delegateAssign
包含有效的對象(所有屬性已經釋放並無效,但仍然有效)。
// Our delegate is deallocating and there is no other strong ref.
- (void)dealloc {
[delegateWeak doSomething]; // Does nothing, already nil.
[delegateAssign doSomething]; // Successful call.
}
這是一個非常特殊的情況,但它向我們揭示了那些weak
變量如何工作以及何時將其無效。
Clang關於Objective-C自動參考計數(ARC)的文檔清楚地解釋了所有權限定符和修飾符:
有四個所有權限定符:
- __ 自動釋放
- __ 強
- __ * unsafe_unretained *
- __ 弱
如果類型具有__ 自動釋放 ,__ 強或__ 弱的資格,那么它就是擁有所有權的資格。
然后,對聲明的屬性有六個所有權修飾符:
- 分配意味着__ * unsafe_unretained *所有權。
- 復制意味着__ 強大的所有權,以及setter上復制語義的通常行為。
- 保留意味着__ 強大的所有權。
- 強暗示__ 強所有權。
- * unsafe_unretained *意味着__ * unsafe_unretained *所有權。
- 弱意味着__所有權弱 。
除了weak以外 ,這些修飾符在非ARC模式下可用。
在語義上,所有權限定詞在五個托管操作中具有不同的含義:讀取,分配,初始化,銷毀和移動,在大多數情況下,我們大多數時候只關心分配操作中的差異。
評估賦值運算符時發生轉讓 。 語義因條件而異:
- 對於__個強對象,首先保留新的pointe; 第二,左值加載了原始語義; 第三,用原始語義將新的pointe存儲到左值中。 最后,老尖兵被釋放。 這不是原子執行的; 面對並發的加載和存儲,必須使用外部同步來使其安全。
- 對於__個弱對象,除非新指針是當前正在釋放的對象,否則將更新左值以指向新指針,在這種情況下,左值將更新為空指針。 對於對象的其他分配,從對象的讀取以及新指針的最終釋放,這必須原子執行。
- 對於__ * unsafe_unretained *對象,使用原始語義將新的指針存儲到左值中。
- 對於__ 自動釋放對象,將使用原始語義保留,自動釋放新指針並將其存儲在左值中。
讀取,初始化,破壞和移動方面的其他區別,請參閱文檔中的第4.2節“語義” 。
為了理解強弱參考,請考慮以下示例,假設我們有一個名為displayLocalVariable的方法。
-(void)displayLocalVariable
{
NSString myName = @"ABC";
NSLog(@"My name is = %@", myName);
}
在上述方法中,myName變量的作用域僅限於displayLocalVariable方法,一旦方法完成,保存字符串“ ABC”的myName變量將從內存中釋放。
現在,如果我們想在整個視圖控制器生命周期中保留myName變量值,該怎么辦。 為此,我們可以創建名為username的屬性,該屬性具有對變量myName的強引用(請參見以下代碼中的self.username = myName;
),如下所示,
@interface LoginViewController ()
@property(nonatomic,strong) NSString* username;
@property(nonatomic,weak) NSString* dummyName;
- (void)displayLocalVariable;
@end
@implementation LoginViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
-(void)viewWillAppear:(BOOL)animated
{
[self displayLocalVariable];
}
- (void)displayLocalVariable
{
NSString myName = @"ABC";
NSLog(@"My name is = %@", myName);
self.username = myName;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
@end
現在,在上面的代碼中,您可以看到myName已分配給self.username,並且self.username具有對myName的強引用(如我們在接口中使用@property在接口中聲明的那樣)(間接具有對“ ABC”字符串的強引用)。 因此,直到self.username處於活動狀態時,字符串myName才會從內存中釋放。
現在考慮將myName分配給一個虛弱引用的dummyName,self.dummyName = myName; 與強引用不同,弱將僅保留myName直到存在對myName的強引用。 請參閱以下代碼以了解弱引用,
-(void)displayLocalVariable
{
NSString myName = @"ABC";
NSLog(@"My name is = %@", myName);
self.dummyName = myName;
}
在上面的代碼中,對myName的引用較弱(即self.dummyName對myName的引用較弱),但對myName沒有強引用,因此self.dummyName將無法保存myName值。
現在再次考慮以下代碼,
-(void)displayLocalVariable
{
NSString myName = @"ABC";
NSLog(@"My name is = %@", myName);
self.username = myName;
self.dummyName = myName;
}
在上面的代碼中,self.username具有對myName的強引用,因此,即使方法結束后,self.dummyName現在也具有myName的值,因為myName具有與之關聯的Strong引用。
現在,每當我們對變量進行強引用時,其保留計數將增加一,並且該變量將不會被釋放,保留計數將達到0。
希望這可以幫助。
示例:@property(強,非原子)ViewController * viewController;
@synthesize viewController;
默認情況下自動獲取並設置為nil
示例:@屬性(弱,非原子)IBOutlet UIButton * myButton;
@synthesize myButton;
強和保留之間的區別:
弱和賦值之間的區別:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.