簡體   English   中英

@property 在 Objective-C 中保留、分配、復制、非原子性

[英]@property retain, assign, copy, nonatomic in Objective-C

作為Objective-C的新手,有人可以給我一個關於保留、分配、復制以及我遺漏的任何其他內容的概述,遵循@property指令嗎? 他們在做什么,為什么我要使用一個而不是另一個?

在了解@property 的屬性之前,您應該知道@property 的用途是什么。

  • @property提供了一種定義類要封裝的信息的方法。 如果您使用@property聲明一個對象/變量,那么導入其類的其他類將可以訪問該對象/變量。

  • 如果你在頭文件中使用@property聲明一個對象,那么你必須在實現文件中使用@synthesize來合成它。 這使得對象KVC 兼容 默認情況下,編譯器會為此對象合成訪問器方法

  • 訪問器方法是:setter 和 getter。

示例:.h

@interface XYZClass : NSObject
@property (nonatomic, retain) NSString *name;
@end

.m

@implementation XYZClass
@synthesize name;
@end

現在編譯器將為name合成訪問器方法。

XYZClass *obj=[[XYZClass alloc]init];
NSString *name1=[obj name]; // get 'name'
[obj setName:@"liza"]; // first letter of 'name' becomes capital in setter method
  • @property的屬性列表

    原子、非原子、保留、復制、只讀、讀寫、分配、強、getter=method、setter=method、unsafe_unretained

  • atomic是默認行為。 如果一個對象被聲明為原子的,那么它就成為線程安全的。 線程安全意味着,一次只有該類特定實例的一個線程可以控制該對象。

如果線程正在執行 getter 方法,則其他線程無法對該對象執行 setter 方法。 它很慢。

@property NSString *name; //by default atomic`
@property (atomic)NSString *name; // explicitly declared atomic`
  • nonatomic不是線程安全的。 您可以使用 nonatomic 屬性屬性來指定合成訪問器只是直接設置或返回一個值,不保證如果從不同線程同時訪問相同值會發生什么。

出於這個原因,訪問非原子屬性比訪問原子屬性更快。

@property (nonatomic)NSString *name;   
  • 當屬性是指向對象的指針時需要保留

setter 方法會增加對象的保留計數,使其在自動釋放池中占用內存。

@property (retain)NSString *name;
  • 復制如果使用復制,則不能使用保留。 使用類的副本實例將包含它自己的副本。

即使設置了可變字符串並隨后更改,該實例也會捕獲它在設置時的任何值。 不會合成 setter 和 getter 方法。

@property (copy) NSString *name;

現在,

NSMutableString *nameString = [NSMutableString stringWithString:@"Liza"];    
xyzObj.name = nameString;    
[nameString appendString:@"Pizza"]; 

名稱將不受影響。

  • readonly如果不想讓屬性通過 setter 方法改變,可以將屬性聲明為 readonly。

編譯器將生成一個 getter,但不會生成一個 setter。

@property (readonly) NSString *name;
  • 讀寫是默認行為。 您不需要顯式指定 readwrite 屬性。

它與只讀相反。

@property (readwrite) NSString *name;
  • assign將生成一個 setter,它將值直接分配給實例變量,而不是復制或保留它。 這最適用於 NSInteger 和 CGFloat 等原始類型,或您不直接擁有的對象,例如委托。

請記住,啟用垃圾收集時,保留和分配基本上可以互換。

@property (assign) NSInteger year;
  • strong是保留的替代品。

它帶有ARC。

@property (nonatomic, strong) AVPlayer *player; 
  • getter=method如果要為 getter 方法使用不同的名稱,可以通過向屬性添加屬性來指定自定義名稱。

對於布爾屬性(具有 YES 或 NO 值的屬性),getter 方法通常以單詞“is”開頭

@property (getter=isFinished) BOOL finished;
  • setter=method如果要為 setter 方法使用不同的名稱,可以通過向屬性添加屬性來指定自定義名稱。

該方法應以冒號結尾。

