Cannot assign to property: 'self' is immutable
Céroce
Membre, Modérateur
Bonjour à tous,
Je me considère encore comme un débutant en Swift... et j'ai un problème avec ce code:
- SCNShadable est un protocole de Scene Kit
- Ma classe DxDyShader hérite de NSObject, sinon elle ne peut pas implémenter SCNProgramDelegate.
Mes questions:
1) Pouvez-vous m'expliquer ce message d'erreur (dans la méthode init()) ?
2) Comment écriviriez-vous ce code ?
Merci !
Je me considère encore comme un débutant en Swift... et j'ai un problème avec ce code:
Quelques précisions:
import Cocoa
import SceneKit
class DxDyShader: NSObject {
var shadable: SCNShadable
var program: SCNProgram {
let prg = SCNProgram()
prg.delegate = self
return prg
}
init(shadable: SCNShadable) {
self.shadable = shadable
self.shadable.program = self.program // Cannot assign to property: 'self' is immutable
}
}
extension DxDyShader: SCNProgramDelegate {
func program(program: SCNProgram, handleError error: NSError) {
NSLog("Could not compile shader")
}
}
- SCNShadable est un protocole de Scene Kit
- Ma classe DxDyShader hérite de NSObject, sinon elle ne peut pas implémenter SCNProgramDelegate.
Mes questions:
1) Pouvez-vous m'expliquer ce message d'erreur (dans la méthode init()) ?
2) Comment écriviriez-vous ce code ?
Merci !
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Ah les joies du mix Swift/Obj-C. Premièrement program est de type SCNProgram? mais comme il s'agit d'un protocol et que l'ivar program est notée optional on se retrouve avec SCNProgram??. Ouais, ça commence bien...
L'idéal est de faire comme en Obj-C en vérifiant si ton objet implémente cette partie optionnelle du protocol et de faire appel au setter :
Ce code est écrit en Swift 3.0, je précise.
Pour program comme on ne sait pas si shadable l'implémente on peut au mieux renvoyer un optional donc SCNProgram?. Au passage on va chercher la valeur directement dans self.shadable histoire de coder un peu propre. (Pas que tu ne code pas propre, mais un développeur aguerri comme toi verra où je veux en venir).
J'ai une journée de code derrière moi, alors je regarderai ça demain matin, quand je serai plus frais.
http://stackoverflow.com/questions/26083377/swift-setting-an-optional-property-of-a-protocol
Donc, pour résumer:
- le message d'erreur est totalement à côté de la plaque
- le problème est que le protocole SCNShadable a sa propriété .program qui est marquée @optional dans le protocole.
C'est un problème d'interoperatibilité entre Swift et ObjC.
J'essaie de faire fonctionner puis je posterai ici.
@Pyroh: je déteste l'idée d'utiliser le runtime ObjC pour contourner le problème. Certes, ça passe, mais on perd aussi le contrôle effectué par le compilateur. J'aimerais éviter autant que possible; c'est tout de même un apport majeur de Swift.
Je me disais aussi que le compilo eÌtait un peu aux fraises avec son message d'erreur...
Maintenant le soucis ici c'est pas Swift en lui meÌ‚me mais son inter-opeÌrabiliteÌ avec Objective-C.
Dans la mesure où tu ne peux pas deÌclarer quoi que ce soit d'optionnel dans un protocol Swift il est normal qu'il faille se reposer sur le runtime Obj-C pour geÌrer une de ses spécificités...
En gros, je crée un protocole dérivé de SCNShadable, mais où la propriété 'program' est obligatoire. Et je caste le shadable vers ce protocole. C'est la technique exposée par Aligator.
Je n'ai pas testé sur Swift 3, et j'ignore si le problème se pose toujours.
P.S.: Qui disait que Swift était facile ?
Mon code complet donne ça:
Au passage, je viens de découvrir la différence entre "computed properties" et "function properties". Ce sont bien ces dernières que je veux!