【问题标题】:Swift property - getter ivarSwift 属性 - getter ivar
【发布时间】:2014-09-14 00:22:38
【问题描述】:

我们应该在 Swift getter 中使用 ivar 属性吗?我的代码导致 getter 调用 getter,直到程序崩溃:

var document: UIDocument? {
    get {
        return self.document
    }
    set {
        self.document = newValue

        useDocument()
    }
}

【问题讨论】:

    标签: swift getter


    【解决方案1】:

    Swift 属性不像在 Objective-C 中那样具有单独的底层存储的概念。相反,您需要创建第二个(私有)属性并将其用作存储:

    private var _document: UIDocument?
    var document: UIDocument? {
        get {
            return _document
        }
        set {
            _document = newValue
            useDocument()
        }
    }
    

    如果您只想在设置document 属性后调用useDocument(),则可以省略getter、setter 和私有属性,而只使用willSetdidSet

    【讨论】:

    • 我在答案中添加了一条注释,如果您的实际代码如此简单,您可以使用willSetdidSet
    • 我最初使用didSet,但我需要useDocument 在属性初始化之前运行。 (设置在演示VCprepareForSegue
    • useDocument 在当前 VC 的 prepareForSegue 中初始化属性时仍未调用
    • 我的prepareForSegue 代码有问题 - 感谢您的帮助 :)
    • 如果 useDocument 对您查看控制器的 UI 进行了任何操作,那么在初始化时(来自 prepareForSegue)它无法从 didSet 工作的原因是您的 VC 的视图尚未加载。在viewDidLoad 中检查self.document 并在此处致电useDocument
    【解决方案2】:

    如果您想要实现的是在设置属性时添加一些自定义处理,则无需定义单独的支持数据成员并实现计算属性:您可以使用 willSetdidSet 属性观察者,分别在设置属性之前之后自动调用。

    在您的具体情况下,这就是您应该如何实现您的属性:

    var document: UIDocument? {
        didSet {
            useDocument()
        }
    }
    

    推荐阅读:Property Observers

    【讨论】:

      【解决方案3】:

      在您的代码中存在无限递归情况:例如,getter 内部的self.document 不断调用 getter 本身。

      您需要自己明确定义一个 ivar。这是一个可能的解决方案:

      private var _document:UIDocument?
      
      var document: UIDocument? {
          get {
              return self._document
          }
          set {
              self._document = newValue
      
              useDocument()
          }
      }
      

      【讨论】: