【问题标题】:ByPass init(coder) in NSView subclass在 NSView 子类中绕过 init(coder)
【发布时间】:2015-06-10 21:36:14
【问题描述】:

我创建了一个 NSView 的子类,如下所示

class StudentCardView: NSView {
    let firstName: String

    init(name: String) {
        firstName = name
        super.init()
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder) <-- ERROR: firstName not initialised
    }
}

let myName = "Test-Name"
var cell = StudentCardView(name: myName)

如何消除需要在 init(coder) 中初始化 firstName 的错误,因为我不打算在情节提要中创建 StudentCardView 的任何视图。

我同意,在调用超类初始化程序之前需要初始化所有常量。这里有出路吗?我犯了任何设计错误吗?

【问题讨论】:

    标签: macos cocoa swift


    【解决方案1】:

    init?(coder:NSCoder) 初始化器是强制性的,这很烦人,因为您通常不需要它。让我们希望这在未来的 Cocoa 版本中有所改变。

    但还是有希望的。当 Xcode 告诉您需要该初始化程序时,它实际上为您提供了包含来自内置模板的简单版本的选项。它看起来像这样:

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    

    这里要注意的是fatalError()。这实际上也消除了您所询问的错误。发生这种情况是因为该函数标有 @noreturn 注释,编译器将其视为可以停止执行检查的提示,因为 fatalError() 之后的代码将永远不会执行。

    所以你可以保持你漂亮的严格不可变 let 实例变量:-)

    【讨论】:

    • 更好的理解方式是它实现并显式崩溃,而不是像在 ObjC 中那样悄悄地做错事。你总是需要一些东西,因为虽然你可能打算从 nib 加载视图,但它们是被允许的,而且 Swift 试图涵盖可能的内容,而不仅仅是预期的内容。 (毕竟,错误几乎总是由于“不应该”发生但实际上确实发生的事情。)
    • @RobNapier 你知道编译器是否以某种特殊方式处理fatalError
    • 当然。它包括属性@noreturn,它告诉编译器调用不会返回,所以其他一切都无关紧要。
    • 啊我不知道@noreturn!那是这个难题中缺少的部分:-)
    • 我不明白。在我的 NSView 子类中,这个初始化程序被调用,因此我的应用程序立即崩溃。我的其他初始化程序需要 init(frameRect: NSRect) {} 没有被调用。
    猜你喜欢
    • 1970-01-01
    • 2011-01-25
    • 1970-01-01
    • 1970-01-01
    • 2018-05-17
    • 1970-01-01
    • 2016-11-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多