【问题标题】:swift: defer non-optional object initializationswift:推迟非可选对象初始化
【发布时间】:2016-07-26 17:15:15
【问题描述】:

使用 CocoaTouch 拨号时,经常会出现 UIView(Controller) 子类属性无法在init 方法中初始化(例如,我们需要已加载视图),但逻辑上它们是非可选的,甚至是非 var .在这种情况下,该属性必须是可选的,才能在没有错误的情况下进行编译,这看起来很丑陋 - 代码使用 ! 来实现。

有什么办法可以解决这个问题吗?我会想象一些延迟初始化。如果此类属性可以在没有初始值的情况下编译,并且如果在初始化之前访问它,则在运行时崩溃。

一些描述问题的代码示例:

class MyVC: UIViewController {
    @IBOutlet var someLabel: UILabel!
    let viewBasedParam: CustomClass // how to keep it non-optional if it can be initialized after view has been loaded?

    override func viewDidLoad() {
        super.viewDidLoad()
        self.viewBasedParam = CustomClass(self.someLabel.text)
    }
}

附: CustomClass 不能有默认初始化程序,因为它需要视图中的数据。

【问题讨论】:

  • 你可以试试lazy
  • 你也可以使用builder模式
  • @ILikeTau,是的,可能,但这种方法非常有限——我必须为属性编写专用的初始化代码(例如lazy var viewBasedParam = self.specialMethodToInitThisParam())。我正在寻找能够从任何地方分配初始值的通用解决方案,即使是通过外部代码。
  • 您应该使用隐式展开的选项,就像您使用 UILabel! 一样。

标签: ios swift initialization optional-parameters


【解决方案1】:

在您的MyVC 中,您可以有一个convenience init 方法,您可以在其中初始化let 变量。试试这个,让我知道它是否适合你:

class MyVC: UIViewController {
let viewBasedParam: CustomClass

    convenience init() {
        self.init(nibName:nil, bundle:nil)
        self.viewBasedParam = CustomClass(self.someLabel.text)//else just initialize with empty string here and then assign actual value in viewDidLoad
    }
}

【讨论】:

  • 直到viewDidLoad() 之前self.someLabel 不是未定义的吗?
  • 我也在该行中添加了注释以使用空字符串进行初始化。
  • 我正在寻找如何避免虚拟初始值。
【解决方案2】:

据我发现,解决方法可能如下:

class MyVC: UIViewController {
    @IBOutlet var someLabel: UILabel!
    private var _viewBasedParam: CustomClass? = nil
    var viewBasedParam: CustomClass {
        get { return self._viewBasedParam! } // always unwrap private optional
        set { self._viewBasedParam = newValue }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        self.viewBasedParam = CustomClass(self.someLabel.text)
    }
}

【讨论】:

  • 您的解决方案似乎比仅声明 var viewBasedParam: CustomClass! 没有优势。
  • @rob,没有初始值我无法声明var viewBasedParam: CustomClass!
  • @brigadir,你不会对let viewBasedParam: CustomClass! 感到困惑吗? var viewBasedParam: CustomClass! 应该可以,但private(set) var viewBasedParam: CustomClass! 会更好。
  • @OOPer 感谢您指出这一点 - 复制粘贴错误。将let 更改为var。所以现在我可以在init() 之后初始化viewBasedParam,即使在类方法之外(外部)设置它的值。如果在某些情况下我在未初始化的情况下阅读它,我会得到非常清晰的“展开”错误。
猜你喜欢
  • 1970-01-01
  • 2016-02-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-27
  • 1970-01-01
  • 2014-03-25
  • 1970-01-01
相关资源
最近更新 更多