【问题标题】:Reusing NSObjects by Overriding release in Obj-C通过覆盖 Obj-C 中的发布来重用 NSObject
【发布时间】:2011-09-28 07:22:37
【问题描述】:

我正在使用单例类实现对象重用方案。

我做的基本上是:

MyClass* obj = [[MyClassBank sharedBank] getReusableItem];

bank 只是一个 NSMutableSet,它经过调整以实现最佳的可重用性。当我愉快地实现这个 Singleton 时,我想到当我用完“obj”后我会做以下事情:

[[MyClassBank sharedBank] doneWithItem:obj];

目前,如果我以这种方式在哪里使用它,我的代码会起作用,但后来我意识到我有时会在“NSCollection”中添加“obj”,有时我会调用:

[theCollection removeAllObjects];

起初我想创建一个由集合组成的自己的类,然后我会迭代集合中的对象并调用:

[[MyClassBank sharedBank] doneWithItem:obj];

但是,这太麻烦了,不是吗?

一个好主意(我认为)突然出现在我的脑海中,那就是覆盖:-(oneway void)release;,因此,我立即跳转到 Apple 的文档,但遇到以下问题:

您只能实现此方法来定义您自己的引用计数方案。这样的实现不应该调用继承的方法;也就是说,它们不应包含对 super 的发布消息。

Ao,我不愿意做这个想法..基本上:

-(oneway void)release{
    if ([self retainCount] == 1) {
        //This will increment retain count by adding self to the collection.
        [[MyClassBank sharedBank] doneWithItem:self];
    }
    [super release];
}

这样做安全吗?

PS:抱歉,帖子太长了,我希望整个想法都清楚..

编辑:

如何覆盖alloc alltogther 并在那里添加[[MyClassBank sharedBank] getReusableItem];

【问题讨论】:

标签: objective-c overriding release reusability nsobject


【解决方案1】:

建议方法:

您正在使用引用计数系统。 99.9999999999999999% 的时间这是一个坏主意。我强烈建议使用不同的机制。也许这些对象可以实现自己独立于retainCount 的引用计数?然后,您可以使用该 referenceCount 来实际控制对象何时可以重用。

不建议的方法:

如果由于某种奇怪的原因您不能这样做,那么您可以执行以下操作这仍然是个坏主意,我不建议您实际使用:: p>

你可以覆盖dealloc:

- (void)dealloc {
  [ivar release], ivar = nil;
  [anotherIvar release], anotherIvar = nil;
  somePrimitive = 0;
  // do not call [super dealloc]
}

- (void)_reallyDealloc {
  [self dealloc];  // clean up any ivars declared at this level
  [super dealloc]; // then continue on up the chain
}

基本上,dealloc 方法将是对象准备好重复使用的点。当您完全处理完对象并最终希望它消失时,您可以使用_reallyDealloc 方法继续上链,最终导致对象被释放。

不要这样做。借助自动引用计数之类的东西,这将带您进入一个充满伤害且非常奇怪的调试场景的世界。 很多工具、类和东西都依赖于引用计数机制才能在不改变的情况下工作,所以乱用它通常不是一个好主意™。

【讨论】:

  • 这正是我想说的。我唯一的附录,一种可能的“并非真正建议”的第三种方法:如果您绝对必须使用自己的内存管理模型并且觉得必须覆盖 -release,则可以考虑使用键值观察在retainCount 属性上。我猜对象可以观察到它们自己的retainCount。这样,至少,您不会弄乱release 之类的方法的实现。
  • 抱歉,我要么没有完全理解你推荐的实现我自己的引用计数的方法,要么你没有注意到我的问题是当一个 NSArray 调用对象上的 release :) ..正如您所说,唯一的方法是覆盖释放或释放。但你不会推荐任何?
  • @Mazyod 如果你必须这样做,通过dealloc 方法比release 方法安全一点,特别是因为新的ARC 功能完全绕过release一个较低级别的运行时函数。
  • 顺便说一句,我将直接调用 [super dealloc],这样,从调用 _reallyDealloc :S .. 这不是很糟糕吗??
  • 另一种选择:您可以考虑使用-returnToBank 之类的方法在相关集合类上的类别。这样你就可以使用像removeAllObjects 这样的成语,而不必担心这种retain/release 魔鬼。
【解决方案2】:

对于觉得这种方法有趣/有用的人来说,这是一种比直接调用 [super dealloc]; 更简洁的方法(这绝对是不好的)

//BAD!
//-(void)dealloc{
//  for some reason, the retainCount at this point == 1
//  if (![[BankStep sharedBank] purgeFlag]) {
//      [self resetObject];
//      [[BankStep sharedBank] doneWithItem:self];
//  } else {
//      [children release];
//      [super dealloc];
//  }
//}

通过调用 [[Bank sharedBank] purgeBank]; ,将标志设置为 true,然后从 NSSet 中删除所有对象。

适应的解决方案:

@Joe Osborn 使用类别实现returnToBank 方法的想法!

【讨论】:

  • 任何有兴趣知道发生在我身上的人,请阅读:我想使用两个作为自定义类实例的对象。一个是直接使用 [pool getReusableObject];然后 [object returnToPool]; .. 然而,另一个是 PITA。我花了两天时间尝试对其建模,因为该对象有一个指向父级的指针和一个来自同一类的子级数组,更不用说它存在于整个地方的数组和 ivars 中......是的,一个 PITA ......我花了整整 5 分钟来实现上面发布的被删除的答案,并且 NSlogs 显示它的工作完美......
猜你喜欢
  • 2016-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-10
  • 2011-04-11
  • 1970-01-01
相关资源
最近更新 更多