[Udemy - Swift 3] On en parle ?

GercofisGercofis Membre
mai 2017 modifié dans Dev. iOS, watchOS, tvOS #1

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 ?


«13

Réponses

  • DrakenDraken Membre
    mai 2017 modifié #2

    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


     


     



     


     


    "!" correspond a la valeur incluse dans la variable ou la constante en question ? dans quel cas doit-on l'utiliser éventuellement ou obligatoirement ?

    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 ... 

  • zoczoc Membre


    Un site qui résumerait bien cette fonction ?


    Le manuel de référence du langage disponible gratuitement sur iTunes ? :)
  • LarmeLarme Membre
    mai 2017 modifié #4

    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.


  • DrakenDraken Membre
    mai 2017 modifié #5

     


     


    "?" je crois comprend que ça correspond a une variable optionnelle donc affectée ou non ?

     


    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 :



    import UIKit

    class ViewController: UIViewController {

    override func viewDidLoad() {
    super.viewDidLoad()
    }
    }


    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.


     



     


    import UIKit


     


    class ViewController: UIViewController {


     


        override func viewDidLoad() {


            super.viewDidLoad()


            


            self.view.backgroundColor = UIColor.cyan


            


        }


    }


     


     


    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 :



    import UIKit

    class ViewController: UIViewController {

    override func viewDidLoad() {
    super.viewDidLoad()

    self.view.backgroundColor = UIColor.cyan

    let rect = CGRect(x: 100, y: 100, width: 100, height: 100)

    // création de numéro 6
    let numero6 = UIView(frame: rect)
    self.view.addSubview(numero6)

    numero6.backgroundColor = UIColor.blue

    }
    }


    La variable numero6 contient l'adresse de la vue, ce qui permet d'y accéder facilement pour modifier son état.



    numero6.backgroundColor = UIColor.blue

    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.



    numero6.tag = 6

    Pour retrouver numero6 j'ai juste besoin de demander à  la vue principale un lien vers la vue secondaire contenant le tag 6.



    let fugitif = self.view.viewWithTag(6)

    Pour colorier numéro6 en rouge, il faut modifier sa propriété .backgroundColor.



    fugitif.backgroundColor = UIColor.red

    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.



    fugitif?.backgroundColor = UIColor.red

    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..

  • DrakenDraken Membre
    mai 2017 modifié #6

     


     


    "!" correspond a la valeur incluse dans la variable ou la constante en question ? dans quel cas doit-on l'utiliser éventuellement ou obligatoirement ?

    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à .



    let fugitif = self.view.viewWithTag(6)
    fugitif!.backgroundColor = UIColor.red

    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 :



    fugitif!.backgroundColor = UIColor.red

    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 :



    let fugitif = self.view.viewWithTag(6)
    // ICI fugitif est une valeur optionnelle pouvant contenir NIL
    if let fugitif = fugitif {
    // ICI fugitif est une valeur non-optionnelle
    // contenant forcément quelque chose
    // On peut l'utiliser sans risque
    // ATTENTION c'est une variable temporaire n'existant
    // qu'entre les { } du if let
    fugitif.backgroundColor = UIColor.red
    }


    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 ..

  • DrakenDraken Membre
    mai 2017 modifié #7

     


     


    "as" doit probablement correspondre au type de valeur attendue  ??? j'avoue patauger.

    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



    import UIKit

    class ViewController: UIViewController {

    override func viewDidLoad() {
    super.viewDidLoad()

    self.view.backgroundColor = UIColor.cyan

    let rect = CGRect(x: 100, y: 100, width: 100, height: 100)

    let label = UILabel(frame: rect)
    label.tag = 42
    self.view.addSubview(label)

    }
    }


    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



    // Identification Label par tag
    let label42 = self.view.viewWithTag(42)
    label42.text = "Hello !"


    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



    let label42 = self.view.viewWithTag(42) as UILabel

    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



    let label42 = self.view.viewWithTag(42) as! UILabel

    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



    let label42 = self.view.viewWithTag(42) as? UILabel


    a



    // Identification Label par tag
    let label42 = self.view.viewWithTag(42) as? UILabel
    // Si le label existe on peut l'utiliser
    if let label = label42 {
    // On peut manipuler le label normalement ici
    label.text = "Mon texte"
    }


  • Joanna CarterJoanna Carter Membre, Modérateur


    a



    // Identification Label par tag
    let label42 = self.view.viewWithTag(42) as? UILabel
    // Si le label existe on peut l'utiliser
    if let label = label42 {
    // On peut manipuler le label normalement ici
    label.text = "Mon texte"
    }



     


    Ou, plus facile que ça :



    if let label42 = self.view.viewWithTag(42) as? UILabel
    {
    label42.text = "Mon texte"
    }


  • 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 :


    .../...


    - Cours complet iOS10 & Swift 3  - Créez 15 applications (21 heures de vidéos) - je l'ai acheté celui-ci


    .../...




     


    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 ?


     


     




    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.




     


    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 ?

  • Joanna CarterJoanna Carter Membre, Modérateur

    Oh, et ne pas utiliser les tags comme ça. C'est plus facile de créer les @IBOutlet sur le ViewController et les connecter.




  • 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.


  •  


    Nous avons donc la même, un peu logique d'utiliser la dernière...



    Ou alors t'es radin. Parce que moi j'ai acheté cette formation un peu au hasard, uniquement parce qu'elle était en solde ..


     



     


    Merci pour toutes tes explications sur ! et ? je devrai les relire quand même.



    Oui, tu devrais ..


     



     


    Par contre pourquoi Xcode oblige toujours a rajouter ça si c'est si plantogène ?



    Alors ça, mystère .. Ils ont peut-être laissé ça de coté pour Swift 4.



  •  


    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 ... 




     


     


    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 !!

  • Joanna CarterJoanna Carter Membre, Modérateur


    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.

  • Joanna CarterJoanna Carter Membre, Modérateur
    mai 2017 modifié #16

    À 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 =".




  • 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.




     


    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....

  • CéroceCéroce Membre, Modérateur

    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...

    Ce qui est bien avec le marketing d'Apple, c'est qu'il couvre tous les aspects de leur business, même les outils de programmation.
  • 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/

  • GercofisGercofis Membre
    mai 2017 modifié #20

    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 ("") ?


  • DrakenDraken Membre
    mai 2017 modifié #21

    import UIKit

    class ViewController: UIViewController {

    override func viewDidLoad() {
    super.viewDidLoad()

    fonction1(nom: "Barak Obama", age: 55)
    fonction2("Donald Trump", 70)

    }

    // MARK: Fonction classique avec des paramétres nommés
    func fonction1(nom:String, age:Int) {
    }

    // MARK: Raz-le-bol de la dictature des paramétres nommés
    func fonction2(_ nom:String, _ age:Int) {
    }

    }



    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.




  • 3°) - L'utilisation de "in" comme dans "fetchTodos("") { (array, arrayData) in " ?


     


    fetchTodos("") { (array, arrayData) l'explication du ("") ?




    Euh c'est où ça ? Dans quelle leçon de Sandy ? Que je puisse comprendre le contexte d'utilisation.

  • Joanna CarterJoanna Carter Membre, Modérateur
    mai 2017 modifié #23

    1. Le _ est là  pour les occasions -


     


      a) quand on ne veut pas utiliser la valeur comme dans ce code de Draken :



    var chrono:Double = 0.0

    for _ in 0...400
    {
    chrono += 0.1

    print (chrono)
    }

    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 :



    func addNestedInteractor(_ interactor: Interactor)
    {
    ...
    }

    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 :



    {
    myInteractor.addNestedInteractor(autreInteractor)
    }

    à  la place de :



    {
    myInteractor.addNestedInteractor(interactor: autreInteractor)
    }

    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.


     


    mark.png 184.2K
  • Joanna CarterJoanna Carter Membre, Modérateur

    @Draken - évidemment, j'étais en train de rédiger ma réponse au même temps que toi  8--)


  • DrakenDraken Membre
    mai 2017 modifié #25

    >:( 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 :



    for _ in 1...3 {
    print ("Trump, ou ?")
    }



    EDIT:  Et zut, le forum n'affiche pas les emojis ! Tant pis pour la tête de clown ..

  • GercofisGercofis Membre
    mai 2017 modifié #26

    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...


     




    Euh c'est où ça ? Dans quelle leçon de Sandy ? Que je puisse comprendre le contexte d'utilisation.




     


    Des la leçon 73 Modifier Todo, dans le fichier TodoTableViewController, dans la fonction par exemple :



    override func viewDidAppear(_ animated: Bool)
    {
    fetchTodos("")
    {
    (array, arrayData) in

    todos = array as? [NSDictionary]

    tableView.reloadData()
    }
    }

     

    j'avoue ne pas avoir tout compris mais je regarde dans ce sens

     

    Merci a tous les deux....

     


     

     


  • LarmeLarme Membre
    mai 2017 modifié #27

    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.


  • GercofisGercofis Membre
    mai 2017 modifié #28

    func fetchTodos(_ predicate:String, completion:(_ array:NSArray,_ arrayData:NSArray)->()) {

    var arr = [NSDictionary]()
    var arrData = [NSManagedObject]()
    let requete:NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName:"Todo")

    requete.predicate = NSPredicate(format: "todo = %@",predicate)

    do {
    let resultats = try context!.fetch(requete)
    for resultat in resultats {

    let todo = (resultat as AnyObject).value(forKey: "todo")
    let date = (resultat as AnyObject).value(forKey: "date")
    let fait = (resultat as AnyObject).value(forKey: "estFait")

    let todoDict = ["todo": todo, "date": date, "estFait": fait as! Bool] //as [String: Any]

    arr.append(todoDict as NSDictionary) // différence voir 8'35" session 69
    arrData.append(resultat as! NSManagedObject)

    }

    completion(arr as NSArray, arrData as NSArray)

    } catch {
    print("erreur requête")
    }
    }
  • LarmeLarme Membre
    mai 2017 modifié #29


    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... 




     


    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. 


     




    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 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.

  • DrakenDraken Membre
    mai 2017 modifié #31


     


    Des la leçon 73 Modifier Todo, dans le fichier TodoTableViewController, dans la fonction par exemple :


     


    override func viewDidAppear(_ animated: Bool) {


            fetchTodos("")  {(array, arrayData) in


                todos = array as? [NSDictionary]


                tableView.reloadData()


            }


        }


    j'avoue ne pas avoir tout compris mais je regarde dans ce sens


     


     




     


     


    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.



    func messageBienvenu() {
    // Création Label
    let label = UILabel()
    label.textAlignment = .center
    label.center = self.view.center
    self.view.addSubview(label)
    label.textColor = UIColor.red
    label.font = UIFont.boldSystemFont(ofSize: 40)
    label.text = "BIENVENU"
    label.sizeToFit()

    // Disparition progressive (3 secondes)
    UIView.animate(withDuration: 3.0,
    animations: { label.alpha = 0 },
    completion: { _ in label.removeFromSuperview() }
    )
    }


    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.



    animations: { label.alpha = 0 }

    Le bloc de completion contient le traitement à  exécuter à  la fin de l'animation.



    completion: { _ in label.removeFromSuperview() }

    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 :



    { (nom des variables) in
    instructions
    }

    La completion de l'animation devrais s'écrire :



    completion: { (indicateurBinaire) in
    label.removeFromSuperview()
    }


    Mais comme on se fiche généralement de savoir si l'animation s'est terminée correctement ou pas, on écrit :



    completion: { _ in label.removeFromSuperview() }

    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 :



    override func viewDidAppear(_ animated: Bool) {
    fetchTodos("") {(array, arrayData) in
    todos = array as? [NSDictionary]
    tableView.reloadData()
    }
    }

    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..


Connectez-vous ou Inscrivez-vous pour répondre.