web-dev-qa-db-ja.com

Swift:コードがそうしているのに「スーパークラスの指定された初期化子を呼び出さなければならない」エラー

目標は、SCNNodeをサブクラス化することです。 class docs によると、init(geometry geometry: SCNGeometry?)は指定された初期化子です(convenienceキーワードはリストされていません)。したがって、このコードはそのスーパークラスの指定された初期化子を呼び出していませんか?

Xcodeが次のエラーを表示するのはなぜですか?

スーパークラスSCNNodeの指定された初期化子を呼び出す必要があります

class PreviewNode: SCNNode {
    // Constants
    let PreviewNodeColor = gRedColor
    let Size = CGFloat(1.0)
    let ChamferRadius = CGFloat(0.0)

    override init() {
        let previewBox = SCNBox(width: Size, height: Size, length: Size, chamferRadius: ChamferRadius)
        previewBox.firstMaterial!.diffuse.contents = PreviewNodeColor
        previewBox.firstMaterial!.transparency = 0.2
        previewBox.firstMaterial!.specular.contents = UIColor.whiteColor()
        super.init(geometry: previewBox)
    }
}
9
Crashalot

ここでの問題は、self.init()を呼び出す前にPreviewNodeプロパティにもアクセスしようとしていることです。

このようにしてみてください:

Xcode 8 GM•Swift

class PreviewNode: SCNNode {
    let previewNodeColor: UIColor = .red
    let size: CGFloat = 1
    let chamferRadius: CGFloat = 0
    convenience override init() {
        self.init()
        let previewBox = SCNBox(width: size, height: size, length: size, chamferRadius: chamferRadius)
        previewBox.firstMaterial?.diffuse.contents = previewNodeColor
        previewBox.firstMaterial?.transparency = 0.2
        previewBox.firstMaterial?.specular.contents = UIColor.white
        self.geometry = previewBox
    }
}
7
Leo Dabus

この答えを使用しましたが、LeoDabusは称賛に値します。 Leoが行ったように新しい便利な初期化子を定義することも、この回答のようにデフォルトの初期化子をオーバーライドすることも同様に有効かどうか、または一方が他方よりも好ましいかどうかを説明できるかどうかコメントしてください。

class PreviewNode: SCNNode {
    // Constants
    let MainColor = gRedColor
    let MainSize = CGFloat(1.0)
    let MainRadius = CGFloat(0.0)
    let MainTransparency = CGFloat(0.2)


    override init() {
        super.init()
        doInit()
    }


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


    private func doInit() {
        let previewBox = SCNBox(width: MainSize, height: MainSize, length: MainSize, chamferRadius: MainRadius)
        previewBox.firstMaterial!.diffuse.contents = MainColor
        previewBox.firstMaterial!.transparency = MainTransparency
        previewBox.firstMaterial!.specular.contents = UIColor.whiteColor()
        self.geometry = previewBox
    }
}
2
Crashalot

Swift 4.2ガイドからの私の理解では、指定されたイニシャライザーはすべての保存されたプロパティを初期化する必要があります。便利なイニシャライザーはプロパティのサブセットを初期化できます(さまざまな状況でインスタンスを作成するのに役立つ場合があります)が、最初にサブクラスの指定されたイニシャライザーを呼び出し、次にスーパークラスの指定されたイニシャライザーを呼び出して、カスタマイズを開始する前にすべての格納されたプロパティを初期化します。Swiftガイドのこの図は、次の場合に役立ちます。

enter image description here

便利なキーワードを使用することにより、LeoはPreviewNodeの指定されたイニシャライザーであるself.init()を呼び出すことができ、次にSCNNodeの指定されたイニシャライザーを呼び出します。これにより、両方で発生したエラーが整理されます。「必須」「初期化子」「init(coder :)」は「SCNNode」のサブクラスによって提供される必要があります。これは、UIViewがNSCodingプロトコルを採用しているためです。

以下は、問題を処理するための3つのオプションを示すLeoのコードのコメントバージョンです。それらはすべて同じように正しいと思いますが、特定の問題に他の問題よりも適している場合があります。

import SceneKit
class PreviewNode: SCNNode {
    let previewNodeColor: UIColor = .red
    let size: CGFloat = 1
    let chamferRadius: CGFloat = 0
    //convenience override init() {   //Option 1 - use with self.init() to use the default designated initialisers up the inheritance ladder
    //override init() {               //Option 2 - use with super.init() and the additional required initialiser below
    required init(coder aDecoder: NSCoder) {  //Option 3 - Use with super.init() to initialise the geometry property of SCNNode and the required intialiser
        //self.init()
        super.init()
        let previewBox = SCNBox(width: size, height: size, length: size, chamferRadius: chamferRadius)
        previewBox.firstMaterial?.diffuse.contents = previewNodeColor
        previewBox.firstMaterial?.transparency = 0.2
        previewBox.firstMaterial?.specular.contents = UIColor.white
        self.geometry = previewBox
    }
    //Use with Option 2 to provide the additional required initialiser for NSCoder
    /*
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    */
}

古い投稿をぶつけて申し訳ありませんが、私は同じ問題を抱えていて、研究は楽しかったです:-)

1
Tim