[Udemy - Swift 3] On en parle ?
Je suis en train de suivre ces cours que ne trouve pas si mal que ça, j'en suis a la leçon 66 en train de me battre avec Core Data... Au milieu de l'exercice ListeTodo après quelques problèmes tout est revenu dans l'ordre. J'avoue trouvé que Sandy navigue un peu vite et sans beaucoup d'explications d'un fichier a l'autre... Mais bon généralement je me fais ma petite application a moi même personnellement en utilisant l'exercice...
J'ai tout même quelques questions:
L'utilité des ponctuations réclamées pas Xcode a qui Sandy obéit sans vraiment d'explications.
Déjà les ponctuations:
"?" je crois comprend que ça correspond a une variable optionnelle donc affectée ou non ?
"!" correspond a la valeur incluse dans la variable ou la constante en question ? dans quel cas doit-on l'utiliser éventuellement ou obligatoirement ?
"as" doit probablement correspondre au type de valeur attendue ??? j'avoue patauger.
la test "do","try","catch" le do{.../...} doit indique le début d'une fonction de teste ?
try lance le teste ? par contre dans un do il semble possible qu'il y ait plusieurs "try"
et le "catch" est appelé en cas d'erreur ?
Un site qui résumerait bien cette fonction ?
Réponses
Tu parles de quels cours, là ? Sandy Ludosky, une formatrice plutôt active, en a développé 3 en français traitant de Swift, sur Udemy :
- Les fondamentaux de Swift 3 - Formation complète (4,5 heures de vidéos)
- Cours complet développeur iOS 9 - Créez 18 Applications (19 heures de vidéos)
- Cours complet iOS10 & Swift 3 - Créez 15 applications (21 heures de vidéos) - je l'ai acheté celui-ci
T'es fou de poser des questions pareils. Joanna vas se jeter sur toi et t'étrangler avec une fourchette ! Ex-Ali t'aurais piétiné avec un troupeau de poneys !
La bonne réponse est NE JAMAIS UTILISER !, NE PAS PENSER A !, JAMAIS, JAMAIS, JAMAIS ...
Le manuel de référence du langage disponible gratuitement sur iTunes ?
Je vais être un peu direct mais, tu poses des questions basiques de Swift, vraiment basiques.
Je vais passer le ? et le !, car ne faisant pas de Swift, je ne sais jamais ce que cela veut dire.
Mais le as est un cast.
Le try/catch/do, cela se fait dans d'autres languages. Et c'est notamment avec ces mécanismes que Swift (depuis la 2.3 je crois) gère les NSError (qu'on met en &error en Objective-C).
Le reste, c'est CoreData, et c'est un sujet complexe. Je recommanderais donc d'étudier plus en détails les bases du Swift avant de te lancer dans CoreData.
Le symbole "?" est affiché par Xcode pour rappeler au développer qu'il utilise une variable optionnelle, qu'elle soit affectée ou non.
Exemple : je crée une application simpliste ne contenant pas grand chose :
Un ViewController vide et une vue vide .. le commencement de tout.
J'ai envie que le fond soit en bleu, alors j'ajoute une instruction.
Magique, je suis dieu ! J'ai créé un micro-univers et il est bleu !
Je peux placer des vues sur la vue principale et les faire vivre. Les dieux aiment toujours avoir un numéro 6 à surveiller, alors j'en crée un :
La variable numero6 contient l'adresse de la vue, ce qui permet d'y accéder facilement pour modifier son état.
On peut agir sur toutes les sous-vues de la vue principale en les stockant dans des variables. Mais il est également possible de leurs associer un numéro d'identification avec la propriété .tag.
Pour retrouver numero6 j'ai juste besoin de demander à la vue principale un lien vers la vue secondaire contenant le tag 6.
Pour colorier numéro6 en rouge, il faut modifier sa propriété .backgroundColor.
Sauf que Xcode n'est pas d'accord avec cette syntaxe et modifie automatiquement le code en ajoutant un "?" après le nom de la vue.
Pourquoi ? Parce que la fonction viewWithTag() retourne une UIView optionnelle (UIView?). Il n'est pas certain qu'il existe une vue secondaire dans la vue principale, avec le .tag 6. L'opération peut échouer, donc iOS retourne une valeur optionnelle.
Ecrire une valeur dans une variable optionnelle nulle, c'est la catastrophe assurée et un plantage immédiat. C'est pourquoi Xcode a l'intelligence d'ajouter un "?" après le nom de la variable. C'est une syntaxe qui signifie :
- si fugitif contient un objet de type UIView on modifie sa propriété .backgroundColor
- si fugitif contient la valeur NIL on ne fait rien, il ne se passe pas de catastrophe.
Le "?" est un mécanisme de sécurité, qui a aussi l'avantage de rappeler visuellement au développeur que fugitif est une variable optionnelle.
Si Sandy n'en parle pas, c'est qu'elle doit considérer cela comme acquit. Parce que c'est vraiment la base..
Comme je le disais plus haut, on ne doit JAMAIS utiliser !. C'est dangereux ce truc et surtout plantogéne.
Cela correspond au contenu de la valeur, en PRESUMANT QU'ELLE EXISTE, ce qui n'est pas toujours le cas.
Je reprend mon exemple précédent, en modifiant le "?" par un "!" parce je SAIS que numéro6 est là , et sera toujours là .
Je compile. Xcode ne bronche pas. J'exécute, ça marche encore et encore.
Et puis un jour, pour une raison ou une autre, il n'y a plus de vue tagée 6. Et l'application se crache en beauté sur la ligne :
IL NE FAUT JAMAIS UTILISER !, MEME SI LE COMPILATEUR LE PROPOSE !!
La meilleure manière d'utiliser une variable optionnelle est d'en créer une version temporaire non-optionnelle, avec if let :
Si la valeur est NIL, if let n'exécute pas les instructions comprises entre les { }, donc pas de risque de plantage ..
Si la valeur n'est pas NIL, if let crée une version non-optionnelle temporaire de la valeur qu'on peut utiliser normalement, sans ajouter de !. Que du bonheur ..
a
as est un opérateur de casting permettant de transformer le type d'objet.
Je reprend mon exemple et je crée un label portant le numéro 42.
a
a
Si je veux modifier son contenu, ma première idée est de le chercher à partir de son tag 42 et d'écrire quelque chose dans sa propriété .text.
a
a
Sauf que Xcode refuse avec énergie, indiquant que label42 ne possède pas de propriété .text.
Et il a raison ! La fonction viewWithTag retourne l'objet UIView contenant le tag 42. C'est un UILabel, mais viewWithTag() ne la connaà®t que sous forme d'un UIView. C'est un problème courant quand on utilise un framework manipulant des objets construits sur une hiérarchie d'héritage. Seul le type de base (UIView) est connu, et non les types dérivés (UILabel, UIImage, UIButton, UISlider, etc ..).
Il faut caster le UIView en UILabel pour l'utiliser.
On pourrais penser qu'il faut utiliser cette syntaxe :
a
a
Mais Xcode n'en veut pas, disant qu'il est impossible de convertir un UIView? en un UILabel. A la place il propose d'ajouter un ! :
a
a
Et ça marche .. Pourtant c'est une connerie. Xcode est parfois un sacré couillon !
Il suffit de changer la valeur 42 par 41 pour voir arriver les ennuis. L'opérateur "as!" ne tient pas plus compte de la valeur NIL que l'opérateur "!". C'est le plantage assuré s'il n'existe pas de vue secondaire avec le .tag 41.
Pour éviter la catastrophe il faut utiliser as? qui génère une valeur optionnelle, même si Xcode "oublie" de proposer cette syntaxe.
a
a
Ou, plus facile que ça :
Nous avons donc la même, un peu logique d'utiliser la dernière...
Merci pour toutes tes explications sur ! et ? je devrai les relire quand même.
Par contre pourquoi Xcode oblige toujours a rajouter ça si c'est si plantogène ?
Merci pour cette réponse ! Souvent les choses hyper basiques comme celles-ci (semble-t-il) le sont tellement que finalement personne n'en parle pensant que tout le monde le sait...
Core Data en assez complet mais pour tout mes petits projets je dois pratiquement l'utiliser tout le temps, donc je fais et refais les tutoriels, sans pour autant en utiliser les options les plus pointues. Mais bon les choses évoluent et c'est tout de même assez facile de faire évoluer une Application d'autant que si je me souviens bien Core Data va géré la version précédente ?
Oh, et ne pas utiliser les tags comme ça. C'est plus facile de créer les @IBOutlet sur le ViewController et les connecter.
C'est clair. Mais dans le cas présent, cela donne un exemple simple à comprendre.
Ou alors t'es radin. Parce que moi j'ai acheté cette formation un peu au hasard, uniquement parce qu'elle était en solde ..
Oui, tu devrais ..
Alors ça, mystère .. Ils ont peut-être laissé ça de coté pour Swift 4.
Ok moi je veux bien mais Xcode l'impose ne serait-ce déjà que pour les Outlets, j'ai tenté de supprimer le "!" il refuse grave !!
ça c'est un cas spécial. Il est attendu que les outlets seront obligatoirement connectés est, du coup, valides. En plus, ayant les ! sur les outlets empêche le compilateur de continuer à dire que les vars doivent être initialisés, après que tu les as ajouté mais avant que tu les aies connecté.
Oui, c'est impossible de s'en passer avec les Outlets. C'est le seul cas où c'est vraiment nécessaire.
Xcode postule qu'un objet graphique créé avec Storyboard existe forcément.
À part des outlets, il faut dire que le compilateur propose souvent les ! comme solution; un conseil sur lequel il faut bien réfléchir.
Le seul temps que je peux imaginer les permettre, c'est dans le code après que l'on a déjà vérifié que la valeur ne soit bien pas nil.
Mais c'est toujours préférable d'utiliser les "if let x =" ou les "guard let x =".
Je me souviens avoir réalisé un tuto il y a quelques temps déjà une "Trésorerie" opérationnelle avec Core Data et Zéro ligne de code...
J'espérais retrouver la même chose....
A partir de ce post, la conversion a divergé vers l'utilisation de CoreData avec Swift. J'ai demandé à la modération de séparer le fil du post en deux sections. Voici le lien pour accéder aux autres posts :
http://forum.cocoacafe.fr/topic/15239-introduction-à -coredata-swift-3/
pendant que nous sommes revenus sur le sujet initial quelques questions (basiques même):
1°) - L'utilisation de underscore "_" ou avec un espace "_ ", déjà Xcode le met d'office avec les Outlets ou Action et pourquoi après l'avoir mit dans les paramètres de la fonction on en est dispensé après ? J'ai l'impression de "Sandy" suit les doléances d'Xcode et ça lui apparaà®t évident, mais toujours pas d'explications !!
"
2°) - Dans les remarques elle utilise "//MARK .... " Je suppose que c'est pour faire apparaitre ces remarques comme une sorte de titre quand on active le PopUp correspondant ? Mais comment fait-on pour faire apparaà®tre ces titres justement ?
3°) - L'utilisation de "in" comme dans "fetchTodos("") { (array, arrayData) in " ?
fetchTodos("") { (array, arrayData) l'explication du ("") ?
a
Pour afficher les MARK: il faut cliquer en haut de la fenêtre, comme montré dans l'image ci-jointe. C'est un truc que j'ai appris récemment avec le MOOC de F. Kordon.
Euh c'est où ça ? Dans quelle leçon de Sandy ? Que je puisse comprendre le contexte d'utilisation.
1. Le _ est là pour les occasions -
a) quand on ne veut pas utiliser la valeur comme dans ce code de Draken :
Ici il voulait faire une boucle 401 fois mais il n'utilise pas les nombres de 0 à 400 dans la boucle.
b ) quand on ne veut pas devoir saisir le nom d'un paramètre dans l'appel à une méthode comme :
Les deux "noms" avant le ":" sont le nom externe, suivi par le nom interne.
Ici il faut avoir un nom de paramètre interne mais, parce que le nom de la méthode contient déjà "Interactor", on veut éviter de le répéter :
à la place de :
2. // MARK: signifie que la ligne apparaà®tra dans le menu en haut de la fenêtre de code, entre les mentions de noms des classes, fonctions, etc ; c'est pour diviser le code et pour marquer les sections.
@Draken - évidemment, j'étais en train de rédiger ma réponse au même temps que toi 8--)
>:( Tu m'as empêché de poster un bel exemple de boucle avec un _.
Allez tant pis, je le poste quand même, mais sans explications :
EDIT: Et zut, le forum n'affiche pas les emojis ! Tant pis pour la tête de clown ..
Pour la MARK j'ai fini par comprendre en fait il faut MARK: et MARK:- ajoute une ligne sur le PopUp. de mémoire en ObjC c'est PRAGMA MARK quelque chose comme ça ?
j'ajoute pour ma défense que Sandy l'oublie souvent...
Des la leçon 73 Modifier Todo, dans le fichier TodoTableViewController, dans la fonction par exemple :
Pour fetchTodos(), regarde la méthode, sa déclaration, donne-là nous. Je suppose que le premier paramètre est un String, et là , elle donne un String vide, d'où "". Pour le reste, je suppose qu'il s'agit d'une closure (appelé block en Objective-C).
Au pifomètre via conjecture fortement poussée, je dirai que cette méthode regarde le paramètre String donné, fait une recherche dessus (genre un NSPredicate sur le nom de l'entité, mais si vide, pas de predicat), mais le tout étant asynchrone, elle renvoie ses données via une closure.
J'utilise #pragma mark en Objective-C.
C'est plus pour faire joli qu'autre chose. Ordonner le code, etc. Bien qu'avoir de bonnes habitudes, c'est un truc à avoir, je pense que le principe de ce cours est d'expliquer les concepts de CoreData plutôt.
Il faut différencier le cours de base (qui t'explique pourquoi tu as "!", des "?", des "if let") d'un cours de concept. Je ne connais pas le Swift à vraiment parler, je connais les concepts, et quand je code en Swift pour tester, bidouiller, je passe volontairement les ! et ?, j'laisse XCode faire, car c'est "confiné", je sais qu'il y a valeur ou non. C'est un peu comme mettre nil dans une methode avec un NSError en paramètre, ce qui revient à faire un try! je crois en Swift, c'est à dire ne pas faire de catch et prier pour que tout fonctionne.
Sauf que cela parfois peut alourdir le code et cacher l'explication du concept.
Avec mon faible niveau en Swift et le fait de ne pas connaà®tre le cours, je ne peux pas juger, et je ne dis pas que ce que l'auteur enseigne est bon ou mauvais, mais la première règle d'Internet, c'est de toujours douter, de remettre en question, et en matière de code, de tester, bidouiller, ne jamais prendre tel quel un code de StackOverflow ou assimilé sans avoir compris, c'est parfois mauvais.
Suite à ton post avec le code de fetchToDo(), c'est bien ce qu'il me semblait (à la question du predicate près).
Le "in" correspond à une closure. C'est un usage basique, qu'on peut retrouver dans (NS)URLSession, Alamofire, UIAlertActionController, etc.
Pour du Swift 3, je trouve cependant dommage d'utiliser des NSDictionary et NSArray et ne pas préférer les types Swift équivalents (alors que y'a un Dictionary Swift juste avant).
Je vais regarder la leçon pour comprendre. Pour le moment je suis totalement d'accord avec Larme.
Je suis toujours étonné de la manière dont Sandy utilise les closures. Cela complique le code, pour un intérêt que je n'arrive pas à saisir.
Une closure est un bloc d'instructions qui ne sont pas destinés à être exécutés tout de suite, mais plus tard. C'est une sorte de processus multi-tâche, indépendant du reste de l'application. Cela permet de manipuler des séquences de code comme des variables.
On s'en sert notamment pour les animations, avec la méthode UIView.animate(). A titre d'exemple j'ai écrit une fonction affichant un message de bienvenu sur l'écran, avant de le faire disparaitre progressivement.
La méthode UIView.animation(withDuration:) utilise deux blocs. L'un pour indiquer l'objectif de l'animation, et l'autre pour préciser ce qui doit se passer à la fin de l'animation.
Le bloc d'animation est court, ne manipulant qu'une propriété d'un seul objet. Mais il pourrais être plus long.
Le bloc de completion contient le traitement à exécuter à la fin de l'animation.
C'est une action un peu violente, puisqu'il s'agit de la destruction du label créé pour afficher le message de bienvenu. Bye bye petit label tu as rempli ta mission, il est temps de libérer la mémoire ..
Ce bloc a besoin d'une variable en entrée, d'où la syntaxe un peu différente de la précédente. Enfin quand je dis qu'il a besoin d'une variable, j'exagère un peu. Disons qu'un développeur d'Apple s'est dis que, peut-être un jour, éventuellement, il pourrais arriver que la complétion soit appelé alors que l'animation n'est pas terminée. Et il a intégré une valeur binaire (booléenne) dans l'appel du bloc de complexion, pour signaler cette possibilité.
La syntaxe d'un bloc avec des variables est :
La completion de l'animation devrais s'écrire :
Mais comme on se fiche généralement de savoir si l'animation s'est terminée correctement ou pas, on écrit :
D'ailleurs Xcode lui même propose cette syntaxe par défaut.
Sandy utilise un bloc avec deux variables, d'où son utilisation de cette syntaxe :
Je vois comment elle fait, mais je ne comprend pas pourquoi elle le fait. Elle procédait déjà de même avec l'exemple dont nous avons parlé dans le topic sur l'introduction à CoreData. Tu as vu comment j'ai réécrit son code pour l'épurer, le simplifier et le rendre plus lisible, en n'utilisant que des éléments propres à Swift. Sandy si un jour, tu passes par notre bar, n'hésite pas à poster ici..