Partage
  • Partager sur Facebook
  • Partager sur Twitter

MOOC Une application iPhone avec le modèle MVC

    31 octobre 2020 à 18:33:14

    Yes. Sélectionne le dans l’aborescence et appuie sur la touche supprimer, tout simplement
    • Partager sur Facebook
    • Partager sur Twitter
      1 novembre 2020 à 1:16:33

      Cool. Grace àn ton idée des contraintes, j'ai retrouvé les 2 éléments. A part quand j'ai modifié l'iPhone d'exécution en 8, je ne m'explique pas qu'ils aient glissé vers le bas.

      Merci, en tout cas ; j'ai appris de nouveaux trucs et vais pouvoir avancer

      • Partager sur Facebook
      • Partager sur Twitter
        1 novembre 2020 à 10:29:18

        Modifier le x et le y ce n’est pas mettre des contraintes. Y c’est la distance par rapport au haut de l’écran. Si tu utilises un iPhone plus grand, mécaniquement il aura l’air plus haut. En realité il est à la même distance du haut. 

        Les contraintes servent à ca : définir in certains nombres de regles pour que les elements aient l’air d’être à la même place, et ce, peu importe la taille d’écran.  

        en bas du storyboard à droite, t’as une série d’icônes. C’est ça qu’il faut utiliser pour définir les contraintes. L’équerre permet de les visualiser. 

        • Partager sur Facebook
        • Partager sur Twitter
          6 novembre 2020 à 9:53:46

          Bonjour
          En simulation, je ne vois pas l'effet "boing" lorsqu'on affiche la question suivante, dans showQuestionView. On est censé avoir une animation qui part de la vue questionView, standard mais avec une taille la rendant invisible et la faisant apparaitre avec un effet spring (oscillations) ; mais je ne vois pas cet effet
          //
          //  ViewController.swift
          //  OpenQuizz
          //
          //  Created by Claudio on 06/10/2020.
          //
          
          import UIKit
          
          class ViewController: UIViewController {
          
              override func viewDidLoad() {
                  super.viewDidLoad()
                  let name = Notification.Name(rawValue: "QuestionsLoaded")
                  NotificationCenter.default.addObserver(
                      self, selector: #selector(questionsLoaded),
                      name: name, object: nil)
                  startNewGame() // On lance une partie tout de suite
                  let panGestureRecognizer = UIKit.UIPanGestureRecognizer(target: self, action: #selector(dragQuestionView(_:)))
                  questionView.addGestureRecognizer(panGestureRecognizer)
                  
              }
          
              @objc func questionsLoaded() {
                  activityIndicator.isHidden = true
                  newGameButton.isHidden = false
                  questionView.title = game.currentQuestion.title
              }
              
              @IBOutlet weak var newGameButton: UIButton!
              @IBOutlet weak var activityIndicator: UIActivityIndicatorView!
              @IBOutlet weak var scoreLabel: UILabel!
              @IBOutlet weak var questionView: QuestionView!
              var game = Game()
              
              @IBAction func didTapNewGameButton() {
                  startNewGame()
              }
              
              private func startNewGame() {
                  activityIndicator.isHidden = false
                  newGameButton.isHidden = true
          
                  questionView.title = "Loading..."
                  questionView.style = .standard
          
                  scoreLabel.text = "0 / 10"
          
                  game.refresh()
              }
              
              @IBAction func UIPanGestureRecognizer(_ sender: UIPanGestureRecognizer) {
              }
                  
              @objc func dragQuestionView(_ sender: UIPanGestureRecognizer) {
                  if game.state == .ongoing {
                      switch sender.state {
                      case .began, .changed:
                          transformQuestionViewWith(gesture: sender)
                      case .ended, .cancelled:
                          answerQuestion()
                      default:
                          break
                      }
                  }
              }
          
              private func transformQuestionViewWith(gesture: UIPanGestureRecognizer) {
                  let translation = gesture.translation(in: questionView)
          
                  let translationTransform = CGAffineTransform(translationX: translation.x, y: translation.y)
          
                  let translationPercent = translation.x/(UIScreen.main.bounds.width / 2)
                  let rotationAngle = (CGFloat.pi / 3) * translationPercent
                  let rotationTransform = CGAffineTransform(rotationAngle: rotationAngle)
          
                  let transform = translationTransform.concatenating(rotationTransform)
                  questionView.transform = transform
          
                  if translation.x > 0 {
                      questionView.style = .correct
                  } else {
                      questionView.style = .incorrect
                  }
              }
              
              private func answerQuestion() {
                  switch questionView.style {
                  case .correct:
                      game.answerCurrentQuestion(with: true)
                  case .incorrect:
                      game.answerCurrentQuestion(with: false)
                   case .standard:
                      break
                  }
          
                  scoreLabel.text = "\(game.score) / 10"
          
                  let screenWidth = UIScreen.main.bounds.width
          
                  var translationTransform: CGAffineTransform
                  if questionView.style == .correct {
                      translationTransform = CGAffineTransform(translationX: screenWidth, y: 0)
                  } else {
                      translationTransform = CGAffineTransform(translationX: -screenWidth, y: 0)
                  }
          
                  UIView.animate(withDuration: 0.3, animations: {
                      self.questionView.transform = translationTransform
                  }, completion: nil)
          
                  UIView.animate(withDuration: 0.3, animations: {
                      self.questionView.transform = translationTransform
                  }, completion: { (success) in
                      if success {
                          self.showQuestionView()
                      }
                  })
          
                  questionView.transform = .identity
                  questionView.style = .standard
          
                  switch game.state {
                  case .ongoing:
                      questionView.title = game.currentQuestion.title
                  case .over:
                      questionView.title = "Game Over"
                  }
              }
              
              private func showQuestionView() {
                  questionView.transform = .identity
                  questionView.transform = CGAffineTransform(scaleX: 0.01, y: 0.01)
          
                  questionView.style = .standard
          
                  switch game.state {
                  case .ongoing:
                      questionView.title = game.currentQuestion.title
                  case .over:
                      questionView.title = "Game Over"
                  }
          
                  UIView.animate(withDuration: 0.4, delay: 0.0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.5, options: [], animations: {
                      self.questionView.transform = .identity
                  }, completion:nil)
              }
              
          }
          
          • Partager sur Facebook
          • Partager sur Twitter
            9 novembre 2020 à 22:59:28 - Message modéré pour le motif suivant : Toute forme de publicité est interdite


              16 novembre 2020 à 9:55:11

              Hello
              Question complémentaire à celle que j'ai posé ci-dessus avec ViewControler.swift:

              Il y a certainement quelquechose que je n'ai pas compris à propos du modèle MVC, car, en cherchant à implémenter une petite modification de mon cru, je me demande pourquoi, dans ViewControler.swift, on trouve plein de code qui gère directement la vue. Je viens de relire tout le cours, mais pas avec cette idée en tête, et ça ne m'a pas frappé. Je vais donc recommencer, plus focalisé sur cet aspect, en attendant que quelqu'un m'éclaire

              Merci d'avance

              A force de relire le code, je crois que j'ai compris: tout le code de ViewControler.swift qui touche des objets de la vue le fait à travers les outlets définis dans le Controler. 

              -
              Edité par ClaudioLooping 16 novembre 2020 à 9:59:13

              • Partager sur Facebook
              • Partager sur Twitter
                16 novembre 2020 à 12:14:37

                MVC ca veut dire “Massive View Controller” c’est un pattern de merde dans l’univers Apple by design. C’est super facile de finir avec de la logique métier et de la logique de présentation dans le ViewController. Finalement c’est un peu des classes foure tout mal découpé  (comme dans le cours)

                Si tu veux un truc propre regarde plutôt MVP / VIPER 

                EDIT : Tu peux également faire du MVVM avec RxSwift mais je suis pas fan de cette approche en UIKit. C’est beaucoup plus intéressant si tu te mets à faire du SwiftUI (Sans RxSwift ofc ! et à l’inverse MVP / VIPER deviennent des dinosaures)

                -
                Edité par Geda 16 novembre 2020 à 12:19:43

                • Partager sur Facebook
                • Partager sur Twitter
                  16 novembre 2020 à 14:14:28

                  Merci Geda

                  Etant donné que je débute dans cet univers, pour l'instant j'applique la formation, mais je note d'aller faire un tour du côté de MVP/VIPER
                  Par hasard, par rapport à ma précédente question, tu aurais une idée de pourquoi je ne vois pas l'effet boing? 

                  -
                  Edité par ClaudioLooping 16 novembre 2020 à 14:15:09

                  • Partager sur Facebook
                  • Partager sur Twitter
                    17 novembre 2020 à 8:39:32

                    Ta question je l’ai pas vraiment regardé. Y’a tout sur une ligne, faut scroller pour lire, c’est un peu chiant. Dans le Code à proprement parler y’a 3 private func qui font des transform. Je ne sais pas de laquelle tu veux parler quand tu parles d’effet boing. Si je voulais lancer un truc au pif je pointerai du doigt la ligne 120. Tu lances 2 animate qui ont l’air de faire la même chose et direct après un identity qui va un peu cancel les animate. Mais c’est vraiment au pif

                    • Partager sur Facebook
                    • Partager sur Twitter
                      17 novembre 2020 à 19:57:51

                      C'est l'animate de la ligne 144

                      Si j'applique les bonnes méthodes aux bons objets ça va mieux :-)

                      -
                      Edité par ClaudioLooping 22 novembre 2020 à 16:59:27

                      • Partager sur Facebook
                      • Partager sur Twitter
                        29 août 2021 à 12:21:08

                        disregard

                        -
                        Edité par ThomasDETRAZ 30 août 2021 à 11:53:49

                        • Partager sur Facebook
                        • Partager sur Twitter
                          1 septembre 2021 à 10:42:38

                          Bonjour à tous !

                          Je sollicite votre aide car je rencontre un problème de compréhension au niveau du chapitre "Télécharger les questions" du cours iPhone MVC.

                          En effet, je suis un peu perdu sur plusieurs aspects concernant l'exercice 2 (Utiliser les types fonctions).

                          Lien de l'exercice : https://openclassrooms.com/fr/courses/4504796-developpez-une-application-iphone-avec-le-modele-mvc/4571292-telechargez-les-questions#/id/r-4571272

                          1) Je ne comprends pas le type de la fonction obtenir division : (Int) -> (Int) -> (Int)

                          • Update : Le premier Int est le paramètre et les deux suivant constituent eux deux le type de retour ?

                          2) Voici la boucle for de la correction :

                          for nombre in tableau {
                              let division = obtenirDivision(x: nombre)
                              division(nombre)
                              somme += division(nombre)
                          }
                          • let division = obtenirDivision(x: nombre), normalement le résultat de la fonction donne un Int mais quand je print "division", j'ai (Function) qui s'affiche.
                          • "division(nombre)" : je ne comprends pas ce que cela fait, en fait j'ai l'impression qu'on passe par une constante pour utiliser la fonction obtenirDivision, j'ai peut-être mal saisi.
                          • "somme += division(nombre)" : pourquoi ne pas simplement mettre "somme += division" ?

                          Merci beaucoup pour votre attention !

                          -
                          Edité par Mickaël Horn 1 septembre 2021 à 10:44:02

                          • Partager sur Facebook
                          • Partager sur Twitter
                            2 septembre 2021 à 18:15:05

                            Salut,

                            1) Effectivement le premier Int c'est le paramètre. Pour les deux suivants, le placement des parenthèses n'aide pas à la compréhension. On pourrait aussi écrire (Int) -> Int. Les deuxièmes parenthèses ne servant à rien. Ou ((Int) -> Int) pour bien encapsuler le type de retour. Il s'agit d'une closure qui prend en paramètre un Int et qui retourne un Int.

                            2) Comme dit plus haut obtenirDivision retourne une closure et non un Int. Donc effectivement ça t'affiche (Function) :) C'est comme si tu faisais print(diviserNombrePairParDeux)

                            -
                            Edité par Geda 2 septembre 2021 à 18:19:49

                            • Partager sur Facebook
                            • Partager sur Twitter
                              3 septembre 2021 à 11:05:37

                              Bonjour et merci pour la réponse !

                              Je suis un peu perturbé avec cette notion de "Type Fonction" parce que normalement, quand tu utilise une fonction, la donnée que tu récupère en retour est directement exploitable et la ce n'est pas le cas.

                              Exemple : (Une fonction qui ajoute 2 à notre Int en paramètre)

                              func AjouteDeux(x: Int) -> Int {
                                  return x + 2
                              }

                              Si je fais un print(ajouteDeux(x: 5)), ça va m'afficher 7.

                              Mais dans l'exemple de obtenirDivision, quand on appelle la fonction, c'est comme si elle n'allait pas "au bout" du chemin car en soit, elle est censée retourner un Int à la fin.

                              On passe par un intermédiaire qui est la constante "division" dans laquelle on met la fonction.

                              Par la suite, on utilise "division" comme si c'était notre fonction avec des parenthèses et le paramètre.

                              J'espère que c'est assez clair, n'hésitez pas à me solliciter si jamais ce n'est pas le cas, j'ai vraiment envie de bien comprendre :)

                              Merci à tous !

                              -
                              Edité par Mickaël Horn 3 septembre 2021 à 11:06:46

                              • Partager sur Facebook
                              • Partager sur Twitter
                                4 septembre 2021 à 20:15:05

                                > quand tu utilise une fonction, la donnée que tu récupère en retour est directement exploitable et la ce n'est pas le cas.

                                Et bien si, c'est le cas. Là tu récupères une closure et tu peux l'utiliser tel quel :) C'est un type comme un autre. Peut-être un type un peu différent mais ça reste un type.

                                > Mais dans l'exemple de obtenirDivision, quand on appelle la fonction, c'est comme si elle n'allait pas "au bout" du chemin car en soit, elle est censée retourner un Int à la fin.

                                Non, elle est censée retourner une fonction. Peut être que obtenirFonctionDivision est un meilleur nom.

                                > On passe par un intermédiaire qui est la constante "division" dans laquelle on met la fonction.

                                Tu pourrais t'en passer et faire obtenirDivision(nombre: 3)(3)

                                >Par la suite, on utilise "division" comme si c'était notre fonction avec des parenthèses et le paramètre.

                                C'est bel et bien une fonction :) Soit diviserNombrePairParDeux soit diviserNombreImpairParDeux

                                Ceci étant dit, en réalité tu ne feras jamais ça car effectivement, c'est contre-intuitif, ça rajoute de la complexité pour rien et on perd en lisibilité en plus d'être source de bug (tu pourrais très bien faire obtenirDivision(x: 3)(4) ce qui te ferait faire une division impaire sur un nombre pair). Dans la réalité, à la limite, tu aurais le if qui appelle une des deux fonctions et qui retourne directement un Int. Dans la réalité, tu n'aurais pas de division qui retourne un Int car n'a aucun sens. A la limite pour obtenir un nombre entier il existe des méthodes comme round ou autre. Tout ça pour dire, qu'on est pas dans la réalité. Il ne faut pas prendre ce bout de code pour autre chose que ce qu'il est : un exemple. Ce n'est pas quelque chose qu'il faut faire, c'est juste pour montrer qu'une fonction n'est rien d'autre qu'une closure et qu'il y a un type pour représenter ça.

                                Un autre exemple serait :

                                func getConstructorOf(element: Any) -> () -> Any {
                                    if element is String {
                                        return String.init
                                    } else if element is Int {
                                        return Int.init
                                    }
                                    
                                    return Bool.init
                                }
                                
                                func createNewInstanceOf(element: Any) -> Any {
                                    let constructor = getConstructorOf(element: element)
                                    return constructor()
                                }
                                
                                
                                print(createNewInstanceOf(element: true)) // false
                                

                                Ça reste néanmoins un usage très marginal. Les closures sont plus souvent utilisées en paramètre d'une méthode :

                                func reduce(list: [Int], operation: (Int, Int) -> Int) -> Int {
                                    var current = list[0]
                                    for value in list[1...] {
                                        current = operation(current, value)
                                    }
                                    
                                    return current
                                }
                                
                                
                                let list = [1, 2, 3]
                                let sum = reduce(list: list) { total, next in
                                    total + next
                                }
                                
                                print(sum) // 6
                                

                                PS : Désolé pour les caractères spéciaux, je suis en markdown et les flèches de retour sont assez mal interprétées...

                                -
                                Edité par Geda 4 septembre 2021 à 20:19:01

                                • Partager sur Facebook
                                • Partager sur Twitter
                                  6 septembre 2021 à 10:34:16

                                  Je te remercie pour tes explications c'est clair maintenant, j'ai encore beaucoup de chemin à parcourir :D
                                  • Partager sur Facebook
                                  • Partager sur Twitter

                                  MOOC Une application iPhone avec le modèle MVC

                                  × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                  × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                  • Editeur
                                  • Markdown