【问题标题】:In swift I cant initialize things before the super.init() or after迅速我无法在 super.init() 之前或之后初始化事物
【发布时间】:2014-09-06 09:50:33
【问题描述】:

我希望能够使用 self 初始化属性 subviewGroup 但这给了我错误:属性 'self.gridView' 未在 super.init 调用时初始化

init(frame: NSRect) {
    super.init(frame: frame)
    subviewGroup = GridViewGroup(rows: 9, columns: 9, gridView: self)
}

/***  Properties  ***/
let subviewGroup: GridViewGroup

如果我把 super.init() 放在这样的初始化之后

init(frame: NSRect) {
    subviewGroup = GridViewGroup(rows: 9, columns: 9, gridView: self)
    super.init(frame: frame)
}

/***  Properties  ***/
let subviewGroup: GridViewGroup

我收到错误:在调用 super.init 之前使用了“self”

我知道我可以使用 Optional,但由于在 init() 调用之后它永远不会为零,因此它似乎没有必要。有没有办法在不将 subviewGroup 设为可选的情况下正确执行此操作?

这是一个使用可选的工作示例

/***  Initializers  ***/
init(frame: NSRect) {
    super.init(frame: frame)
    subviewGroup = GridViewGroup(rows: 9, columns: 9, gridView: self)
}

/***  Properties  ***/
let subviewGroup: GridViewGroup?

【问题讨论】:

标签: initialization swift optional


【解决方案1】:

如您所见,正确的解决方案是使用可选的。但是因为你知道在init 之外它永远不会是nil,所以你可以使用隐式展开的可选。

let subviewGroup: GridViewGroup!

【讨论】:

    【解决方案2】:

    这正是隐式展开的可选项的好处。您可以像这样轻松地将它们添加到您的示例中:

    /***  Initializers  ***/
    init(frame: NSRect) {
        super.init(frame: frame)
        subviewGroup = GridViewGroup(rows: 9, columns: 9, gridView: self)
    }
    
    /***  Properties  ***/
    let subviewGroup: GridViewGroup!
    

    使用隐式展开的可选项允许您将变量视为不是可选项,并在调用它时直接访问底层。

    使用普通的可选项,您的代码可能看起来像 var nonoptional: GridViewGroup = subviewGroup!,而使用隐式展开的可选项,您可以丢弃 !:var nonoptional: GridViewGroup = subviewGroup

    来自 Apple 的文档:

    当可选项的值为 在第一次定义可选项后立即确认存在,并且 可以肯定地假设在此后的每一点都存在。这 Swift 中隐式解包选项的主要用途是在课堂上 初始化

    【讨论】:

      【解决方案3】:

      您的用例急需一个隐式展开的可选项;这是一个完美的例子,说明了何时会使用这种模式,并且这种模式在整个 Cocoa Touch API 的许多地方都有使用。

      开始:

      A.初始化的正确顺序应该是这样的:

          init(frame: NSRect) {
              subviewGroup = GridViewGroup(rows: 9, columns: 9, gridView: self)
              super.init(frame: frame)
          }
      

      ...根据 Swift 编程手册:

      “指定的初始化器必须确保其类引入的所有属性在委托给超类初始化器之前都已初始化。”

      其次:

      B.将您的 subviewGroup 常量声明为隐式展开的可选项;这样做会给它一个默认值nil,这意味着就编译器而言,它已经满足了初始化的要求!这种形式给你一个一次性的机会(因为它是一个常数,你使用let)给它分配一个非零值,然后你可以在你的初始化程序中毫无问题地这样做:

      let subviewGroup: GridViewGroup!
      
      init(frame: NSRect) {
          subviewGroup = GridViewGroup(rows: 9, columns: 9, gridView: self)
          super.init(frame: frame)
      }
      

      我希望这会有所帮助!

      【讨论】:

      • 注意:我想假设我们已经通过将subviewGroup 声明为隐式展开的可选项在技术上进行了初始化,init() 方法中的操作顺序如 A 上面没有那么重要;但是,我相信遵循规定的模式仍然是一种好习惯
      • 所以我对这个答案感到困惑。编译器抱怨:“在 super.init 调用之前使用'self'”
      猜你喜欢
      • 1970-01-01
      • 2015-09-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-29
      • 2021-09-10
      相关资源
      最近更新 更多