作为 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 atomic、nonatomic、retain、copy、readonly、readwrite、assign、strong、getter=method、setter=method、unsafe_unretained 的属性列表
atomic 是默认行为。如果一个对象被声明为原子的,那么它就成为线程安全的。线程安全意味着,一次只有该类的特定实例的一个线程可以控制该对象。
如果线程正在执行 getter 方法,则其他线程无法对该对象执行 setter 方法。它很慢。
@property NSString *name; //by default atomic`
@property (atomic)NSString *name; // explicitly declared atomic`
非原子不是线程安全的。您可以使用非原子属性来指定合成访问器直接设置或返回一个值,而不保证如果从不同线程同时访问相同的值会发生什么。
因此,访问非原子属性比访问原子属性更快。
@property (nonatomic)NSString *name;
当属性是指向对象的指针时,retain 是必需的。
setter 方法会增加对象的保留计数,从而占用自动释放池中的内存。
@property (retain)NSString *name;
复制如果使用复制,则不能使用保留。使用类的副本实例将包含它自己的副本。
即使设置了可变字符串并随后更改,该实例也会捕获它在设置时具有的任何值。不会合成任何 setter 和 getter 方法。
@property (copy) NSString *name;
现在,
NSMutableString *nameString = [NSMutableString stringWithString:@"Liza"];
xyzObj.name = nameString;
[nameString appendString:@"Pizza"];
名称将不受影响。
readonly 如果您不想通过 setter 方法更改属性,则可以将属性声明为只读。
编译器将生成一个 getter,但不会生成一个 setter。
@property (readonly) NSString *name;
读写是默认行为。您不需要明确指定 readwrite 属性。
它与只读相反。
@property (readwrite) NSString *name;
assign 将生成一个设置器,该设置器将值直接分配给实例变量,而不是复制或保留它。这对于 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 vs. readonly - “readwrite”是默认值。当您@synthesize 时,将为您创建一个 getter 和一个 setter。如果您使用“只读”,则不会创建任何设置器。将它用于在对象实例化后您不想更改的值。
保留 vs. 复制 vs. 分配
“分配”是默认值。在@synthesize 创建的setter 中,值将简单地分配给属性。我的理解是“分配”应该用于非指针属性。
当属性是指向对象的指针时,需要“保留”。 @synthesize 生成的 setter 将保留(也就是添加保留计数)对象。完成后,您将需要释放该对象。
当对象是可变的时,需要“复制”。如果您现在需要对象的值,并且您不希望该值反映对象的其他所有者所做的任何更改,请使用此选项。完成后您将需要释放该对象,因为您保留了副本。
atomic
与建议 nonatomic
一样糟糕。这两种选择都不是“正确”的选择,因此语言设计者选择了两种解决方案中更安全的一种。事实上 nonatomic
通常是更好的选择,因为它省略了极其昂贵的线程锁。使用 atomic
的唯一原因是您的属性可能是从多个线程设置的(在这种情况下,省略它会导致过度释放或泄漏)。
在阅读了很多文章后,我决定将所有属性信息放在一起:
atomic //默认非原子 strong=retain //默认 weak= unsafe_unretained retain assign //默认 unsafe_unretained copy readonly readwrite //default
下面是详细文章的链接,您可以在其中找到这些属性。
非常感谢所有在这里给出最佳答案的人!!
iOS 中的可变属性属性或修饰符
这是文章中的示例描述
atomic -Atomic 意味着只有一个线程访问变量(静态类型)。 -Atomic 是线程安全的。 - 但它的性能很慢 - 原子是默认行为 - 非垃圾收集环境中的原子访问器(即使用保留/释放/自动释放时)将使用锁来确保另一个线程不会干扰正确的设置/获取的价值。 - 它实际上不是关键字。
例子 :
@property (retain) NSString *name;
@synthesize name;
nonatomic -Nonatomic 表示多线程访问变量(动态类型)。 -Nonatomic 是线程不安全的。 - 但它的性能很快 - 非原子不是默认行为,我们需要在属性属性中添加非原子关键字。 - 当两个不同的进程(线程)同时访问同一个变量时,可能会导致意外的行为。
例子:
@property (nonatomic, retain) NSString *name;
@synthesize name;
解释:
假设有一个名为“name”的原子字符串属性,如果你从线程 A 调用 [self setName:@"A"],从线程 B 调用 [self setName:@"B"],从线程 B 调用 [self name]线程 C,则不同线程上的所有操作将串行执行,这意味着如果一个线程正在执行 setter 或 getter,则其他线程将等待。这使得属性“name”读/写安全,但如果另一个线程 D 同时调用 [name release],则此操作可能会产生崩溃,因为这里不涉及 setter/getter 调用。这意味着一个对象是读/写安全的(ATOMIC)但不是线程安全的,因为另一个线程可以同时向对象发送任何类型的消息。开发人员应确保此类对象的线程安全。
如果属性“name”是非原子的,那么上面示例中的所有线程 - A、B、C 和 D 将同时执行,产生任何不可预知的结果。在原子的情况下,A、B 或 C 中的任何一个将首先执行,但 D 仍然可以并行执行。
强(iOS4 = 保留)-它说“将其保留在堆中,直到我不再指向它为止”-换句话说,“我是所有者,您不能在使用与保留相同的目标之前解除分配”-只有在需要保留对象时才使用 strong 。 - 默认情况下,所有实例变量和局部变量都是强指针。 - 我们通常将 strong 用于 UIViewControllers(UI 项的父项) -strong 与 ARC 一起使用,它基本上可以帮助您,不必担心对象的保留计数。完成后,ARC 会自动为您释放它。使用关键字 strong 意味着您拥有该对象。
例子:
@property (strong, nonatomic) ViewController *viewController;
@synthesize viewController;
弱(iOS4 = unsafe_unretained)-它说“只要其他人强烈指向它就保留它”-与分配相同,不保留或释放-“弱”引用是您不保留的引用。 - 我们通常对 IBOutlets(UIViewController 的 Childs)使用weak。这是因为子对象只需要与父对象一样存在。 - 弱引用是不保护被引用对象不被垃圾收集器收集的引用。 -Weak 本质上是赋值,一个未保留的属性。除了当对象被释放时,弱指针自动设置为 nil
例子 :
@property (weak, nonatomic) IBOutlet UIButton *myButton;
@synthesize myButton;
强&弱解释,Thanks to BJ Homer:
想象我们的对象是一只狗,而这只狗想要逃跑(被释放)。强指针就像狗的皮带。只要你把皮带拴在狗身上,狗就不会逃跑。如果五个人将他们的皮带拴在一只狗身上(五个强指针指向一个物体),那么在所有五根皮带都脱离之前,狗不会逃跑。另一方面,弱指针就像小孩子指着狗说“看!一条狗!”只要狗还在皮带上,小孩子仍然可以看到狗,他们仍然会指向它。然而,一旦所有的皮带都松开了,不管有多少小孩指着它,狗都会跑掉。一旦最后一个强指针(leash)不再指向一个对象,这个对象就会被释放,所有的弱指针都会被清零。当我们使用弱?您唯一想使用弱的情况是,如果您想避免保留循环(例如,父母保留孩子,孩子保留父母,因此两者都不会被释放)。
retain = strong - 保留,释放旧值并分配 -retain 指定应发送新值 -retain 分配时发送旧值 -release -retain 与 strong 相同。 -apple 说如果你写保留它只会自动转换/像强一样工作。 - 像“alloc”这样的方法包括一个隐含的“retain”
例子:
@property (nonatomic, retain) NSString *name;
@synthesize name;
assign -assign 是默认值,只是执行变量赋值 -assign 是一个属性属性,它告诉编译器如何合成属性的 setter 实现 -我将 assign 用于 C 原始属性,weak 用于对 Objective-C 对象的弱引用。
例子:
@property (nonatomic, assign) NSString *address;
@synthesize address;
unsafe_unretained -unsafe_unretained 是一个所有权限定符,它告诉 ARC 如何插入保留/释放调用 -unsafe_unretained 是分配的 ARC 版本。
例子:
@property (nonatomic, unsafe_unretained) NSString *nickName;
@synthesize nickName;
当对象是可变的时,需要 copy -copy。 -copy 指定应在分配时发送新值 -copy 并发送旧值 -release。 -copy 就像retain 返回一个你必须在非垃圾收集环境中显式释放(例如,在dealloc 中)的对象。 - 如果您使用副本,那么您仍然需要在 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
不定期副业成功案例分享
@property
声明一个对象,那么您必须在实现文件中使用@synthesize
合成它。”不总是。例如,“默认情况下,readwrite
属性将由实例变量支持,该变量将再次由编译器自动合成。”从 doc。