j'ai une erreur "class 'ViewController' has no initializers ?"
Si je ne me trompe pas, on a ce message quand on a déclaré des propriétés mais qu'on ne les a pas initialisées. Le compilateur s'attend à ce que tu ajoutes une méthode init() pour le faire.
Tu peux également de déclarer les propriétés en !, ce qui indique que les variables ne sont pas initialisées à l'init, mais que tu sais ce que tu fais. Notamment, c'est le cas des IBOutlets.
Décidément j'en apprends tous les jours, il y a 3 mois quand je m'y suis un peu remis, j'avais l'impression que je pouvais tout faire et plus j'avance, plus j'en doute...
Quelque part je trouve ça passionnant et ne sais trop comment vous remercier.
Les réponses sont rapides, précises ça évite de rester bloqué trop longtemps.
Décidément j'en apprends tous les jours, il y a 3 mois quand je m'y suis un peu remis, j'avais l'impression que je pouvais tout faire et plus j'avance, plus j'en doute...
Si ça peut te rassurer, j'ai commencé mon premier projet professionnel en Swift il y a seulement trois mois. J'avais déjà un projet perso à mon actif, mais il n'a pas d'interface utilisateur, alors je n'avais pas eu à m'interfacer à UIKit.
J'ai eu de nombreuses difficultés il y a 3 mois avec les exceptions, les optionals, les closures, les initialisations... Aujourd'hui, je me sens relativement à l'aise. La solution est toujours la même: persévérer.
Je sais aussi qu'il me reste encore des sujets à approfondir: les génériques, les collections, la programmation fonctionnelle, etc. Je ne sais pas trop non plus comment fonctionne Swift sous le capot. Bref, j'ai atteint un bon niveau opérationnel, mais je ne suis pas un expert.
J'ai déjà lu ici: " Vous nous dites de ne pas utiliser le !, mais le vous le faà®tes sans arrêt ". Et je trouve ça tellement vrai. Dans la vraie vie, les propriétés ! ont leur utilité. Le tout est de savoir ce qu'on fait.
Pour les dépendances passées à un View Controller, personnellement, je les déclare ainsi:
Absolument Céroce ! Il faut savoir faire preuve de pragmatisme en ne tombant pas dans des discours extrémistes où l'utilisation du "!" est le mal absolu. Ta proposition est par ailleurs judicieuse.
J'avoue n'avoir jamais trop compris pourquoi les IBOutlets sont systématiquement "!" ?
On touche ici au point le plus problématique de Swift: c'est un langage qui tente d'être le plus statique possible " parce que ça permet de mieux détecter les erreurs de types et améliore les performances " mais qui doit composer avec des frameworks écrites dans un langage dynamique: Objective-C.
Dans le cas des Outlets, elles sont fixées par Key-Value Coding (qui n'existe qu'en Objective-C). Elle ne sont pas encore fixées à l'init, mais le sont dès qu'on arrive dans viewDidLoad(). On pourrait donc les déclarer en ?, puisqu'après-tout elles ne sont pas fixées à tout moment, il y a donc un doute quant à leur validité.
Mais le choix qu'a fait Apple est le même que celui de mon exemple ci-dessus: les déclarer ! est plus pratique, ça évite de tester à chaque fois si la propriété est nil. Et si jamais on essaie de les utiliser avant qu'elles sont fixées, on est vite au courant: ça plante.
Absolument Céroce ! Il faut savoir faire preuve de pragmatisme en ne tombant pas dans des discours extrémistes où l'utilisation du "!" est le mal absolu. Ta proposition est par ailleurs judicieuse.
On n'a jamais dit que l'utilisation du ! est le mal absolu. Juste qu'il faut savoir, en l'utilisant, ce que l'on fait :-*
Si je ne me trompe pas, on a ce message quand on a déclaré des propriétés mais qu'on ne les a pas initialisées. Le compilateur s'attend à ce que tu ajoutes une méthode init() pour le faire.
Je ne connaissais pas la méthode init() qu'il faut déclarer directement pour calmer Xcode ?
Je veux dire func init() ne marche pas alors qu'init() fonctionne du coup les alertes s'éteignent...
Mais je vois dans divers exemples que les paramètres sont réaffectés dans la fonction ?
L'idéal n'est pas de les utiliser directement et d'affecter le résultat par exemple.
Bref pas très clair tout ça, disons quid de la portée des paramètres ?
Je pense qu'il faut que tu lises le chapitre de la doc Swift d'Apple qui parle de l'initialisation. Tu verras que c'est fort complexe pour les classes.
D'ailleurs, je préfère ne pas répondre pour ne pas écrire de bêtises !
D'ailleurs, je préfère ne pas répondre pour ne pas écrire de bêtises !
Bah non ! si tu n'avais pas écrit sur l'assert dans viewDidLoad(), je n'avais jamais pensé d'utiliser ce truc et je n'aurais pas fait la recherche pour trouver qu'il est possible de mettre les vars ! à nil après :-*
Je ne connaissais pas la méthode init() qu'il faut déclarer directement pour calmer Xcode ?
init() n'est pas une méthode, c'est là pour faire l'initialisation des membres d'une classe.
Pour la classe UIViewController, il y a trois versions d'init :
class UIViewController
{
init() { ... }
init(nibName: String?, bundle: Bundle?) { ... }
init?(coder: NSCoder) { ... }
}
Si tu veux ajouter l'initialisation de tes propres vars, tu as deux choix : faire un méthode commune pour les initialiser les vars et l'appeler d'un override de tous les inits, ou initialiser tous les vars lors de leurs déclarations.
class ViewController : UIViewController
{
var nom: String
Return from initializer without initializing all stored properties
J'ai le message suivant a la fin de la fonction/directive "init"
J'ai comme l'impression que c'est la détection d'une variable de classe non initialisée ?
Après vérification elles bien toutes utilisées a différents niveaux.
Peut-on penser que parfois Xcode se trompe ?
Je veux dire que parfois il ne reconnait pas telle ou telle variable/propertie qu'il suffit souvent de réécrire.
Je n'ai jamais eu de pépins de ce genre. Tu ne peux pas montrer davantage de code ? Ce n'est pas facile de comprendre la nature du problème sur un simple message d'erreur.
class JourCouleur {
//var couleur: String = ""
var compteurAhp: Int = 0
var compteurBhp: Int = 0
var compteurAhc: Int = 0
var compteurBhc: Int = 0
var prixKwhc: Int = 0
var prixKwHp: Int = 0
var JcTotCxKw : Int = 0 //resultat du calcul
var JcTotPlKw : Int = 0 //résultat du calcul
var JcTotCxEuro : Float = 0 //résultat du calcul
var JcTotPlEuro : Float = 0 //résultat du calcul
//var date : Date
var JcLblKwHp: UILabel
var JcLblKwHc: UILabel
var JcLblTotEuro: UILabel
var JcLblTotHpEuro: UILabel
var JcLblTotHcEuro: UILabel
var JcLblHcEuro: UILabel
var JcLTfCptAhp: UITextField
var JcLTfCptBhp: UITextField
var JcLTfCptAhc: UITextField
var JcLTfCptBhc: UITextField
Essaie de simplifier ta classe. Tu devrais avoir un Modèle pour faire les calculs, et le Contrôleur qui extrait les valeurs des UITextFields, et les écrit dans les UILabels.
Essaie de simplifier ta classe. Tu devrais avoir un Modèle pour faire les calculs, et le Contrôleur qui extrait les valeurs des UITextFields, et les écrit dans les UILabels.
Effectivement en neutralisant JcLblHcEuro Xcode se calme, il me semblait l'avoir déjà neutralisé mais bon !!!
Et pourquoi tu passes tous les composants à l'init d'une classe qui n'est pas une viewController ? Ou, même, si elle était un viewController ?
L'idée de départ était de faire une classe un peu générique vu que je fais 6 fois le même calcul que pour le coup j'ai réduit a 3...
Vos 2 remarques sont très justifiées disons que c'était mais premiers essais de faire ma propre Classe Modèle confier le soin a celle-ci de faire les calculs passe encore mais d'afficher les valeurs non effectivement.
En fait j'avais démarré avec uniquement les valeurs pour en gérer le stockage, j'ai rajouter les calculs ( pas forcément une bonne chose ! ) après j'ai rajouté l'affichage, on se laisse aller dans la fouler mais passer une labelView en paramètre n'a pas vraiment gros intérêt d'autant que de paramètres en variables les choses se compliquent a souhait, au point de ne plus afficher les bonnes valeurs dans les bons labels.
Réponses
Il faut voir si toutes les propriétés de ta classe ont une valeur par défaut.
Tu peux également de déclarer les propriétés en !, ce qui indique que les variables ne sont pas initialisées à l'init, mais que tu sais ce que tu fais. Notamment, c'est le cas des IBOutlets.
Décidément j'en apprends tous les jours, il y a 3 mois quand je m'y suis un peu remis, j'avais l'impression que je pouvais tout faire et plus j'avance, plus j'en doute...
Quelque part je trouve ça passionnant et ne sais trop comment vous remercier.
Les réponses sont rapides, précises ça évite de rester bloqué trop longtemps.
J'évite quand même de poster trop vite..
Donc merci a tous.
C'est le mal !
J'ai eu de nombreuses difficultés il y a 3 mois avec les exceptions, les optionals, les closures, les initialisations... Aujourd'hui, je me sens relativement à l'aise. La solution est toujours la même: persévérer.
Je sais aussi qu'il me reste encore des sujets à approfondir: les génériques, les collections, la programmation fonctionnelle, etc. Je ne sais pas trop non plus comment fonctionne Swift sous le capot. Bref, j'ai atteint un bon niveau opérationnel, mais je ne suis pas un expert.
Bah ouais c'est pire que ça ! ::)
Il ne faut pas utiliser les ! sauf pour les IBOutlets comme :
À part de ça, c'est :
... ou :
Pour les dépendances passées à un View Controller, personnellement, je les déclare ainsi:
Et j'écris:
Et ça me semble pertinent parce que je vais savoir dès viewDidLoad() si j'ai oublié de fixer la dépendance, et c'est assurément un bug à corriger.
Alors que déclarer la dépendance en Product? rend l'erreur silencieuse, et m'oblige à un tas de contorsions avec les optionals.
Absolument Céroce ! Il faut savoir faire preuve de pragmatisme en ne tombant pas dans des discours extrémistes où l'utilisation du "!" est le mal absolu. Ta proposition est par ailleurs judicieuse.
J'avoue n'avoir jamais trop compris pourquoi les IBOutlets sont systématiquement "!" ?
Est-ce que quelque part ça voudrait dire qu'il ne faut jamais les utiliser directement ?
On touche ici au point le plus problématique de Swift: c'est un langage qui tente d'être le plus statique possible " parce que ça permet de mieux détecter les erreurs de types et améliore les performances " mais qui doit composer avec des frameworks écrites dans un langage dynamique: Objective-C.
Dans le cas des Outlets, elles sont fixées par Key-Value Coding (qui n'existe qu'en Objective-C). Elle ne sont pas encore fixées à l'init, mais le sont dès qu'on arrive dans viewDidLoad(). On pourrait donc les déclarer en ?, puisqu'après-tout elles ne sont pas fixées à tout moment, il y a donc un doute quant à leur validité.
Mais le choix qu'a fait Apple est le même que celui de mon exemple ci-dessus: les déclarer ! est plus pratique, ça évite de tester à chaque fois si la propriété est nil. Et si jamais on essaie de les utiliser avant qu'elles sont fixées, on est vite au courant: ça plante.
On n'a jamais dit que l'utilisation du ! est le mal absolu. Juste qu'il faut savoir, en l'utilisant, ce que l'on fait :-*
Mais il faut faire attention quand même ailleurs parce qu'on pourrait toujours faire :
... après que l'on est déjà passé par viewDidLoad()
Je ne connaissais pas la méthode init() qu'il faut déclarer directement pour calmer Xcode ?
Je veux dire func init() ne marche pas alors qu'init() fonctionne du coup les alertes s'éteignent...
Mais je vois dans divers exemples que les paramètres sont réaffectés dans la fonction ?
L'idéal n'est pas de les utiliser directement et d'affecter le résultat par exemple.
Bref pas très clair tout ça, disons quid de la portée des paramètres ?
Je pense qu'il faut que tu lises le chapitre de la doc Swift d'Apple qui parle de l'initialisation. Tu verras que c'est fort complexe pour les classes.
D'ailleurs, je préfère ne pas répondre pour ne pas écrire de bêtises !
Bah non ! si tu n'avais pas écrit sur l'assert dans viewDidLoad(), je n'avais jamais pensé d'utiliser ce truc et je n'aurais pas fait la recherche pour trouver qu'il est possible de mettre les vars ! à nil après :-*
init() n'est pas une méthode, c'est là pour faire l'initialisation des membres d'une classe.
Pour la classe UIViewController, il y a trois versions d'init :
Si tu veux ajouter l'initialisation de tes propres vars, tu as deux choix : faire un méthode commune pour les initialiser les vars et l'appeler d'un override de tous les inits, ou initialiser tous les vars lors de leurs déclarations.
... ou :
ça ne répond pas a la question sur la portée.
Pourquoi pas ?
Si les vars sont déclarées dehors l'init() mais elles sont initialisées dans l'init(), elles restent en mémoire après.
Pour finir sur cette partie du sujet il faut appeler la fonction init(typeParam: monParam.......)
moninstance = moninstance.maClasse(typeParam: monParam,........)
Je suppose que si la méthode init a l'attribut "requered" l'appel de la méthode init est obligatoire ?
Je suppose qu'il faut utiliser TOUS les paramètres ?
Pendant qu'on y est faut-il (obligatoirement) killer l'instance créée après utilisation ?
J'ai le message suivant a la fin de la fonction/directive "init"
J'ai comme l'impression que c'est la détection d'une variable de classe non initialisée ?
Après vérification elles bien toutes utilisées a différents niveaux.
Peut-on penser que parfois Xcode se trompe ?
Je veux dire que parfois il ne reconnait pas telle ou telle variable/propertie qu'il suffit souvent de réécrire.
Je n'ai jamais eu de pépins de ce genre. Tu ne peux pas montrer davantage de code ? Ce n'est pas facile de comprendre la nature du problème sur un simple message d'erreur.
Le message apparaà®t en face de la dernière accolade ....
Essaie de simplifier ta classe. Tu devrais avoir un Modèle pour faire les calculs, et le Contrôleur qui extrait les valeurs des UITextFields, et les écrit dans les UILabels.
Et pourquoi tu passes tous les composants à l'init d'une classe qui n'est pas une viewController ? Ou, même, si elle était un viewController ?
Effectivement en neutralisant JcLblHcEuro Xcode se calme, il me semblait l'avoir déjà neutralisé mais bon !!!
L'idée de départ était de faire une classe un peu générique vu que je fais 6 fois le même calcul que pour le coup j'ai réduit a 3...
Vos 2 remarques sont très justifiées disons que c'était mais premiers essais de faire ma propre Classe Modèle confier le soin a celle-ci de faire les calculs passe encore mais d'afficher les valeurs non effectivement.
En fait j'avais démarré avec uniquement les valeurs pour en gérer le stockage, j'ai rajouter les calculs ( pas forcément une bonne chose ! ) après j'ai rajouté l'affichage, on se laisse aller dans la fouler mais passer une labelView en paramètre n'a pas vraiment gros intérêt d'autant que de paramètres en variables les choses se compliquent a souhait, au point de ne plus afficher les bonnes valeurs dans les bons labels.
Donc encore et toujours merci...