Swift:Self.init在初始化程序中多次调用

时间:2017-04-29 14:41:26

标签: swift swift3 initializer

这个让我难过。我无法弄清楚为什么Swift抱怨self.init在这段代码中不止一次被调用:

public init(body: String) {
    let parser = Gravl.Parser()

    if let node = parser.parse(body) {
        super.init(document: self, gravlNode: node)
    } else {
        // Swift complains with the mentioned error on this line (it doesn't matter what "whatever" is):
        super.init(document: self, gravlNode: whatever)
    }
}

除非我遗漏了某些内容,否则很明显它只会调用init一次。有趣的是,如果我评论第二行,Swift抱怨Super.init并没有在所有路径上调用,哈哈。

我错过了什么?

更新

好的,问题是肯定试图在调用super.init时传递self。哈,我完全忘了我在做那件事。我想我已经通过实验编写并编译并认为它可能确实有效,但看起来像it's actually a bug它完全按照这种方式进行编译。

无论如何,由于将self传递给初始化程序是多余的,因为它是同一个对象,我更改了父初始化程序以接受可选的文档参数(它只是一个内部初始化程序)所以没什么大不了的)如果是nil我只是在父初始值设定项中将它设置为self

对于那些好奇的人来说,这就是父初始化程序(现在)的样子:

internal init(document: Document?, gravlNode: Gravl.Node) {
    self.value = gravlNode.value
    super.init()
    self.document = document ?? self as! Document
    // other stuff...
}

1 个答案:

答案 0 :(得分:3)

我怀疑这是一个错误的诊断(即错误的错误信息)。如果你有一个我们可以试验的完整例子会非常有帮助,但这条线没有意义(我怀疑是潜在的问题):

    super.init(document: self, gravlNode: node)

您无法将self传递给super.init。您尚未初始化(在您调用super.init之前,您尚未初始化)。例如,请考虑以下简化代码:

class S {
    init(document: AnyObject) {}
}

class C: S {
    public init() {
        super.init(document: self)
    }
}

这导致error: 'self' used before super.init call,我认为这是正确的错误。

编辑:我相信Hamish肯定发现了一个编译器错误。您可以在Xcode 8.3.1中使用它(尚未在8.3.2上测试过):

class S {
    var x: Int
    init(document: S) {
        self.x = document.x
    }
}

class C: S {
    public init() {
        super.init(document: self)
    }
}

let c = C() // malloc: *** error for object 0x600000031244: Invalid pointer dequeued from free list