关于ios:@property在Objective-C中保留,赋值,复制,非原子

@property retain, assign, copy, nonatomic in Objective-C

作为一个对Objective-C不熟悉的人,有人能给我一个关于遵循@property指令的保留、分配、复制和我缺少的任何其他内容的概述吗?他们在做什么?我为什么要用一个又一个?


在了解@property的属性之前,您应该知道@property的用途。好的。

  • @属性提供了一种定义类要封装的信息的方法。如果使用@property声明一个对象/变量,那么其他导入其类的类将可以访问该对象/变量。好的。

  • 如果在头文件中使用@property声明一个对象,那么必须在实现文件中使用@synthesis来合成它。这使得对象kvc兼容。默认情况下,编译器将为此对象合成访问器方法。好的。

  • 访问器方法有:setter和getter。好的。

例子:h好的。

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

m好的。

1
2
3
@implementation XYZClass
@synthesize name;
@end

现在编译器将为name合成访问器方法。好的。

1
2
3
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=方法、setter=方法、不安全的未保留好的。

  • 原子是默认行为。如果一个对象声明为原子对象,那么它就成为线程安全的。线程安全意味着,一次只有该类特定实例的一个线程可以控制该对象。好的。

如果线程正在执行getter方法,则其他线程无法对该对象执行setter方法。它很慢。好的。

1
2
@property NSString *name; //by default atomic`
@property (atomic)NSString *name; // explicitly declared atomic`
  • 非原子不是线程安全的。您可以使用非原子属性来指定合成的访问器只是直接设置或返回一个值,而不保证如果从不同的线程同时访问相同的值会发生什么。

因此,访问非原子属性比访问原子属性更快。好的。

1
@property (nonatomic)NSString *name;
  • 当属性是指向对象的指针时,需要保留。

setter方法将增加对象的保留计数,以便它将占用自动释放池中的内存。好的。

1
@property (retain)NSString *name;
  • 复制如果使用"复制",则不能使用"保留"。使用类的复制实例将包含它自己的副本。

即使设置了可变字符串并随后进行了更改,实例也会捕获设置时它拥有的任何值。不会合成setter和getter方法。好的。

1
@property (copy) NSString *name;

现在,好的。

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

名称将不受影响。好的。

  • 只读如果不希望通过setter方法更改属性,则可以将属性声明为只读。

编译器将生成getter,但不会生成setter。好的。

1
@property (readonly) NSString *name;
  • 读写是默认行为。不需要显式指定readwrite属性。

它与readonly相反。好的。

1
@property (readwrite) NSString *name;
  • assign将生成一个setter,它将值直接分配给实例变量,而不是复制或保留它。这最适合于nsinteger和cgloat之类的基本类型,或者不直接拥有的对象,例如委托。

记住,当启用垃圾收集时,retain和assign基本上是可互换的。好的。

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

它带有弧线。好的。

1
@property (nonatomic, strong) AVPlayer *player;
  • getter=method如果要对getter方法使用其他名称,可以通过向属性添加属性来指定自定义名称。

对于布尔属性(具有yes或no值的属性),getter方法通常以单词"is"开头。好的。

1
@property (getter=isFinished) BOOL finished;
  • setter=method如果要对setter方法使用其他名称,可以通过向属性添加属性来指定自定义名称。

该方法应以冒号结束。好的。

1
@property(setter = boolBool:) BOOL finished;
  • 不安全不存在cocoa和cocoa touch中有一些类还不支持弱引用,这意味着您不能声明弱属性或弱局部变量来跟踪它们。这些类包括nstextview、nsfont和nscollorspace等。如果需要使用对这些类之一的弱引用,则必须使用不安全的引用。

不安全引用类似于弱引用,因为它不会使相关对象保持活动状态,但如果目标对象被释放,则不会将其设置为nil。好的。

1
@property (unsafe_unretained) NSObject *unsafeProperty;

如果需要指定多个属性,只需将它们作为逗号分隔的列表包含,如下所示:好的。

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

好啊。


mage链接到的文章不再有效。下面是我在Objective-C中的(非常)短时间编码中学到的内容:

非原子与原子-"原子"是默认值。始终使用"非原子"。我不知道为什么,但我读到的那本书说"很少有理由"使用"原子"。(顺便说一句:我读的书是BNR的"iOS编程"一书。)

读写与只读-默认为"读写"。当你@synthesis时,将为你创建一个getter和一个setter。如果使用"readonly",则不会创建setter。将其用于对象实例化后不希望更改的值。

保留与复制与分配

  • "分配"是默认值。在@synthesis创建的setter中,该值将简单地分配给属性。我的理解是"assign"应该用于非指针属性。
  • 当属性是指向对象的指针时,需要使用"retain"。@synthesis生成的setter将保留(也就是添加保留计数)对象。完成后,需要释放对象。
  • 对象可变时需要"复制"。如果此时需要对象的值,并且不希望该值反映对象的其他所有者所做的任何更改,请使用此选项。完成后,您需要释放对象,因为您保留了副本。


