Setter 方法真的在 Obj-C 中做吗?
Posted
技术标签:
【中文标题】Setter 方法真的在 Obj-C 中做吗?【英文标题】:Setter method really do in Obj-C? 【发布时间】:2013-04-09 17:16:11 【问题描述】:这里是一个setter方法的实现:
- (void)setCount:(NSNumber *)newCount
[newCount retain];
[_count release];
// Make the new assignment.
_count = newCount;
如果retainCount
的_count
是
【问题讨论】:
你怎么知道retainCount 一种“吸气剂”方法?你是说二传手吗? @Anoop:假设发生了 为什么实际保留计数在这里很重要?只要对象retain
s 包含它所引用的内容,并为每个retain
发出一个release
,它的工作就应该完成。如果您始终如一地这样做,那么您甚至不需要关心实际的保留计数。
@JustSid 不,如果对象在引用计数为 1 时被设置回自身,那就错了。然后它被释放、解除分配,并保留悬空指针。
【参考方案1】:
唯一可以保留计数为 0 的有效对象是 nil
。并且向nil
发送任何消息只会返回 0 而不执行任何其他操作,因此这种情况已涵盖。
如果你的意思是“这怎么能与一个被释放的对象一起工作”——好吧,它不能。一个被释放的对象的保留计数并不是真正的 0,因为这个对象不再存在——它已经被销毁,现在只是一块内存——所以它没有任何属性。对释放的对象做任何事情都是无效的,将会发生什么是未定义的。
【讨论】:
@DungProton:是的。它在引用计数达到 0 时发送dealloc
。它不会在将来的某个时候被标记和释放——它会在那时被释放。即使这实际上没有发生,这些也是操作的语义,因此任何依赖于对象在上次发布后仍处于活动状态的代码都是不正确的。
@DungProton:两者都有。如果保留计数为 1,release
会将其设为 0。将其设为 0 会使对象可破坏,因此 release
会破坏对象。
@DungProton:如果调用 release
时保留计数为 1,则该版本为 0。您可以将发布视为这样实现:if (--myRetainCount == 0) [self dealloc];
。 (这实际上不是它的实现方式,但它几乎是这样工作的。)
@DungProton:我很确定在正常情况下,对象在收到最后一个版本后会立即释放。您可以阅读 Objective-C 运行时的源代码并亲自查看。内存被释放,然后可以被其他分配使用。指针本身并没有被破坏——没有“破坏”指针值这样的事情——它只是不再有效。
@RobNapier:即使是“你会崩溃”的假设也太多了。几乎任何事情都可能发生,但从长远来看,几乎没有什么是好的。【参考方案2】:
想象一个具有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
可能看起来不同了。但它确实不是,只是它包含数字,而不是地址。但是,实际上,地址就是一个数字!
所以,在 setter 中::
- (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;
[在手动保留版本下]该分配没有什么神奇之处。它只是将一个数字从一个变量复制到另一个变量。对象完全不受此影响。
【讨论】:
以上是关于Setter 方法真的在 Obj-C 中做吗?的主要内容,如果未能解决你的问题,请参考以下文章