Le but est de sous-classer SCNNode. Selon le class docs , init(geometry geometry: SCNGeometry?)
est un initialiseur désigné (aucun mot clé convenience
n'est répertorié). Ce code n'invoque-t-il donc pas un initialiseur désigné de sa super-classe?
Pourquoi Xcode affiche-t-il l'erreur suivante?
Doit appeler un initialiseur désigné de la superclasse 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)
}
}
Le problème est que vous essayez également d'accéder à vos propriétés PreviewNode avant d'appeler self.init ().
Essayez comme ça:
Xcode 8 GM • Swift 3
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
}
}
Utilisé cette réponse, mais Leo Dabus mérite un crédit. Veuillez commenter si vous pouvez expliquer s’il est tout aussi valable de définir un nouvel initialiseur pratique que Leo l’a fait ou de remplacer l’initialiseur par défaut comme le fait cette réponse, ou si l’un est préférable l’autre.
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
}
}
D'après ce que je comprends du Guide de Swift 4.2, les initialiseurs désignés doivent initialiser toutes les propriétés stockées. Les initiateurs de commodité peuvent initialiser un sous-ensemble de propriétés (ce qui peut être utile pour créer des instances dans des circonstances différentes). Ils doivent toutefois appeler un initialiseur désigné de la sous-classe qui à son tour appelle l'initialiseur désigné de la ou des superclasses pour initialiser toutes les propriétés stockées avant la personnalisation commence. Ce diagramme du guide rapide peut aider:
En utilisant le mot clé de commodité, Leo peut alors appeler self.init (), qui est l'initialiseur désigné de PreviewNode, qui à son tour appelle l'initialiseur désigné de SCNNode. Cela résout l’erreur que nous avons tous les deux: l’initialisation 'obligatoire' initializer 'init (coder :)' doit être fournie par la sous-classe de 'SCNNode'. En effet, UIView adopte le protocole NSCoding.
Vous trouverez ci-dessous une version commentée du code de Leo indiquant les trois options permettant de gérer le problème. Je pense qu'ils sont tous également corrects, mais on peut résoudre un problème particulier mieux que d'autres.
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")
}
*/
}
Désolé de remplacer un ancien message, mais le problème est le même et la recherche était amusante :-)