在阅读了许多文章之后,我决定将所有属性信息放在一起:好的。

  • atomic //default
  • nonatomic
  • strong=retain //default
  • weak= unsafe_unretained
  • retain
  • assign //default
  • unsafe_unretained
  • copy
  • readonly
  • readwrite //default
  • 下面是详细文章的链接,您可以在其中找到这些属性。好的。

    非常感谢所有在这里给出最佳答案的人!!好的。

    Variable property attributes or Modifiers in iOS

    Ok.

    这是文章的样本描述好的。

  • 原子的-原子意味着只有一个线程访问变量(静态类型)。-原子是线程安全的。-但是它的性能很慢-原子是默认行为-非垃圾收集环境中的原子访问器(即使用retain/release/autorelease时)将使用锁确保另一个线程不会干扰值的正确设置/获取。-它实际上不是一个关键字。
  • 例子:好的。

    1
    2
    3
    @property (retain) NSString *name;

    @synthesize name;
  • 非原子的-非原子意味着多线程访问变量(动态类型)。-非原子是线程不安全的。-但是它的性能很快-非原子不是默认行为,我们需要在属性属性中添加非原子关键字。-当两个不同的进程(线程)同时访问同一个变量时,可能会导致意外的行为。
  • 例子:好的。

    1
    2
    3
    @property (nonatomic, retain) NSString *name;

    @synthesize name;

    说明:好的。

    假设有一个名为"name"的原子字符串属性,如果从线程a调用[self setname:@"a"]从线程B调用[self setname:@"b"],从线程C调用[self name],则不同线程上的所有操作都将连续执行,这意味着如果一个线程正在执行setter或getter,则其他线程将等待。这使属性"name"读/写安全,但如果另一个线程d同时调用[name release],则此操作可能会导致崩溃,因为此处不涉及setter/getter调用。这意味着对象是读/写安全的(原子的),但不是线程安全的,因为其他线程可以同时向对象发送任何类型的消息。开发人员应该确保这些对象的线程安全。好的。

    如果属性"name"是非原子的,那么上面示例中的所有线程(a、b、c和d)都将同时执行,从而产生任何不可预知的结果。在原子的情况下,a、b或c中的任何一个将首先执行,但d仍然可以并行执行。好的。

  • 强(ios4=保留)-上面写着"把这个放在堆里,直到我不再指向它"-换言之,"我是所有者,你不能在目标明确之前就把它处理掉,就像保留一样"-只有在需要保留对象时才使用强。-默认情况下,所有实例变量和局部变量都是强指针。-我们通常对uiviewcontrollers(ui项的父项)使用strong-STRONG与ARC一起使用,它基本上可以帮助您不必担心对象的保留计数。完成后,ARC会自动释放它。使用关键字STRONG表示您拥有对象。
  • 例子:好的。

    1
    2
    3
    @property (strong, nonatomic) ViewController *viewController;

    @synthesize viewController;
  • 弱(ios4=不安全-上面写着"只要有人强烈地指向它,就保持这个"-与分配相同,不保留或释放-"弱"引用是指不保留的引用。-我们通常对iboutlets(uiviewcontroller的子对象)使用weak,这是因为子对象仅只要父对象存在,就需要存在。-弱引用是不保护被引用对象不被垃圾收集器收集的引用。-弱本质上是分配的,是不包含的属性。除非当对象被释放时,弱指针自动设置为零
  • 例子:好的。

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

    @synthesize myButton;

    强和弱的解释,多亏了bj homer:好的。

    想象一下我们的目标是一只狗,而这只狗想逃跑(被释放)。有力的指针就像狗身上的皮带。只要你把皮带系在狗身上,狗就不会跑掉。如果五个人把他们的皮带系在一只狗上(五个有力的指针指向一个物体),那么这只狗不会逃跑,直到五条皮带都被解开。另一方面,弱指针就像小孩子指着狗说"看!狗!"只要狗还系着皮带,孩子们仍然能看到狗,他们还会指着它。不过,只要所有的皮带都断开,狗就会跑开,不管有多少小孩指着它。一旦最后一个强指针(皮带)不再指向某个对象,该对象将被释放,所有弱指针都将归零。当我们使用弱者?唯一一次你想使用弱的,是如果你想避免保留周期(例如,父母保留了孩子,而孩子保留了父母,所以两人都没有被释放)。好的。

  • 保持=强-保留旧值,释放旧值并分配-retain指定应发送的新值-分配时保留,发送的旧值-释放-保留与强保留相同。-苹果公司说,如果你写"保留",它将自动转换/工作像强。-"alloc"等方法包含隐式"retain"
  • 例子:好的。

    1
    2
    3
    @property (nonatomic, retain) NSString *name;

    @synthesize name;
  • 分配-赋值是默认值,只需执行变量赋值-assign是一个属性属性,它告诉编译器如何合成属性的setter实现。-我将使用assign表示c基元属性,使用weak表示对objective-c对象的弱引用。
  • 例子:好的。

    1
    2
    3
    @property (nonatomic, assign) NSString *address;

    @synthesize address;
  • 不安全的好的。

    -不安全的"未保留"是一个所有权限定符,它告诉ARC如何插入保留/释放调用-不安全的未保留是assign的arc版本。好的。

  • 例子:好的。

    1
    2
    3
    @property (nonatomic, unsafe_unretained) NSString *nickName;

    @synthesize nickName;
  • 复制-对象可变时需要复制。-copy指定应发送新值-copy on assignment和旧值sent-release。-复制类似于retain返回一个对象,在非垃圾收集环境中必须显式释放该对象(例如,在dealoc中)。-如果您使用copy,那么您仍然需要在dealloc中释放它。-如果此时需要对象的值,并且不希望该值反映其他人所做的任何更改,请使用此选项。对象的所有者。完成后,您需要释放对象,因为您保留了副本。
  • 例子:好的。

    1
    2
    3
    @property (nonatomic, copy) NSArray *myArray;

    @synthesize myArray;

    好啊。


    原子属性一次只能由一个线程访问。它是线程安全的。默认值为atomic。请注意,没有关键字atomic

    非逻辑意味着多个线程可以访问该项。它是线程不安全的

    所以在使用Atomic时应该非常小心,因为它会影响代码的性能。