繁体   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