目標は、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)
}
}
ここでの問題は、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
}
}
この答えを使用しましたが、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
}
}
Swift 4.2ガイドからの私の理解では、指定されたイニシャライザーはすべての保存されたプロパティを初期化する必要があります。便利なイニシャライザーはプロパティのサブセットを初期化できます(さまざまな状況でインスタンスを作成するのに役立つ場合があります)が、最初にサブクラスの指定されたイニシャライザーを呼び出し、次にスーパークラスの指定されたイニシャライザーを呼び出して、カスタマイズを開始する前にすべての格納されたプロパティを初期化します。Swiftガイドのこの図は、次の場合に役立ちます。
便利なキーワードを使用することにより、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")
}
*/
}
古い投稿をぶつけて申し訳ありませんが、私は同じ問題を抱えていて、研究は楽しかったです:-)