5

谁能解释设置someObject = someOtherObject;self.someObject = someOtherObject;someObject 是否是使用 @property (nonatomic, retain) SomeType someObject; 创建的类属性之间的区别?

为了澄清我有类似的东西:

@interface SomeClass : NSObject {
   SomeType* someObject;
}

@property (nonatomic, retain) SomeType* someObject;

@end

我注意到有时当我使用没有 self 的属性时,我会得到 EXC_BAD ACCESS ,这似乎很随机。当我使用 self 时,我的程序会按应有的方式运行。当我跳过 self 时,我没有收到任何编译器错误或警告,所以我猜它是某种有效的语法?

4

4 回答 4

5

self.someObject = someOtherObject使用该财产。属性为您生成 setter 和 getter。在您的情况下,您将retain属性赋予属性,这意味着通过此属性设置的对象将自动收到一条retain消息,将其保留计数增加 1。此外,成员变量的旧值会发送一条release消息,减少其保留计数保留计数。

当对象的保留计数达到 0 时,对象将被释放。如果您尝试访问已释放的对象(例如,如果您尝试过于频繁地释放它),则会收到 EXC_BAD_ACCESS 异常。

在你的情况下:

SomeOtherObject *soo = [[SomeOtherObject alloc] init]; //retain count: 1
self.someObject = soo; //soo's retain count is now 2
[soo release]; //soo's retain count is 1 again, as self still uses it.
[self doSomethingWithSoo];

但是,如果您不使用 setter,则不得释放soo.

SomeOtherObject *soo = [[SomeOtherObject alloc] init]; //retain count: 1
someObject = soo; //soo's retain count is still  1
[soo release]; //soo's retain count is 0, it will be deallocated
[self doSomethingWithSoo]; //will fail with an EXC_BAD_ACCESS exception, as soo does not exist anymore.
于 2011-02-03T09:26:41.017 回答
2

属性只是访问数据的一种便捷方式。所以当你声明属性 @property (nonatomic, retain) SomeType* someObject; 这意味着在访问期间将合成 2 种方法:

吸气剂:

-(SomeType*) someObject {
   return someObject;
}

二传手

-(void) setSomeObject:(SomeType*) obj {
   [someObject release];
   someObject = [obj retain];
}

因此,properties 和 ivars 之间的主要区别在于 properties 动态创建 setter/getter 方法(并且您可以覆盖它们)。但是当您编写 someObject = new_val 时,您只是将引用复制到内存位置。除了一个汇编指令外,这里没有做任何额外的工作。

还有一件事要提:原子的和非原子的。使用 atomic 时,合成的 setter/getter 将确保始终从 getter 返回整个值或由 setter 设置,而不管任何其他线程上的 setter 活动。也就是说,如果线程 A 在 getter 的中间,而线程 B 调用 setter,则实际可行的值——很可能是一个自动释放的对象——将返回给 A 中的调用者。

在非原子中,没有这样的保证。因此,非原子比原子快得多。

编辑:因此,如果您有一些变量,可以从不同的线程访问或/并且必须完成一些额外的工作(例如保留,引发一些标志......),那么您的选择就是财产。但有时你有一个变量,它经常被访问,通过属性访问会导致很大的开销,因为处理器必须执行更多的操作来合成和调用方法。

于 2011-02-03T09:22:47.613 回答
1

这都是关于内存管理的。

您的类属性在 .h / .m 文件中someObject生成了带有注释@property/的访问器。@synthsize

当您使用 访问您的财产时someObject,您可以直接访问该财产。当您访问时,self.someObject您正在调用访问[self someObject]器来为您管理内存。

因此,当您需要分配一个类属性时,这样做会更干净,self.someObject = someOtherObject;因为您使用 setter 并且不必关心释放和保留。当您的 setter 生成时@property (nonatomic, retain),它会为您保留。

于 2011-02-03T09:27:46.490 回答
0

两者的区别在于:

1)当你不使用“self”时。您将结果直接分配给成员变量。

2)当你使用“自我”时。您正在对该属性调用 setter 方法。与 [self setMyObject:...]; 相同

所以在self.myobject的情况下,它会保留它的retain,而在其他情况下,(没有self),如果你不使用alloc,那么它将被视为自动释放的对象。

在大多数情况下,您会发现您想要使用“self.”,除非在对象初始化期间。

顺便说一句,你也可以使用self.someObject = [someOtherObject retain]增加保留计数器

于 2011-02-03T09:27:03.747 回答