简体   繁体   English

我无法迅速在super.init()之前或之后初始化事物

[英]In swift I cant initialize things before the super.init() or after

I want to be able to initialize the property subviewGroup using self but this gives me the error: Property 'self.gridView' not initialized at super.init call 我希望能够使用self初始化属性subviewGroup,但这给了我错误:在super.init调用中未初始化属性'self.gridView'

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

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

Then if I put the super.init() after the initialization like this 然后如果我像这样在初始化后放置super.init()

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

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

I get the error: 'self' used before super.init call 我收到错误:在super.init调用之前使用了'self'

I know I can use an Optional but since it will never be nil after the init() call it seems unnecessary. 我知道我可以使用Optional,但是由于init()调用后它永远不会为零,所以它似乎是不必要的。 Is there a way to do this properly without making subviewGroup an optional? 有没有一种方法可以正确地做到这一点而无需将subviewGroup设为可选?

Here is a working example using an optional 这是一个使用可选的工作示例

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

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

This is exactly what implicitly unwrapped optionals are good for. 这正是隐式展开的可选对象所擅长的。 You can easily add them to your example like this: 您可以像这样轻松地将它们添加到您的示例中:

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

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

Using an implicitly unwrapped optional allows you to treat the variable as if it weren't an optional and access the underlying directly when you call it. 使用隐式展开的可选变量可以使您将变量视为不是可选变量,并在调用它时直接访问基础。

Using a normal optional your code may look like var nonoptional: GridViewGroup = subviewGroup! 使用普通的可选代码可能看起来像var nonoptional: GridViewGroup = subviewGroup! while with implicitly unwrapped optionals you can discard the !: var nonoptional: GridViewGroup = subviewGroup . 而使用隐式展开的可选对象,您可以放弃!: var nonoptional: GridViewGroup = subviewGroup

From Apple's docs: 从苹果的文档:

Implicitly unwrapped optionals are useful when an optional's value is confirmed to exist immediately after the optional is first defined and can definitely be assumed to exist at every point thereafter. 当在第一个定义了可选对象的值之后立即确认该可选对象的值存在并且可以肯定地假定此后的每个点都存在时,隐式解开的可选对象很有用。 The primary use of implicitly unwrapped optionals in Swift is during class initialization Swift中隐式展开的可选对象的主要用途是在类初始化期间

Your use case is crying out for an implicitly unwrapped optional; 您的用例正在寻求一个隐式展开的可选; this is a perfect example of when you would use one, and this pattern is used in many places throughout the Cocoa Touch API. 这是使用时机的完美示例,并且整个Cocoa Touch API的许多地方都使用了这种模式。

To begin with: 首先:

A. The proper order of your initialization should be something like this: 答:正确的初始化顺序应该是这样的:

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

...per the Swift Programming Book: ...根据《 Swift编程手册》:

"A designated initializer must ensure that all of the properties introduced by its class are initialized before it delegates up to a superclass initializer.” “指定的初始值设定项必须确保由其类引入的所有属性在委托给超类初始值设定项之前都已初始化。”

Then secondly: 然后第二:

B. Declare your subviewGroup constant as an implicitly unwrapped optional; B.将您的subviewGroup常量声明为一个隐式展开的可选; doing so gives it a default value of nil , meaning that as far as the compiler is concerned the requirement that it be initialized has been met! 这样做为它提供了默认值nil ,这意味着就编译器而言,已满足对其初始化的要求! This form leaves you with a one-time opportunity (since it is a constant, where you used let ) to assign a non-nil value to it, which you can then do in your initializer without issue as so: 这种形式给您一次机会(因为它是一个常量,在其中使用let ),可以为其分配一个非nil值,然后您就可以在初始化器中这样做,而不会出现问题:

let subviewGroup: GridViewGroup!

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

I hope this helps! 我希望这有帮助!

The correct solution, as you found, is use optional. 如您所见,正确的解决方案是使用可选的。 But because you know it will never be nil outside init , you can use implicitly unwrapped optional. 但是因为您知道它在init之外永远不会nil ,所以您可以使用隐式展开的optional。

let subviewGroup: GridViewGroup!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在super.init之前快速调用self - swift calls self before super.init 在super.init之前使用表达式中的初始化属性的Swift错误 - Swift error using initialized properties in expressions before super.init 在super.init之前的init中调用classForCoder - Calling classForCoder in init before super.init Swift:属性未在super.init调用时初始化 - Swift: Property not initialized at super.init call Swift中的super.init()递归问题 - super.init() recursive issue in Swift 在super.init调用之前初始化非可选属性,而无需复制代码 - Initialize Non-Optional Property Before super.init call without duplicating code 更新到Xcode 6.1后,“在super.init初始化之前在基础对象中使用属性'nibName'” - “Use of property 'nibName' in base object before super.init initializes it” after updating to Xcode 6.1 Swift类中的错误:super.init调用时未初始化属性-如何初始化需要在其初始值设定项参数中使用self的属性 - Error in Swift class: Property not initialized at super.init call - How to initialize properties which need use of self in their initializer parameter 属性未在super.init调用中初始化 - Property not initialized at super.init call 如何在Swift中通过super.init从子类修改基类属性? - How to modify base class properties from sub classes via super.init in Swift?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM