这是一个setter方法的实现:
- (void)setCount:(NSNumber *)newCount {
[newCount retain];
[_count release];
// Make the new assignment.
_count = newCount;
}
如果retainCount
of _count
is <=0,它如何释放?
这是一个setter方法的实现:
- (void)setCount:(NSNumber *)newCount {
[newCount retain];
[_count release];
// Make the new assignment.
_count = newCount;
}
如果retainCount
of _count
is <=0,它如何释放?
唯一可以保留计数为 0 的有效对象是nil
. 并且发送任何消息nil
只返回 0 而不做任何其他事情,因此这种情况已涵盖。
如果你的意思是“这怎么能与一个释放的对象一起工作”——好吧,它不能。一个被释放的对象的保留计数并不是真正的 0,因为该对象不再存在——它已经被销毁,现在只是一块内存——所以它没有任何属性。对释放的对象做任何事情都是无效的,并且会发生什么是未定义的。
想象一个带有retainCount
实例变量的类。
@implementation MyClass
{
NSUInteger retainCount;
}
- (id) retain {
retainCount++;
return self;
}
- (void) release {
if (retainCount > 1)
retainCount--;
else
[self dealloc];
}
...
@end
一旦一个对象被释放,它就死了,消失了,完成了,等等......因此,将retainCount减为0是没有意义的,因为根据定义,对象将被释放并与一个释放的对象一起工作是未定义的行为。
上面是 NSObject 的确切逻辑,但是完全不同的实现(你真的不想看到 NSObject 的实际实现——这很痛苦)。
混淆的另一个来源似乎是引用的含义。
NSObject *foo;
char *bar;
NSUInteger baz;
出于所有意图和目的,上述三个变量声明的行为相同[在手动保留/释放中]。
当你说 时bar = "Hello, World!";
,你是在告诉编译器'复制包含字符串“Hello, World!”的内存地址。到名为bar
“”的内存中。同样foo
,只有您要复制包含该类实例的内存地址NSObject
。
现在,baz
可能看起来不一样了。但它确实不是,只是它包含数字,而不是地址。但是,真的,地址就是一个数字!
所以,在一个二传手::
- (void)setCount:(NSNumber *)newCount {
// increment newCount's retain count
[newCount retain];
// decrement the _count's retain count (which may cause it to be deallocated or not)
[_count release];
// copy the address of the memory that holds the NSNumber instance referenced
// by `newCount` into the instance variable `_count`.
_count = newCount;
}
该分配没有什么神奇的[在手动保留释放下]。它只是将一个数字从一个变量复制到另一个变量。对象完全不受此影响。