【问题标题】:What's the purpose of an ivar when a property exists?当属性存在时,ivar 的目的是什么?
【发布时间】:2010-07-26 16:38:37
【问题描述】:

以下内容不会在编译或运行时抱怨没有name ivar。那么为什么看到 ivar @property/@synthesize 如此普遍。

@interface PropTest : NSObject
{
}
@property (retain) NSString *name;
@end

@implementation PropTest
@synthesize name;
@end

int main (int argc, const char * argv[]) {
  NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
  PropTest *p = [[PropTest new] autorelease];
  p.name = @"Hello, World!";
  NSLog(@"%@",p.name);
  [pool drain];
  return 0;
}

此代码打印

Hello, World!

事实上,如果我访问p->name,我会收到警告:

warning: instance variable 'name' is @private; this will be a hard error in the future

这表示如果一个 ivar 不存在,则会为我创建一个 ivar。

如果这是真的,那么手动创建 ivar 有什么意义(忽略显而易见的问题,即有时不使用 g/setter 访问器是有正当理由的)?

或者换个说法,我应该在需要绕过访问器时为属性创建一个ivar吗?

【问题讨论】:

    标签: objective-c properties


    【解决方案1】:

    合成的 ivars(无需手动声明 ivars 的能力)是新的 Objective-C 运行时的一个特性,它仍然没有在所有系统上使用。对于 32 位 Mac(以及直到最近的 iPhone 模拟器),您必须手动声明 ivars。如果您只针对具有新运行时的系统,则没有理由手动声明 ivars。

    【讨论】:

    • 我认为正如 Cris 所说,不声明 ivars 存在一些问题。调试是我经常遇到的。
    【解决方案2】:

    eman 的回答总体上是正确的,但即使在新的运行时中仍然声明 ivars 有一个原因:Apple 不鼓励在 init 和 dealloc 方法中合成访问器。本质上,除了设置变量之外,getter 和 setter 还可以有副作用。特别是,它们可以触发 KVO 通知。与 ivar 交谈时,您只需发送 release 即可完成。但是,如果您只有一个属性,那么您唯一的选择就是设置它并希望您避免任何不幸的交互。

    说实话,我不确定这在实践中会有多大的问题。我只是迷信地避免了它,尽管我暗中怀疑它在大多数情况下会导致问题。但 Apple 确实在文档中指出了这一点,所以我认为有一些担心的理由。

    【讨论】:

    • 您仍然可以使用合成的 ivars 直接访问 ivar(有一个错误您不能,但我很确定它现在已修复),所以这不是问题。
    • @eman:IIRC 他们正在计划修复,但除非您使用预发布的 Xcode 版本,否则不会修复。
    【解决方案3】:

    确保属性得到 ivars 支持的两个不太好但必要的理由:

    1. 由于某种原因,XCode 调试器不显示没有明确声明相应 ivars 的属性。
    2. 在我看来,在某些情况下使用不带 ivar 的 @property 会隐藏其他 ivar,从而导致编译错误(请参阅 Why does a subclass @property with no corresponding ivar hide superclass ivars?

    除非我在这里弄错了几根棍子,否则我认为在没有明确 ivars 的情况下使用 @property 可能会导致不方便的烦恼。

    【讨论】:

      猜你喜欢
      • 2015-02-23
      • 1970-01-01
      • 2011-05-07
      • 1970-01-01
      • 2013-01-11
      • 1970-01-01
      • 2013-03-17
      • 2012-11-23
      • 1970-01-01
      相关资源
      最近更新 更多