簡體   English   中英

Objective-C ARC:強vs保留,弱vs分配

[英]Objective-C ARC: strong vs retain and weak vs assign

ARC為屬性引入了兩個新的內存管理屬性,即strongweak

除了copy ,這顯然是完全不同的, strongretain之間以及weakassign之間是否存在差異?

根據我的理解,這里唯一的區別是, weak函數會將nil分配給指針,而assign不會,這意味着程序一旦釋放后將消息發送給指針,程序就會崩潰。 但是,如果我使用weak ,那將永遠不會發生,因為發送到nil消息不會做任何事情。

我不知道strongretain之間有什么區別。

有什么原因為什么我應該在新項目中使用assignretain ,還是被棄用?

在閱讀了許多Stackoverflow帖子和演示應用程序以檢查可變屬性屬性的文章之后,我決定將所有屬性信息放在一起:

  1. 原子//默認
  2. 非原子
  3. strong =保留//默認
  4. 保留
  5. 分配//默認
  6. unsafe_unretained
  7. 復制
  8. 只讀
  9. readwrite //默認

以下是詳細的文章鏈接,您可以在其中找到上述所有屬性,這些絕對會對您有所幫助。 非常感謝在這里給出最佳答案的所有人!!

iOS中的可變屬性屬性或修飾符

1.strong(iOS4 =保留)

  • 它說:“將其保留在堆中,直到我不再指向它為止”
  • 換句話說:“我是所有者,您無法在保留目標之前將其分配給目標對象”
  • 僅在需要保留對象時才使用Strong。
  • 默認情況下,所有實例變量和局部變量都是強指針。
  • 我們通常對UIViewControllers(UI項目的父對象)使用強
  • strong與ARC一起使用,它基本上可以幫助您,而不必擔心對象的保留計數。 完成后,ARC會自動為您釋放它。使用關鍵字Strong意味着您擁有該對象。

例:

@property (strong, nonatomic) ViewController *viewController;

@synthesize viewController;

2.弱 -

  • 它說:“只要有人堅決指出,就保持下去”
  • 與分配相同,沒有保留或釋放
  • “弱”引用是您不保留的引用。
  • 我們通常對IBOutlets(UIViewController的Childs)使用弱函數,這是有效的,因為子對象只需要與父對象一樣存在即可。
  • 弱引用是一種引用,它不能保護所引用的對象免受垃圾收集器的收集。
  • 弱本質上是賦值,是未保留的屬性。 除了對象被釋放時,弱指針會自動設置為nil

范例:

@property (weak, nonatomic) IBOutlet UIButton *myButton;

@synthesize myButton;

強弱解釋, 多虧了BJ Homer

想象我們的對象是一只狗,那只狗想逃跑(被釋放)。

強壯的指針就像拴在狗身上的皮帶。 只要您將皮帶拴在狗上,狗就不會跑開。 如果有五個人將皮帶拴在一只狗上(五個強力指針指向一個物體),則只有將所有五個皮帶分開后,狗才會逃跑。

另一方面,弱指針就像小孩指着狗說:“看!狗!” 只要那只狗仍系在皮帶上,小孩子仍然可以看見它,他們仍會指向它。 但是,一旦所有的皮帶都松開了,無論有多少小孩指向它,狗都會跑開。

一旦最后一個強指針(皮帶)不再指向對象,該對象將被釋放,所有弱指針將被清零。

什么時候用弱?

您唯一想使用弱函數的情況是,如果您想避免保留周期(例如,父母保留了孩子,而孩子保留了父母,因此都不會被釋放)。

3.保留=強

  • 它被保留,舊值被釋放並被分配了保留,指定應發送新值
  • 保留賦值並發送舊值-release
  • 保留與堅強相同。
  • 蘋果說,如果您寫保留,它將自動轉換/僅像強一樣工作。
  • 像“分配”這樣的方法包括一個隱式的“保留”

例:

@property (nonatomic, retain) NSString *name;

@synthesize name;

4.分配

  • 指定是默認值,僅執行變量分配
  • Assign是一個屬性屬性,它告訴編譯器如何綜合該屬性的setter實現
  • 我將對C基本屬性使用assign,對Objective-C對象的弱引用使用weak。

例:

@property (nonatomic, assign) NSString *address;

@synthesize address;

過渡到ARC發行說明 (有關屬性屬性的部分中的示例)。

// The following declaration is a synonym for: @property(retain) MyClass *myObject;

@property(strong) MyClass *myObject;

如此strongretain在屬性聲明中一樣。

對於ARC項目我會用strong ,而不是retain ,我會用assign對於C原始性能和weak的,以Objective-C對象的弱引用。

據我所知, strongretain是同義詞,因此它們的作用完全相同

然后, weak幾乎就像assign一樣,但是在它所指向的對象被釋放后自動設置為nil。

這意味着,您可以簡單地替換它們。

但是 ,我遇到一種特殊情況,我必須使用assign而不是weak 假設我們有兩個屬性delegateAssigndelegateWeak 在這兩者中都存儲了我們的代表,即通過擁有唯一的強引用來擁有我們。 委托正在釋放,因此我們的-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變量如何工作以及何時將其無效。

非原子/原子

  • 非原子比原子快得多
  • 始終使用非原子的,除非您對原子有非常特定的要求,這應該很少(原子不能保證線程安全-僅在同時由另一個線程設置該屬性時才停止訪問該屬性)

強/弱/分配

  • 使用strong來保留對象-盡管關鍵字retain是同義詞,但是最好使用strong來代替
  • 如果只需要一個不保留對象的指針,請使用函數-避免保留循環(即委托)很有用-當釋放對象時,它將自動使指針無效
  • 使用指定的primatives -釋放時完全一樣軟弱只是它不為零出對象(默認設置)

(可選的)

復制

  • 用它來創建對象的淺表副本
  • 始終設置要復制的不可變屬性的良好實踐-因為可變版本可以傳遞給不可變屬性,所以復制將確保您始終處理不可變對象
  • 如果傳入一個不可變的對象,它將保留它-如果傳入一個可變的對象,它將復制它

只讀

  • 使用它來禁用該屬性的設置(如果存在違規行為,則防止編譯代碼)
  • 您可以通過直接通過其實例變量更改變量,也可以在getter方法本身內更改getter傳遞的內容

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。

希望這可以幫助。

強大:

  • 屬性不會銷毀,但是只有將屬性設置為nil,對象才會被銷毀
  • 默認情況下,所有實例變量和局部變量都是強指針。
  • 僅在需要保留對象時才使用Strong。
  • 我們通常對UIViewControllers(UI項目的父對象)使用強
  • IOS 4(非ARC)我們可以使用保留關鍵字
  • IOS 5(ARC)我們可以使用強關鍵字

示例:@property(強,非原子)ViewController * viewController;

@synthesize viewController;

默認情況下自動獲取並設置為nil

  • 我們通常對IBOutlets(UIViewController的Childs)使用弱函數並進行委托
  • 與分配相同,沒有保留或釋放

示例:@屬性(弱,非原子)IBOutlet UIButton * myButton;

@synthesize myButton;

強和保留之間的區別:

  • 在iOS4中,強等於保留
  • 這意味着您擁有該對象並將其保留在堆中,直到不再指向它為止
  • 如果您寫保留,它將自動像強

弱和賦值之間的區別:

  • “弱”引用是您不會保留的引用,只要他人強烈指出,您就保留該引用
  • 當對象被“取消分配”時,弱指針將自動設置為nil
  • “賦值”屬性的屬性告訴編譯器如何綜合屬性的setter實現

暫無
暫無

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

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