【问题标题】:Is there any reason to declare ivars if you're using properties exclusively in Objective-C?如果您仅在 Objective-C 中使用属性,是否有任何理由声明 ivars?
【发布时间】:2011-02-04 22:43:17
【问题描述】:

我倾向于只在我的类中使用属​​性,尤其是现在你可以在类扩展中声明属性,这要归功于现代的 Objective-C 2.0 运行时——我使用这个特性来创建“私有”属性。

我的问题是,是否有充分的理由再在类接口中声明 ivars。我更喜欢我的面向公众的接口尽可能简洁和干净,只显示我的类中相关的方面。

例如,我倾向于做以下事情:

MyClass.h:

@interface MyClass : NSObject

@property (nonatomic, copy) NSString * publicString;
@property (nonatomic, copy, readonly) NSString * readOnlyString;

@end

MyClass.m:

@interface MyClass ()

@property (nonatomic, copy, readwrite) NSString * readOnlyString;
@property (nonatomic, copy) NSString * privateString;

@end

@implementation MyClass

@synthesize publicString = publicString_;
@synthesize readOnlyString = readOnlyString_;
@synthesize privateString = privateString_;

- (void)init
{
    self = [super init];

    if (self != nil)
    {
        self.publicString = @"Public String";
        self.readOnlyString = @"Read-Only String";
        self.privateString = @"Private String";
    }

    return self;
}

- (void)dealloc
{
    [publicString_ release];
    [readOnlyString_ release];
    [privateString_ release];

    [super dealloc];
}

@end

抛开代码风格偏好不谈,像这样完全避免 ivars 有什么问题吗?

【问题讨论】:

    标签: objective-c properties instance-variables


    【解决方案1】:

    我可能已经找到了一个足够适合我用 ivars 明确支持我的属性的答案。调试器似乎不会列出任何自动合成的 ivars,因此除了手动调用属性访问器之外,没有办法在调试期间钻取 self 并检查各种值,这很乏味。除非他们改变这一点,否则这可能足以让我回过头来明确声明 ivars。

    【讨论】:

    • 我有,但是直接使用 GDB 很痛苦,因为它不支持点语法。
    • 减去严重的“butt”拼写错误,此外,最新版本的 Xcode 似乎在调试器控制台中提供了“有用的”自动完成建议,但它不会费心向前移动光标,所以它最终会变得一团糟。呃……
    • 最新版本是什么?我还在 SL 上。
    • 如果你使用 lldb 而不是 gdb 那么你可以看到属性值。
    【解决方案2】:

    主要问题,如果它困扰你的话,是每个 Cocoa With Love,动态实例变量,如你正在使用的那些,除了 64 位 Intel/PowerPC 之外的运行时不支持(根据 Chuck 的评论修复下面)和 ARM(适用于 iOS)。

    我目前无法找到有关该问题的权威 Apple 文档;请注意,仅限于最新的 OS X v10.6 是不够的,因为它可用于并支持 Apple 从 PowerPC 切换后立即发货的 32 位 Intel 机器。

    迟来的额外想法:在不知道 Xcode 4 中的任何潜在变化的情况下,在头文件中声明其他私有实例变量的一个很好的理由是将它们标记为 IBOutlets 并以图形方式将它们连接起来。诚然,这实际上只与非常特定类型的类和成员变量相关。

    【讨论】:

    • 实际上,正如 CWL 条目中正确指出的那样,也支持 64 位 PPC。只有 ARM 之外的 32 位平台获得了旧版运行时。
    • 是的,我记得我使用的功能仅在现代运行时可用,但我目前只在 iOS 上使用,所以这不是那么重要。
    • 在这种情况下,很难在@interface 中找到支持ivar 声明的理由。我所能想到的——在试图扮演魔鬼的拥护者时——是启用性能黑客,当不扮演魔鬼的拥护者时,无论如何我都会完全反对。
    • 哦,实际上,我想将成员变量暴露给 Interface Builder 的审查是非常有用的,也是将 ivars 放入头文件的明确理由。我已经更新了我的答案。
    • 我将属性暴露给 Interface Builder,而不是 ivars,这很好用。
    【解决方案3】:

    在调试问题上我必须同意 LucasTizma。

    当我开始使用 XCode4 时,我开始没有显式声明 ivars,而是使用 @synthesize aVar = _aVar 语法为我创建它们。在尝试调试代码时,我注意到我无法将光标悬停在变量上并查看其值。

    对我来说,这是不可接受的。我想它又回到了明确声明它们。

    【讨论】:

    • 这可能是 GDB 的一个错误或缺点,它仍然是唯一可用于 iOS 的调试器。希望 LLDB 能够尽快为 iOS 使用做好准备并解决这个问题。
    【解决方案4】:

    除了 Tommy 的担心之外,声明 ivar 无疑是一种很好的做法,尤其是在您的代码可能会被重用或者您可能会在某个时候返回到您的代码的情况下。

    【讨论】:

    • 我不明白为什么会这样。为什么这是一个好习惯?它只是由我的类管理的数据,但属性具有内存管理和其他属性的便利,所以我不明白为什么使用 ivars 被认为是好的做法。
    • 这清楚地表明您的班级正在存储该数据。属性不一定必须与 ivars 相对应; IMO 类拥有它们的 ivars(ivars 基本上是类的一部分);属性就是——属性。这真的是一个概念性的东西。
    • 我想我能明白你的意思。我对此的看法是,其他类不应该以一种或另一种方式关心一个类的属性是否由自定义访问器支持或确定。但我确实明白你的意思。
    • 通常(特别是你可以看到 Apple 的代码)你访问另一个类的属性,而不是它的 ivars。该类可以有更多(或更少)的 ivars 来保存该类的用户不应该关心的其他值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-21
    • 2013-11-19
    相关资源
    最近更新 更多