gérer les date avec UIDatePicker

bonjour a tous,


 


je suis encore dans le brouillard avec les syntaxes swift.


je n arrive pas a récupérer la valeur du datepicker ni a lui en passer une, pour afficher directement une date voulue.


 


j imagine que cela vous parrait basic mais la doc ne semble pas claire du tout. 


 


merci de votre aide


Mots clés:
«1

Réponses

  • un passage ici UIDatePicker - UIKit | Apple Developer Documentation peut-être pour commencer, que tu peux compléter avec GG


  • merci pour le lien, mais justement il ne m a pas suffit pour y parvenir.


    c est quoi GG?



  • merci pour le lien, mais justement il ne m a pas suffit pour y parvenir.


    c est quoi GG?




     GG c'est ça


     


    ::)

  • cdsoftcdsoft Membre
    décembre 2017 modifié #5

    voici ce que je fais mais cela ne fonctionne pas, et ça plante:



    import UIKit
    class secondViewController: UIViewController {

    @IBOutlet weak var labeltwo: UILabel!


    @IBOutlet weak var datetwo: UIDatePicker!


    var dateValue: DateFormatter = DateFormatter()



    override func viewDidLoad() {
    super.viewDidLoad()
    datetwo.datePickerMode = .date
    dateValue.dateFormat = "dd/mm/yyyy"


    labeltwo.text = dateValue.string(from: datetwo.date)

    datetwo.addTarget(self, action: Selector("actiodate"), for: .valueChanged)


    func actiodate(_ sender: UIDatePicker) {
    labeltwo.text = dateValue.string(from: sender.date)
    }
    }
    }

  • Joanna CarterJoanna Carter Membre, Modérateur
    ça plante comment ? Avec quelle erreur ?
  • voici ce que j ai:


    2017-12-25 00:29:17.590547+0200 projet2[24708:2581131] -[projet2.secondViewController actiodate:]: unrecognized selector sent to instance 0x7fc4dad1a8b0


    2017-12-25 00:29:17.610866+0200 projet2[24708:2581131] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[projet2.secondViewController actiodate:]: unrecognized selector sent to instance 0x7fc4dad1a8b0'


    *** First throw call stack:


    (


    0   CoreFoundation                      0x0000000106b7d1ab __exceptionPreprocess + 171


    1   libobjc.A.dylib                     0x0000000102db9f41 objc_exception_throw + 48


    2   CoreFoundation                      0x0000000106bfda34 -[NSObject(NSObject) doesNotRecognizeSelector:] + 132


    3   UIKit                               0x0000000103c4f761 -[UIResponder doesNotRecognizeSelector:] + 295


    4   CoreFoundation                      0x0000000106b000a8 ___forwarding___ + 1432


    5   CoreFoundation                      0x0000000106affa88 _CF_forwarding_prep_0 + 120


    6   UIKit                               0x0000000103a21275 -[UIApplication sendAction:to:from:forEvent:] + 83


    7   UIKit                               0x0000000103b9e4a2 -[UIControl sendAction:to:forEvent:] + 67


    8   UIKit                               0x0000000103b9e7bf -[UIControl _sendActionsForEvents:withEvent:] + 450


    9   UIKit                               0x0000000104540edc -[_UIDatePickerView pickerView:didSelectRow:inComponent:] + 568


    10  UIKit                               0x0000000103a03cc5 -[UIPickerView _sendSelectionChangedForComponent:notify:] + 104


    11  UIKit                               0x0000000103a03f11 -[UIPickerView _sendSelectionChangedFromTable:notify:] + 366


    12  UIKit                               0x000000010430fa88 -[UIPickerTableView _scrollingFinished] + 187


    13  UIKit                               0x000000010430fc78 -[UIPickerTableView scrollViewDidEndDecelerating:] + 30


    14  UIKit                               0x0000000103b209c8 -[UIScrollView(UIScrollViewInternal) _scrollViewDidEndDeceleratingForDelegate] + 179


    15  UIKit                               0x0000000103b1a827 -[UIScrollView(UIScrollViewInternal) _stopScrollDecelerationNotify:] + 321


    16  UIKit                               0x0000000103b1aa7b -[UIScrollView(UIScrollViewInternal) _stopScrollingNotify:pin:tramplingDragFlags:] + 502


    17  UIKit                               0x0000000103b10c99 -[UIScrollView _smoothScrollWithUpdateTime:] + 3134


    18  UIKit                               0x0000000103b10ecf -[UIScrollView _smoothScrollDisplayLink:] + 354


    19  QuartzCore                          0x0000000109fef818 _ZN2CA7Display11DisplayLink14dispatch_itemsEyyy + 684


    20  QuartzCore                          0x000000010a12b970 _ZL22display_timer_callbackP12__CFMachPortPvlS1_ + 248


    21  CoreFoundation                      0x0000000106b0c9c9 __CFMachPortPerform + 169


    22  CoreFoundation                      0x0000000106b0c909 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 41


    23  CoreFoundation                      0x0000000106b0c871 __CFRunLoopDoSource1 + 465


    24  CoreFoundation                      0x0000000106b04654 __CFRunLoopRun + 2596


    25  CoreFoundation                      0x0000000106b039b9 CFRunLoopRunSpecific + 409


    26  GraphicsServices                    0x000000010929a9c6 GSEventRunModal + 62


    27  UIKit                               0x0000000103a1f5e8 UIApplicationMain + 159


    28  projet2                             0x00000001024972f7 main + 55


    29  libdyld.dylib                       0x0000000107c59d81 start + 1


    )


    libc++abi.dylib: terminating with uncaught exception of type NSException


    (lldb)


  • Joanna CarterJoanna Carter Membre, Modérateur
    décembre 2017 modifié #8
    1. Tu as mis la méthode actiodate dans la méthode viewDidLoad.


    2. Tu n'as pas marqué la méthode actiodate comme @objc


    3. Tu n'as pas utilisé la bonne syntaxe pour les selectors.


    override func viewDidLoad()
    {
    super.viewDidLoad()

    datePicker.addTarget(self, action: #selector(actiodate(_:)), for: .valueChanged)
    }

    @objc func actiodate(_ sender: UIDatePicker)
    {
    ...
    }

    Ou, tu aurais pu connecté l'action vars la méthode en glissant entre le DatePicker et le code.
  • bonjour et merci Joanna,


     


    je vais essayer pour la syntaxe.


    mais je voudrais bien comprendre comment fait-on la difference entre ces differentes syntaxes qui ne sont pas compilees en erreur avant l execution.


    existe t il une documentation qui regroupe de maniere precise les controles avec leur mise oeuvre programmee.


    un peu comme sous windev ou la doc est vraiment bien faite.(ces encore mon modele de reference puisque je viens de cet environnement de dev)


     


    et egalement, pourrais tu m expliquer ce que tu veux dire par :



     


     


    Ou, tu aurais pu connecté l'action vars la méthode en glissant entre le DatePicker et le code. 

     


    merci encore


  • Joanna CarterJoanna Carter Membre, Modérateur
    décembre 2017 modifié #10

    Tu n'as pas fait vraiment une erreur en utilisant le syntaxe Selector("nomDeMethode") parce que ça utilise l'init de la struct Selector.


     


    Mais, si tu utilises Swift 4, tu aurais dû eu un avertissement qui te dit "Use '#selector' instead of explicitly constructing a 'Selector'" ; du coup le code que j'ai écrit.


     


    Il faut lire les docs sous la rubrique "Selector Expressions" ici : https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Expressions.html#//apple_ref/doc/uid/TP40014097-CH32-ID383


     


    Les docs pour les controles sont bien comprehensives et se trouvent ici : https://developer.apple.com/documentation/uikit


     


    Comment connecter un Action à  ton code se trouve sous la rubrique "Define an Action to Perform" ici : https://developer.apple.com/library/content/referencelibrary/GettingStarted/DevelopiOSAppsSwift/ConnectTheUIToCode.html


  • merci a toi


  • DrakenDraken Membre
    décembre 2017 modifié #12

    Une chose à  savoir : les selectors sont des reliquats de l'Objective-C, le langage historique Apple. C'est pourquoi Xcode ajoute le symbole @objc devant ta fonction actiodate(). Swift a été conçu pour éviter autant que possible l'usage de code non vérifiable à  la compilation (une grande spécialité de l'Objective-C).


     


    Il est difficile de se passer complètement des Selectors, parce que la plupart des interactions composants graphiques/Code du framework UIKit les utilisent.


     


    En général on ne les définit pas dans le code. Il est plus facile de créer un @IBAction avec Xcode pour " connecter graphiquement" un événement utilisateur avec une fonction.



    import UIKit
    class secondViewController: UIViewController {

    @IBOutlet weak var labeltwo: UILabel!

    @IBOutlet weak var datetwo: UIDatePicker!

    var dateValue: DateFormatter = DateFormatter()

    override func viewDidLoad() {
    super.viewDidLoad()
    datetwo.datePickerMode = .date
    dateValue.dateFormat = "dd/mm/yyyy"

    labeltwo.text = dateValue.string(from: datetwo.date)
    }

    // Evenement action utilisateur (connection événement/code définie graphiquement avec Xcode)
    @IBAction func actiodate(_ sender: UIDatePicker) {
    labeltwo.text = dateValue.string(from: sender.date)
    }

    }

  • cdsoftcdsoft Membre
    décembre 2017 modifié #13

    ok


     


    merci beaucoup pour ces precisions


     


    j en profite encore vous demander s il est possible de faire l inverse en forcant l affichage d une date dans le datepicker


     


    exemple:


    le datepicker n affiche pas la date du jour mais se positionne sur une date particuliere, de maniere dynamique


  • Le datePicker a une propriété date que tu peux setter

  • @IBOutlet weak var dateTwo: UIDatePicker!

    override func viewDidLoad() {
    super.viewDidLoad()

    let dateCourante = Date()
    dateTwo.date = dateCourante
    }
  • Ou encore :



    @IBOutlet weak var dateTwo: UIDatePicker!

    override func viewDidLoad() {
    super.viewDidLoad()

    // Calcul de la date dans 3 jours (3*24 heures)
    let dateDansTroisJours = Date(timeIntervalSinceNow: 3*24*60*60)
    dateTwo.date = dateDansTroisJours
    }
  • Joanna CarterJoanna Carter Membre, Modérateur
    Bah non Draken !


    let today = Date()

    let tomorrow = Calendar.current.date(byAdding: .day, value: 1, to: today)
  • merci a tous



  • DrakenDraken Membre
    décembre 2017 modifié #19


    Bah non Draken !

     



    let today = Date()

    let tomorrow = Calendar.current.date(byAdding: .day, value: 1, to: today)



    Vraiment ?



    // Calcul de la date dans 3 jours (3*24 heures)
    let maintenant = Date()
    let dateDansTroisJours = Date(timeIntervalSinceNow: 3*24*60*60)
    let tomorrow = Calendar.current.date(byAdding: .day, value: 3, to: maintenant)

    print ("Maintenant : ", maintenant)
    print ("dans 3 jours : ", dateDansTroisJours)
    if let dateNounours = tomorrow {
    print ("version nounours : ", dateNounours)
    }

    a


     



     


    Maintenant               :  2017-12-25 16:12:49 +0000


    dans 3 jours     :  2017-12-28 16:12:49 +0000


    version nounours :  2017-12-28 16:12:49 +0000



  • cdsoftcdsoft Membre
    décembre 2017 modifié #20

    navré mais je reviens vers vous car j ai voulu tester vos code sur l événement datepicker et chez moi cela ne marche pas.


    la syntaxe :


    datetwo.addTarget(self, action: #selector(actiodate(_ :)), for: .valueChanged)


    me donne l erreur suivante :


    Use of local variable 'actiodate' before its declaration


     


    et quand je veux utiliser la création du @IBAction


    @IBAction func actiodate(_ sender: UIDatePicker) {


            labeltwo.textdateValue.string(from: sender.date)


            


        }


    je n ai pas de erreur mais mon programme plante comme avant des que je change la date du contrôle datepicker


     


    comme il s agit d un projet ou il y a tout et n importe quoi pour apprendre a manipuler swift je vous envoie tous le code de mon  secondcontrolerview , qui comporte surtout des lignes commentées.


    sachant que les reste du code avec les affichages des valeurs transmises fonctionnent. Le pb concerne le datepicker



    //
    // secondViewController.swift
    // projet2
    //
    // Created by Yaron Maman on 17/12/2017.
    // Copyright © 2017 Yaron Maman. All rights reserved.
    //

    import UIKit

    class secondViewController: UIViewController {

    @IBOutlet weak var labeltwo: UILabel!

    @IBOutlet weak var filedtwo: UITextField!

    @IBOutlet weak var seg: UISegmentedControl!

    @IBOutlet weak var datetwo: UIDatePicker!



    @IBAction func actiodate(_ sender: UIDatePicker) {
    labeltwo.text = dateValue.string(from: sender.date)

    }
    var dateValue: DateFormatter = DateFormatter()
    var text = ""
    var field = ""
    var f2 = ""
    var switchtwo = false
    var segvar = false
    // var date = DateFormatter()


    override func viewDidLoad() {
    super.viewDidLoad()



    datetwo.datePickerMode = .date
    dateValue.dateFormat = "dd/mm/yyyy"
    //datetwo = dateValue.value(forKey: "12/11/1987") as! UIDatePicker
    // datetwo.date = dateValue.date(from: "12/01/1980")!

    print ("totototot \(datetwo.date) ")
    // print(date.string(from: datetwo.date))

    labeltwo.text = text
    print(switchtwo)
    if switchtwo {
    f2 = field.uppercased()
    filedtwo.text = f2
    seg.setEnabled(true, forSegmentAt: 1)
    seg.selectedSegmentIndex = 1
    //filedtwo.text!.uppercased()
    }else{
    seg.setEnabled(true, forSegmentAt: 0)
    seg.selectedSegmentIndex = 0
    filedtwo.text = field
    }
    print(dateValue.string(from: datetwo.date))
    labeltwo.text = dateValue.string(from: datetwo.date)

    // Add an event to call onDidChangeDate function when value is changed.
    // datetwo.addTarget(self, action: Selector(("datePickerValueChanged:")), for: .valueChanged)
    // datetwo.addTarget(self, action: #selector(actiodate(_:)), for: .valueChanged)

    // Do any additional setup after loading the view.
    //@objc func actiodate(_ sender: UIDatePicker) {
    // labeltwo.text = dateValue.string(from: sender.date)
    // }


    }

    // func datePickerValueChanged(_ sender: UIDatePicker) {

    // labeltwo.text = dateValue.string(from: sender.date)
    // }

    override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
    }


    /*
    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    // Get the new view controller using segue.destinationViewController.
    // Pass the selected object to the new view controller.
    }
    */

    }


    merci


  • Je n'ai pas le temps de te répondre ce soir (je viens de boire ma coupe de champagne annuelle pour les fêtes, ce qui altère mes compétences éducatives). Je te fais un petit tuto demain, sur la manière de créer une IBAction avec Xcode. A mon avis, tu as juste recopié le code, sans réaliser la connexion graphique événement/fonction avec  Xcode.

  • Joanna CarterJoanna Carter Membre, Modérateur
    Encore une fois, tu as mis la méthode actiodate à  l'intérieur de la méthode viewDidLoad. Il faut la mettre en dehors.


  • Encore une fois, tu as mis la méthode actiodate à  l'intérieur de la méthode viewDidLoad. Il faut la mettre en dehors.




     


    Une méthode (je dirais locale) a l'intérieur d'une fonction c'est pas possible ?

  • Joanna CarterJoanna Carter Membre, Modérateur

    Si, les méthodes come ça est possible mais pas dans le cas d'une méthode que l'on veuille utiliser comme selector pour lier une Action.


     


    Regardes le code pour la connecter :



    datePicker.addTarget(self, action: #selector(actiodate(_:)), for: .valueChanged)

    La cible est "self" ; du coup, la méthode doit être membre de "self" ; sinon, le système Target/Action ne peut pas la trouver.




  • Une méthode (je dirais locale) a l'intérieur d'une fonction c'est pas possible ?




    Juste quand je lisais ces lignes chez moi il refusait la func interne ?

  • merci je vais reessayer


  • @cdsoft


     


    Petit exemple : J'ai écrit un mini-programme avec un storyboard ne contenant qu'une UIDatePicker.


     


    Etape 1 : J'ai défini un outlet, tu sais le faire puisque tu l'utilises déjà  dans ton programme


    Etape 2 : Création d'une IBAction, c'est presque similaire à  l'outlet. 


       - Je sélectionne l'UIDatePicker sur le Storyboard en pressant sur la touche " Ctrl " et je trace un lien vers le bas de la fenêtre de code.


     


     


  • Joanna CarterJoanna Carter Membre, Modérateur

    Et, en refaisant ton code, il faut l'écrire plus clair :



    class secondViewController: UIViewController {

    @IBOutlet weak var label: UILabel! // tu n'as qu'un

    @IBOutlet weak var textField: UITextField! // tu n'as qu'un et ce n'est pas un filed

    @IBOutlet weak var segmentedControl: UISegmentedControl! // n'utilises pas le abréviations

    @IBOutlet weak var datePicker: UIDatePicker! // la var n'est pas pour stocker une date

    @IBAction func handleDateChange(_ sender: UIDatePicker) // nommer les punchs pour dire qu'elles font
    {
    label.text = dateValue.string(from: sender.date)

    }

    var dateFormatter = DateFormatter() // la var n'est pas pour stocker une valeur, c'est un truc pour transformer les Dates en Strings

    var text = ""

    var field = ""

    var f2 = "" // Ce n'est pas nécessaire de la déclarer ici. Tu l'utilises comme let plus tard et tu peux la déclarer comme let sur place.

    Et il y a plus de fautes mais j'arrête maintenant


  • DrakenDraken Membre
    décembre 2017 modifié #29

    Xcode affiche alors une boite de dialogue pour connaà®tre le nom de la connection à  créer.


     


    - Il faut modifier le paramétre " Connection "  pour signifier que c'est une Action.


    - Lui donner un nom (actionDatePicker)


    - Lui donner un type (UIDatePicker)


    - Définir le type d'événement (Value Changed par défaut ce qui correspond à  ton besoin actuel).


    - Définir qu'il faut passer le Sender


     


    Et valider en cliquant sur le bouton Connect.


     


    EDIT : Grrr.. Nounours c'est pas bien de poster dans mon tuto ..


  • Xcode génère alors automatiquement une fonction pour gérer l'action :



    import UIKit

    class ViewController: UIViewController {

    @IBOutlet weak var datePicker: UIDatePicker!

    override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
    }

    @IBAction func actionDatePicker(_ sender: UIDatePicker) {
    }

    }

    Il ne reste plus qu'à  ajouter du code pour gérer l'action. Par exemple :



    @IBAction func actionDatePicker(_ sender: UIDatePicker) {
    let nouvelledate = sender.date
    print ("Nouvelle date : ", nouvelledate)
    }

    Et c'est tout ..

  • encore merci a vous tous pour vos partages clairs et rapides.


     


    je vais tester tout ca au plus vite en esperant vite me familiariser avec ce langage


    a+


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