@property(setter = boolBool:) BOOL finished;
  • unsafe_unretained Cocoa 和 Cocoa Touch 中有一些類尚不支持弱引用,這意味着您無法聲明弱屬性或弱局部變量來跟蹤它們。 這些類包括 NSTextView、NSFont 和 NSColorSpace 等。 如果需要對這些類之一使用弱引用,則必須使用不安全的引用。

不安全引用類似於弱引用,因為它不會保持其相關對象的活動狀態,但如果目標對象被釋放,則不會將其設置為nil

@property (unsafe_unretained) NSObject *unsafeProperty;

如果您需要指定多個屬性,只需將它們作為逗號分隔的列表包含,如下所示:

@property (readonly, getter=isFinished) BOOL finished;

MrMage 鏈接的文章不再有效。 所以,這是我在 Objective-C 中(非常)短時間編碼中學到的東西:

非原子與原子 - “原子”是默認值。 始終使用“非原子”。 我不知道為什么,但我讀過的書說“很少有理由”使用“原子”。 (順便說一句:我讀的書是 BNR“iOS 編程”書。)

readwrite 與 readonly - “readwrite”是默認值。 當您@synthesize 時,將為您創建一個 getter 和一個 setter。 如果您使用“只讀”,則不會創建任何 setter。 將它用於您不想在對象實例化后更改的值。

保留與復制與分配

  • “分配”是默認值。 在由@synthesize 創建的 setter 中,值將簡單地分配給屬性。 我的理解是“assign”應該用於非指針屬性。
  • 當屬性是指向對象的指針時,需要“保留”。 @synthesize 生成的 setter 將保留(也就是添加保留計數)對象。 完成后,您需要釋放對象。
  • 當對象可變時需要“復制”。 如果您需要當前對象的值,並且您不希望該值反映該對象的其他所有者所做的任何更改,請使用此選項。 完成后您需要釋放對象,因為您保留了副本。

看了很多文章我決定把所有的屬性信息放在一起:

  1. 原子 //默認
  2. 非原子的
  3. 強=保留//默認
  4. 弱 = unsafe_unretained
  5. 保持
  6. 賦值 //默認
  7. unsafe_unretained
  8. 復制
  9. 只讀
  10. 讀寫 //默認

下面是詳細文章的鏈接,您可以在其中找到這些屬性。

非常感謝所有在這里給出最佳答案的人!!

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

這是文章中的示例描述

  1. atomic -Atomic 表示只有一個線程訪問變量(靜態類型)。 -Atomic 是線程安全的。 - 但它的性能很慢 - 原子是默認行為 - 非垃圾收集環境中的原子訪問器(即使用保留/釋放/自動釋放時)將使用鎖來確保另一個線程不會干擾正確的設置/獲取的價值。 -它實際上不是關鍵字。

例子 :

@property (retain) NSString *name;

@synthesize name;
  1. 非原子-Nonatomic裝置多線程訪問的變量(動態型)。 -Nonatomic 是線程不安全的。 - 但它的性能很快 - Nonatomic 不是默認行為,我們需要在屬性屬性中添加 nonatomic 關鍵字。 - 當兩個不同的進程(線程)同時訪問同一個變量時,它可能會導致意外行為。

例子:

@property (nonatomic, retain) NSString *name;

@synthesize name;

解釋:

假設有一個原子字符串屬性叫做“name”,如果你從線程A調用[self setName:@"A"],從線程B調用[self setName:@"B"],然后從線程調用[self setName:@"B"]線程C,那么對不同線程的所有操作將串行執行,這意味着如果一個線程正在執行setter或getter,則其他線程將等待。 這使得屬性“name”讀/寫安全,但如果另一個線程 D 同時調用 [name release] ,則此操作可能會導致崩潰,因為此處不涉及 setter/getter 調用。 這意味着一個對象是讀/寫安全 (ATOMIC) 但不是線程安全的,因為另一個線程可以同時向該對象發送任何類型的消息。 開發人員應確保此類對象的線程安全。

