【问题标题】:Objective C: I need some advice regarding properties vs ivars目标 C:我需要一些关于属性与 ivars 的建议
【发布时间】:2015-09-04 19:13:39
【问题描述】:

我在 stackoverflow 和许多其他网站上查找了我当前的问题,但老实说我有点困惑。我应该只在另一个类需要访问它时使用属性,而当它仅用于我的私有类时使用 ivars 吗?这就是我到目前为止所得到的,尽管我确实听到了一些关于何时使用 ivars 和属性的其他信息。我只是想保持我的代码干净和更现代。任何澄清将不胜感激。

【问题讨论】:

    标签: objective-c properties ivar


    【解决方案1】:

    这是一个非常基于意见的话题。所以我试图坚持无争议的事实和建议:

    • 永远不要从班级之外访问 ivars。公共访问总是通过属性及其访问器或其他方法完成。如今,标头永远不应包含 ivar 声明。
    • 在内部使用 ivars 是可能的,而且并不少见。 ARC 使对象类型更容易做到这一点,因为所有权是自动处理的。
    • 使用属性可以为您提供对NSStringNSArray 等人的正确所有权处理。 (copy)。
    • 此外,在某些情况下,它们可以帮助提高线程安全性 (atomic)。
    • 在内部使用属性可以使 KVO 合规性或其他副作用更易于实施。
    • 使用私有属性是公开 IBOutlets 的标准模式。
    • 可以在运行时查询属性。不过,这很少需要。
    • 私有属性存在污染类的方法命名空间的问题。可能会发生意外覆盖。

    在实现中是否使用 ivars 的实际决定是个人喜好问题。它受到代码风格的许多微妙细节的影响。

    【讨论】:

    • Ivars 也可以在运行时查询。
    • @AminNegm-Awad 是的,但它们携带的静态信息要少得多。
    • @Alistra 我很欣赏你建议的编辑,但在这个有争议的情况下,我更喜欢你添加另一个帖子来说明你的观点。
    • @FreeNickname 我认为 Apple 的这个具体建议 1. 自以为是(他们没有给出任何解释或理由)和 2. 不适用(该文档是关于手动保留发布代码,而不是 ARC)。作为一个有争议的项目,我不想将它添加到我的列表中。
    • @AminNegm-Awad,DRY 是一个很好的论据。我可以为其他一切提供反驳论据。但我们不同意设置者/向self 发送消息。我相信这是一个很好的论据,你不知道。我想,继续这个讨论是没有意义的,尼古拉如禾说得对:固执己见。附言请使用@来呼叫你的对手,否则他/她不会收到通知。此外,Alan Kay 创建了 Smalltalk,而不是 Obj-C。而且你不是世界上唯一一个阅读 Clang 文档的人。而且 Clang 并不是唯一的 Obj-C 编译器。不过,感谢您的对话。
    【解决方案2】:

    在我看来 - 如果你没有覆盖 getter 和 setter,你应该只使用由 ivar 支持的属性。

    你应该在公共接口中声明它们以使其成为公共,并在私有接口中声明它们以使其成为私有。

    这样做有很多优点,其中一些是:

    1. 在 getter 中执行惰性实例化
    2. 在 setter 中进行验证
    3. 将属性设为只读公开并私下读写

    在您的班级中,您应该几乎始终通过 getter/setter 访问您的属性,除非:

    1. 您希望避免在这些方法中实现的行为(延迟实例化、验证)
    2. 你在初始化器中
    3. 你在 getter/setter 中

    下面是一个例子,说明以下几点:

    @interface SomeObject : NSObject
    @property (strong, nonatomic) NSMutableArray * objects;
    @property (readonly, nonatomic, getter=isActive) BOOL active; // Public read-only 
    @end
    
    @interface SomeObject()
    @property (readwrite, nonatomic, getter=isActive) BOOL active; // Can be updated internally
    @property (nonatomic, getter=isVisible) BOOL visible;
    @end
    
    @implementation SomeObject
    
    - (NSMutableArray)objects {
       if (!_objects) {
          _objects = [NSMutableArray array]; // Lazy instantiate when first accessed
       }
       return _objects;
    }
    
    - (BOOL)isActive {
       return _isActive && self.isVisible; // Cannot be active if not visible
    }
    
    - (BOOL)setActive:(BOOL)active {
       self.visible = active; // Keep visibility same as active
       _active = active;
    }
    
    -(BOO)setVisible:(BOOL)visible {
       _visible = visible;
       // perform animation or something else...
    }
    
    @end
    

    任何这些都不能使用 ivars 来实现。

    【讨论】:

      【解决方案3】:

      你应该在你的类内外使用声明的属性。大多数开发人员说您应该只在初始化程序中将 ivar 设置在属性后面。 (我不同意,在这种情况下也使用 setter 和 getter,但我是少数。)

      【讨论】:

      • 不仅仅是“大多数开发人员”。实际上是苹果公司这么说的。 Link。看Don’t Use Accessor Methods in Initializer Methods and dealloc
      • 我知道。你知道苹果本身不遵循这条规则吗? e.在NSView。然而,遵循规则而不给出理由永远不能证明除了没有自己的大脑之外。
      • 从你上面的最后一个回复(“棘手的我”)我想,你认为我认为你的答案不好,我是那个否决它的人。所以,只是澄清一下:我不是最初反对它的人。写完评论后,我没有投反对票。不过,在阅读了您关于没有自己的大脑的回复后,我确实对它投了反对票。因为我不能对 cme​​ts 投反对票。如果你愿意,你可以恨我,但我相信试图冒犯别人并不是捍卫你立场的方式。请再次使用@
      • 不,我不这么认为。而且我不知道您是否可以投票。而且我不讨厌人们赞成、反对、cmets 或任何其他可能发生在 SO 上的事情。
      猜你喜欢
      • 2013-05-03
      • 2013-08-01
      • 2014-01-19
      • 1970-01-01
      • 2021-04-02
      • 1970-01-01
      • 1970-01-01
      • 2017-09-28
      • 1970-01-01
      相关资源
      最近更新 更多