我知道这已被讨论过,但我只是没有得到一些内存管理。我知道retain会使对象保持活动状态,copy会为对象提供一个单独的对象副本。
我不知道的是当涉及到ivars&属性,保留为属性意味着setter释放旧值&保留新的:
property = newValue;
// retain
if (property != newValue)
{
[property release];
property = [newValue retain];
}
但是我看过他们将静态字符串分配给retain属性的示例,例如。
self.stringProperty = @"something";
(some other code)
self.stringProperty = @"somethingElse";
第二次调用set string应该调用静态字符串上的release是不允许的,为什么程序不会崩溃?
此外,如果使用retain属性声明一个对象&然后用init分配一些东西,例如
@property(retain)someArray;
someArray = [[NSArray alloc] initWithArray:arbArray];
这是否意味着someArray现在的保留计数为2,但如果它是用
创建的someArray = [NSArray arrayWithArray:arbArray];
保留计数仅为1,因为第二个是工厂方法?
答案 0 :(得分:3)
第二次调用set string应该调用静态字符串上的release是不允许的,为什么程序不会崩溃?
您可以将release
传递给常量字符串,它不会做任何有意义的事情,因此这些代码行是有效的。
这是否意味着someArray现在的保留计数为2,但如果它是用...创建的,则保留计数仅为1,因为第二个是工厂方法?
嗯,首先,
someArray = [[NSArray alloc] initWithArray:arbArray];
不使用@property
创建的方法,只是直接访问ivar。要使用属性方法,您必须使用self.someArray = ...;
。
但是,是的,
[[NSArray alloc] initWithArray:arbArray]
返回有效保留计数为1的对象,
[NSArray arrayWithArray:arbArray]
返回有效保留计数为0的对象,因此,如果 通过@property
创建的“保留”设置器传递它们,则ivar的有效保留计数为分别为2和1。
答案 1 :(得分:0)
这是一个问题,但无论如何......
静态字符串在很多方面都是特殊情况,其中一种方法是,您可以retain
和release
将它们放在心中,而不会产生任何影响。
另外,NString
属性通常具有copy
而不是retain
语义,如果重要的话,无论如何都会消除该问题。但事实并非如此。
在第二种情况下,直接从retain
(或alloc
或其他所有权授予电话)分配copy
属性是不好的做法,除非您主动添加相应的release
之后,或autorelease
期间,例如:
self.someArray = [[[NSArray alloc] initWithArray:arbArray] autorelease];
但是在这种特殊情况下,没有理由不使用类方法。
答案 2 :(得分:0)
第二次调用set string应该调用静态字符串上的release是不允许的,为什么程序不会崩溃?
它不是一个静态字符串,它是一个常量字符串。但是,这与问题无关,但实际上您可以发送-retain到从NSObject 派生的任何Objective-C对象,除了 NSAutoreleasePool。如果你看看一个常量NSString的retainCount(有点顽皮,但是因为我们正在讨论实现,OK),例如。
NSLog(@"retain count = %u", [@"foo" retainCount]);
你很可能会发现它被设置为一个非常大的数字(实际上是UINT_MAX)。这是运行时忽略释放和保留调用的信号。
顺便说一下,忘记释放对象不会立即导致程序崩溃。实际上,如果你有大量的RAM,在操作系统开始交换之前你可能不会注意到。
这是否意味着someArray现在的保留计数为2,但如果它是用
创建的
不,因为您没有使用该属性来分配新数组,所以您直接进入了ivar:
self.someArray = [[NSArray alloc] initWithArray:arbArray];
会泄漏。
self.someArray = [NSArray arrayWithArray:arbArray];
没关系。