如果屬性“name”是非原子的,那么上例中的所有線程——A、B、C 和 D 將同時執行,產生任何不可預測的結果。 在原子的情況下,A、B 或 C 中的任何一個將首先執行,但 D 仍然可以並行執行。

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

例子:

@property (strong, nonatomic) ViewController *viewController;

@synthesize viewController;
  1. (iOS4 = unsafe_unretained ) - 它說“只要其他人強烈地指向它,就保留它” - 與賦值相同,不保留或釋放 - “弱”引用是您不保留的引用。 - 我們一般對IBOutlets(UIViewController 的Childs)使用weak。這是因為子對象只需要在父對象存在時就存在。 -弱引用是不保護被引用對象不被垃圾收集器收集的引用。 -Weak 本質上是賦值,一種未保留的屬性。 除了對象被釋放時,弱指針自動設置為 nil

例子 :

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

@synthesize myButton;

強弱解釋,感謝 BJ Homer

想象一下我們的對象是一只狗,而這只狗想要逃跑(被釋放)。 強指針就像狗的皮帶。 只要你把皮帶拴在狗身上,狗就不會逃跑。 如果五個人將他們的皮帶拴在一只狗上(五個強烈的指針指向一個物體),那么在所有五根皮帶都松開之前,狗不會逃跑。 另一方面,弱指針就像小孩子指着狗說“看!一只狗!” 只要狗仍然被拴在皮帶上,小孩子仍然可以看到狗,他們仍然會指向它。 然而,一旦所有的皮帶都松開了,不管有多少小孩指着它,這只狗都會逃跑。 一旦最后一個強指針(leash)不再指向一個對象,該對象將被釋放,所有弱指針將被清零。 當我們使用弱? 您唯一想要使用弱的情況是,如果您想避免保留循環(例如,父項保留子項而子項保留父項,因此兩者都不會被釋放)。

  1. 保留= 強 - 它被保留,舊值被釋放並被分配 -retain 指定應該發送新值 -retain 在分配時發送舊值 -release -retain 與 strong 相同。 -apple 說如果你寫保留它會自動轉換/像強一樣工作。 -像“alloc”這樣的方法包括一個隱含的“保留”

例子:

@property (nonatomic, retain) NSString *name;

@synthesize name;
  1. assign -assign 是默認值,只是執行一個變量賦值 -assign 是一個屬性屬性,它告訴編譯器如何合成屬性的 setter 實現 -我將assign用於C原始屬性,weak用於對Objective-C對象的弱引用。

例子:

@property (nonatomic, assign) NSString *address;

@synthesize address;
  1. unsafe_unretained

    -unsafe_unretained 是所有權限定符,它告訴 ARC 如何插入保留/釋放調用 -unsafe_unretained 是分配的 ARC 版本。

例子:

@property (nonatomic, unsafe_unretained) NSString *nickName;

@synthesize nickName;
  1. 當對象是可變的時需要copy -copy。 -copy 指定應該發送新值 -copy 分配和發送舊值 -release。 -copy 就像保留返回一個對象,您必須在非垃圾收集環境中明確釋放(例如,在 dealloc 中)。 - 如果你使用 copy 那么你仍然需要在 dealloc 中釋放它。 - 如果您需要當前對象的值,並且您不希望該值反映該對象的其他所有者所做的任何更改,請使用此選項。 完成后您需要釋放對象,因為您保留了副本。

例子:

@property (nonatomic, copy) NSArray *myArray;

@synthesize myArray;

原子屬性一次只能被一個線程訪問。 它是線程安全的 默認是 atomic 。請注意沒有關鍵字atomic

非原子意味着多個線程可以訪問該項目。它是線程不安全的

所以在使用 atomic 時應該非常小心。因為它會影響代碼的性能

更喜歡這個關於iOS中objective-c屬性的鏈接......

https://techguy1996.blogspot.com/2020/02/properties-in-objective-c-ios.html

暫無
暫無

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

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