date système avec une heure différente ?

Bonjour, 


 


Dans une appli, je veux récupérer la date système pour faire un calcul et quand je fais un NSLog il met une heure différente de l'heure affichée sur l'iphone ?


 


voici ma demande : 


NSDate *date = [NSDate date]; //Aujourd'hui


    //NSDateComponents *leGap = [[NSDateComponents alloc] init];


    //[leGap setHour:1];


    NSDate *nouvelleDate = [[NSCalendar currentCalendar]


                            dateByAddingComponents:leGap toDate:date options:0];


    NSLog(@Date système : %@", date);


    NSLog(@Nouvelle date : %@", nouvelleDate);


 


et dans le debug : 


 


2013-11-18 15:45:52.507 Easy[739:60b] heure : 03:45 PM


2013-11-18 15:46:04.416 Easy[739:60b] Date système : 2013-11-18 14:46:04 +0000


2013-11-18 15:46:04.423 Easy[739:60b] Nouvelle date : 2013-11-18 04:46:04 +0000


 


 


Quelqu'un aurait il une idée ??


normalement "heure" et "date système" devraient être les mêmes


 


J'ai pensé à  l'heure GMT Greenwich qui a une heure de différence avec la France, et si c'est ça est-ce qu'il y aura toujours une différence et ce suivant le lieu géographique ?


 


merci de votre réponse.


 


Jean-Baptiste


«1

Réponses

  • Sujet maintes fois abordés, par exemple ici


  • CéroceCéroce Membre, Modérateur
    novembre 2013 modifié #3

    J'ai pensé à  l'heure GMT Greenwich qui a une heure de différence avec la France,

    ça, ça dépend de la saison.
     

    et si c'est ça est-ce qu'il y aura toujours une différence et ce suivant le lieu géographique ?

    Non pas toujours, il n'y a pas de différence quand on se trouve dans le fuseau du méridien de Greenwich !

    Une NSDate est en quelque sorte absolue sur tout le globe. C'est à  l'affichage (en général avec un NSDateFormatter) que sont pris en compte le fuseau horaire et le calendrier, qui n'est pas forcément grégorien).
    Si tu veux faire des calculs, ce n'est pas sur les NSDateComponents qu'il faut travailler, mais sur NSDate.
  • AliGatorAliGator Membre, Modérateur
    3:45PM heure de Paris aujourd'hui et 2013-11-18 14:46:04 +0000 c'est la même heure, il n'y a aucun décalage c'est bien la bonne date, ça représente le même moment absolu, il n'y a donc aucun problème.
  • Ok je comprends l'absolue date dont tu parles Ceroce.


     


    Donc le NSdateComponent me donne l'heure de l'Iphone


    et NSDate me donne l'heure mondiale de Greenwich sans le décalage horaire.


     


    Dans l'appli que je travaille je me base sur l'heure qu'il est à  l'endroit où se trouve l'iphone et je propose à  l'utilisateur d'ajouter ou de retirer les heures de décalages où il va atterrir. cette nouvelle heure sera gardée en mémoire et sera actualisée avec l'heure de l'iphone (heure Iphone + decalage) 


    Est ce que ç'est une bonne solution de faire comme cela d'après vous ?


     


    Que me conseillez vous d'utiliser comme méthode pour ajouter les heures qui sont choisie avec un PickerView ?


     


    merci en tout cas de vos réponses super rapide.


     


     


    Jean-Baptiste 

  • AliGatorAliGator Membre, Modérateur

    Ok je comprends l'absolue date dont tu parles Ceroce.
     
    Donc le NSdateComponent me donne l'heure de l'Iphone
    et NSDate me donne l'heure mondiale de Greenwich sans le décalage horaire.

    Non je pense que tu n'as toujours pas bien assimilé les concepts.

    15h à  Greenweech c'est pareil que 14h à  Paris en hiver. C'est le même moment.
    [NSDate date] retourne le moment courant. C'est pas la "wallclock", c'est juste le moment courant.

    C'est seulement à  l'affichage que tu vois la différence. Une NSDate définit un moment, mais si ensuite tu la convertis sous forme de NSString (soit avec description soit avec un NSDateFormatter) elle va utiliser un format particulier, lié au réglage de fuseau horaire de l'iPhone. Mais quel que soit le fuseau horaire utilisé, c'est toujours la même date.


    Donc NSDate ne donne pas "l'heure mondiale de Greenwich sans décalage horaire", il donne "le moment présent". Un moment dans le temps. Si tu appelles qqun à  New York là  maintenant tout de suite, quel que soit le fuseau horaire dans lequel chacun de vous vous vous trouvez, ce sera le même moment dans le temps pour vous deux.

    Par contre si tu demandes de faire un NSLog(@%@, [NSDate date]), ce qui appelle la méthode description" sur l'objet NSDate pour le transformer en NSString, bah il faut bien qu'il affiche cette date avec un certain format. L'implémentation qu'Apple a choisi la méthode description de NSDate pour transformer cette NSDate en NSString à  des fins d'affichage dans la console, c'est d'afficher l'heure que ce moment représente tel que à  Greenwich. Mais ils auraient pu choisir autre chose, par exemple ils auraient pu choisir à  la place d'afficher le Timestamp UNIX que cette NSDate représente. Ou l'heure que cela représente à  Cupertino. Ca n'est qu'une représentation textuelle comme une autre. Quelle que soit la représentation textuelle (NSString) de cet objet NSDate, ça représente dans tous les cas le même moment dans le temps.

    NSDate ne contient aucune information de "fuseau horaire". Ca représente un moment, pas une heure ni un fuseau horaire. C'est comme la couleur "rouge", qui peut être représentée comme rgb(255,0,0) ou comme yuv(76,84,255) ou comme hsv(0,100,100), dans tous les cas c'est la même couleur.
  • CéroceCéroce Membre, Modérateur
    novembre 2013 modifié #7

    Dans l'appli que je travaille je me base sur l'heure qu'il est à  l'endroit où se trouve l'iphone et je propose à  l'utilisateur d'ajouter ou de retirer les heures de décalages où il va atterrir. cette nouvelle heure sera gardée en mémoire et sera actualisée avec l'heure de l'iphone (heure Iphone + decalage) 
    Est ce que ç'est une bonne solution de faire comme cela d'après vous ?

    Non, parce qu'il y a deux notions ici: le temps de vol, et le décalage horaire.

    Pour la durée du vol, il faut ajouter des minutes à  la NSDate. Par exemple, si l'heure de départ est 7:00 GMT et que le vol dure 1h30, l'avion atterrit à  8:30 GMT.
    L'heure de départ et l'heure d'arrivée sont deux moments différents, donc deux NSDates différentes.

    Pour le décalage horaire, c'est à  l'affichage qu'il faut le gérer. Si le lieu de départ est dans le fuseau GMT+1, et le lieu d'arrivée dans le fuseau GMT+2, alors l'avion décolle à  8:00 heure locale (7:00+1) et atterrit à  10h30 heure locale (8:30+2).
    NSDateFormatter possède une méthode setTimeZone:. Je ne l'ai jamais utilisé, mais je pense que c'est la bonne méthode.
  • Very good Ceroce ! 


     


    merci d'avoir pris le temps de m'expliquer ! j'ai noté (dixit Kubernan) qu'on pose beaucoup cette question mais quand j'ai essayé de trouver des infos sur le forum avant je n'ai pas su demander avec les mots corrects cas je n'ai rien trouver. Peut-être une appli à  développer pour le forum : " poser votre question de néophyte, on va se débrouiller..." ! 


     


    merci en tout cas.


     


    J'ai bien compris le concept et effectivement je vais me pencher sur setTimeZone.


     


    en fait, dans l'appli, je demande à  l'utilisateur de mettre l'heure actuelle du pays où il va atterrir pour que l'appli se base sur cette heure, qu'un enchainement spécifique de viewController apparaisse et aussi que l'appli puisse faire une alarme toutes les 2 heures si besoin.


    Je ne pense pas avoir besoin du temps de vol. Je ne peux pas non plus utiliser la solution de localisation géographique de l'Iphone car elle est normalement déconnectée pendant le voyage en avion et c'est pendant ce moment que la personne utilisera l'application.


    Voilà  pourquoi je demande à  l'utilisateur d'entrer l'heure actuelle du pays de destination et ensuite je dois me débrouiller pour faire tourner l'horloge de l'appli.


     


    Une question encore, est ce que l'horloge tournera si l'appli est éteinte ? comment gérer une alarme si l'appli est éteinte ?


    Est ce qu'une appli est vraiment éteinte quand elle disparait de l'écran ? car si je fais double-clique sur le bouton central de l'iphone la liste des applis ouvertes apparait.


     


    merci 


     


     


    "message perso pour Ceroce" Je trouve cette syntaxe bizarre : "On n'est nul part plus à  l'aise que chez-soi pour prendre des photos. Ne perdez plus votre temps dans les déplacements."


    je pensais à  la double négation, est ce que " on est nul part plus à  l'aise ...." serait peut-être plus vendeur et moins négatif ? qu'en penses tu ?

  • CéroceCéroce Membre, Modérateur
    novembre 2013 modifié #9

    poser votre question de néophyte, on va se débrouiller..." !

    C'est en nous disant ce que tu souhaitais faire exactement que nous avons pu t'aider.
    Tu comprends, là  il y avait deux notions qui s'embrouillaient dans ta tête, mais nous n'en voyions qu'une seule. D'ailleurs, ce que tu cherches à  faire n'est pas très courant.
     

    en fait, dans l'appli, je demande à  l'utilisateur de mettre l'heure actuelle du pays où il va atterrir pour que l'appli se base sur cette heure, qu'un enchainement spécifique de viewController apparaisse et aussi que l'appli puisse faire une alarme toutes les 2 heures si besoin.

    Là , par exemple, je n'arrive plus à  te suivre. Déjà , je trouve curieux de demander à  l'utilisateur l'heure dans un autre fuseau, parce que ce n'est pas si simple pour lui.
    Si tu veux qu'une alarme sonne dans deux heures, alors ce sera 2 heures plus tard, peu importe le fuseau.
     

    Une question encore, est ce que l'horloge tournera si l'appli est éteinte ?

    Ton appli n'a pas besoin de compter le temps: il faut juste afficher la bonne heure quand l'appli est au premier plan. Raffraichis le dessin de l'horloge en utilisant un NSTimer et base-toi sur l'heure courante obtenue par +[NSDate date].
     

    comment gérer une alarme si l'appli est éteinte ?

    Local Notifications.
     

    Est ce qu'une appli est vraiment éteinte quand elle disparait de l'écran ? car si je fais double-clique sur le bouton central de l'iphone la liste des applis ouvertes apparait.

    Son processus est interrompu, mais iOS évite de le "tuer", autrement il devrait recréer le processus à  chaque fois qu'on active l'appli, ce qui fait attendre l'utilisateur. iOS conserve si possible le processus en RAM et/ou dans un cache sur la mémoire flash. C'est vraiment quand le cache est plein qu'il commence à  tuer les processus.
    Sous iOS 7, il y a quelques nouveautés pour faire des traitements en tâche de fond, sans trop tirer sur la batterie.
     

    "message perso pour Ceroce"

    Utilise la messagerie privée pour ne pas dévier du sujet.
  • AliGatorAliGator Membre, Modérateur
    novembre 2013 modifié #10
    Lecture O-bli-ga-toire

    (Entre autres ça commence dès la première page par indiquer que "Date objects allow you to store absolute points in time which are meaningful across locales, calendars and timezones." donc rejoins ce que l'on t'expliquais depuis le début de ce thread ;))
  • Oui ! je l'avais trouvé et je suis en train de l'éplucher !


     


    merci AliGator


  • bonjour, 


     


    Pour être plus clair, cette appli va servir lorsque l'utilisateur voyagera dans un avion et donc c'est pour cela que je lui demande d'entrer   le nombre d'heures de décalages avec son heure de départ. Je ne lui demande pas quelle est la durée de son trajet.


    Donc dans un premier temps l'application prend comme référence l'heure de l'Iphone et ensuite après modification de l'utilisateur, on aura l'heure dans le pays de destination. C'est comme si il mettait sa montre à  l'heure du pays de destination alors qu'il est encore dans l'avion.


    ex : il part à  22:00 de Paris et il mets sa montre à  16:00 puisqu'il va à  New York (-6:00 à  partir de la France). 


     


    je voulais vous soumettre mon code car je ne connais pas la méthode pour ajouter une variable dans NSTimeInterval.


     


    NSDate *date =[[NSDate alloc] init];


        NSTimeInterval decallaHoraire = 1 * 60 * 60;


        NSDate *modifTemps;


        modifTemps = [date dateByAddingTimeInterval:decallaHoraire];


        


        NSString *dateChoisie = [dateFormatter stringFromDate:modifTemps];


     


        NSLog(@date = %@", date);


        NSLog(@dateChoisie = %@", dateChoisie);


        NSLog(@modifTemps = %@", modifTemps);


     


    2013-11-22 20:06:10.951 Easy[1925:60b] date = 2013-11-22 19:06:10 +0000


    2013-11-22 20:06:10.956 Easy[1925:60b] dateChoisie = 21:06 PM


    2013-11-22 20:06:10.960 Easy[1925:60b] modifTemps = 2013-11-22 20:06:10 +0000


     


     


    J'aimerai que le "1" de decallHoraire soit une variable qui dépends de la réponse d'un PickerView qui a des nombre entiers.


    le PickerView fonctionne mais je ne sais pas comment transférer la donnée ?


     


    On m'a déconseillé d'utiliser NSDateComponents 


     


    Merci de votre aide

  • AliGatorAliGator Membre, Modérateur
    Je ne sais pas qui t'a déconseillé d'utiliser NSDateComponents, mais c'est un conseil bizarre... quand c'est pour ajouter des durée, c'est au contraire la classe idéale pour manipuler des composantes de dates individuelles indépendantes, et d'être sûr d'être indépendant de choses comme le passage de l'heure d'été à  l'heure d'hiver.

    Cependant, dans ton cas, tu prends encore le problème à  l'envers... j'ai l'impression que tu n'as toujours pas compris qu'une NSDate représente un moment dans le temps, indépendant du fuseau horaire. Un moment n'est pas une heure, c'est un instant donné. Si tu appelles au téléphone ton pote qui vis sur la côte Pacifique aux US, il ne sera pas la même heure chez toi et chez lui, mais ce coup de fil se passera au même moment pour vous deux.

    Donc pour ton cas, il ne faut pas du tout ajouter de durée à  ta NSDate (ce que tu pourrais faire avec NSDateComponents le cas échéant), mais changer le fuseau horaire de la NSDate. On n'ajoute pas d'heures à  un temps absolu tel une NSDate quand on parle de décalage horaire. On change juste de timezone.

        NSDateFormatter* df = [NSDateFormatter new];
    df.dateStyle = NSDateFormatterShortStyle;
    df.timeStyle = NSDateFormatterMediumStyle;

    df.timeZone = [NSTimeZone localTimeZone]; // Le fuseau horaire réglé dans l'iPhone ("Europe/Paris" sans doute pour toi)
    NSString* localTime = [df stringFromDate:now]; // L'heure correspondant à  cet instant absolu dans le fuseau horaire local
    NSLog(@Heure locale : %@", localTime);

    df.timeZone = [NSTimeZone timeZoneWithName:@US/Pacific]; // Pacific Time (PST), comme à  Cupertino
    NSString* cupertinoTime = [df stringFromDate:now]; // L'heure correspondant à  cet exact même instant absolu mais dans le fuseau horaire PST (-08:00)
    NSLog(@Heure à  cupertino : %@", cupertinoTime);

    // Heure locale : 11/22/13, 8:46:08 PM
    // Heure à  cupertino : 11/22/13, 11:46:08 AM
    Là  je me base sur la même NSDate que j'ai appelé "now" et qui représente l'instant courant, et j'ai exprimé cet instant courant sous la forme d'une heure dans le fuseau horaire local, et d'une heure dans le fuseau horaire PST (-08:00) correspondant à  la côte pacifique US. C'est le même instant, tu ne voyages pas dans le temps, tu ne parles pas de 2 instants distincts (genre l'un à  un instant T et l'autre 2h plus tard) mais bien d'un même instant, exprimé dans 2 timezones différentes.
  • AliGatorAliGator Membre, Modérateur
    novembre 2013 modifié #14
    Tu peux même aller plus loin, et mixer les 2 concepts :
    1) Demander l'heure et le fuseau horaire de départ. Ca va nous permettre de calculer une NSDate D représentant un moment abstrait indépendant du fuseau horaire
    2) Demander la durée T du vol. On va ajouter cette durée T au moment D, pour représenter l'instant qui se trouve dans le futur, T minutes après l'instant D
    3) Demander le fuseau horaire d'arrivée. Ca va nous permettre d'afficher cet instant D+T (= instant représentant l'arrivée de ton vol à  destination) sous forme d'une heure dans le fuseau horaire d'arrivée.
     
        // Données entrées par l'utilisateur : heure de départ, fuseau horaire utilisé pour les heures de départ et d'arrivée, durée du vol
    NSString* departureTime = @27/10/2013 01:15:00;
    NSLocale* userLocale = [NSLocale localeWithLocaleIdentifier:@fr_FR]; // L'utilisateur a écrit la date en utilisant le format français JJ/MM/AAAA
    NSTimeZone* departureTimeZone = [NSTimeZone timeZoneWithName:@Europe/Paris]; // Quel est le fuseau horaire de départ utilisé pour exprimer l'heure de départ
    int flightDurationInMinutes = 150; // Durée du vol = 2h30
    NSTimeZone* arrivalTimeZone = [NSTimeZone timeZoneWithAbbreviation:@PST]; // Dans quel fuseau horaire exprimer l'heure d'arrivée

    // On prépare un DateFormatter pour convertir les chaà®nes (jour+heure) en NSDate (moment dans le temps) et vice-versa
    NSDateFormatter* df = [NSDateFormatter new];
    df.dateStyle = NSDateFormatterShortStyle;
    df.timeStyle = NSDateFormatterMediumStyle;
    df.locale = userLocale;

    // On convertit la date & heure de départ, exprimée sous forme de texte dans le fuseau horaire donné, en un instant (abstrait de toute timezone)
    df.timeZone = departureTimeZone;
    NSDate* departureMoment = [df dateFromString:departureTime];
    NSLog(@Vous partez de Paris le %@ heure locale de Paris", [df stringFromDate:departureMoment]);

    // On calcule le "moment" correspondant à  l'arrivée, soit 2h30 plus tard après le départ
    NSDate* arrivalMoment = [departureMoment dateByAddingTimeInterval:flightDurationInMinutes*60]; // On pourrait utiliser NSDateComponents à  la limite
    NSLog(@Quand vous arriverez à  Cupertino %d minutes plus tard, il sera %@ à  Paris...", flightDurationInMinutes, [df stringFromDate:arrivalMoment]);

    df.timeZone = arrivalTimeZone;
    NSLog(@"... soit %@ heure locale de Cupertino", [df stringFromDate:arrivalMoment]);
    Ce qui donne quand on exécute :

    Vous partez de Paris le 27/10/2013 01:15:00 heure locale de Paris
    Quand vous arriverez à  Cupertino 150 minutes plus tard, il sera 27/10/2013 02:45:00 à  Paris...
    ... soit 26/10/2013 18:45:00 heure locale de Cupertino

    Ce qui est parfaitement juste. En effet :
    • le 27 octobre 2013 est le jour où on est passé de l'heure d'été à  l'heure d'hiver en France. Du coup si tu pars de Paris à  1h15 du matin ce jour-là , 2h30 plus tard il ne sera pas 3h45 à  Paris, mais 2h45, puisqu'à  3h du matin ce jour-là  on a reculé d'une heure. Donc au moment où tu arrives à  destination, si tu appelles ta femme restée à  Paris, sa montre indiquera 2h45 et non 3h45 à  cause du passage à  l'heure d'hiver (du moins si elle a mis sa montre à  l'heure ^^). Tu vois donc que le NSDateFormatter prend cela en compte quand il affiche ta date.
    • Et du coup comme entre Cupertino (fuseau horaire PST) et Paris, il y a 9h de décalage horaire quand on est en heure d'été, 8h quand on est en heure d'hiver... Bah là  quand tu arriveras il sera bien 18h45 à  Cupertino quand il sera 2h45 à  Paris
    On voit bien dans mon exemples que :
    - Pour les manipulations de durée, pour exprimer un moment "2h30 plus tard", là  j'ajoute un timeInterval à  la NSDate, pour produire une NSDate différente représentant le moment "150 minutes plus tard".
    - Mais pour les manipulations de changement de fuseau horaire, je change le... fuseau horaire (timeZone), et pas la NSDate elle-même

    Et après NSDate fais les additions comme il faut juste entre un moment et un autre (si tu demandes la différente entre ces 2 moments elle sera toujours de 2h30, quel que soit le fuseau horaire et qu'on ait changé d'heure d'été/hiver ou pas), et c'est NSDateFormatter qui se charge de l'affichage de ce moment soit exprimé dans un fuseau horaire (Paris) soit dans un autre (Cupertino) et en prenant en compte l'heure d'été/heure d'hiver et la locale de l'utilisateur (dates en français façon JJ/MM/AAAA ou en anglais façon MM/JJ/AAAA puisqu'ils mettent le mois en premier, eux), et tous ces détails qui ne sont que différentes façons d'exprimer une même date / un même moment dans le temps.

    ---

    C'est donc à  l'affichage (NSDateFormatter) lors de la conversion en chaà®ne que tu dis que tu veux afficher la date et l'heure telle qu'elle est affichée à  Cupertino ou telle qu'elle est affichée à  Paris. Mais dans les 2 cas, le moment (NSDate) auquel tu arrives à  l'aéroport est le même pour toi qui est à  Cupertino ou ta femme qui est à  Paris et que tu appelles juste en sortant de l'avion.

    (J'ai l'impression que ça fait la 50eme fois que je te l'explique, mais bon)
  • Whaou ! Merci Doc.


    Que me conseilles tu alors pour changer le TimeZone ? j'ai essayé NSArray *timeZoneNames = [NSTimeZone knownTimeZoneNames];  Dans mon PickerView mais ça me fait une liste énorme de destinations Africa, America,Europe.... l'utilisateur va mettre des plombes à  seulement rentrer " j'ai 3 heures de décalages horaires"


    J'ai envie que l'appli soit rapide à  utiliser et là  je crois que ça va énerver plus qu'autre chose.


     


    c'est pour cela que je voulais simplement lui demander de mettre le nombre d'heure décalage avec son pays de départ, c'est à  dire le nombre d'heures en plus ou en moins entre l'heure de Paris et l'heure de Cupertino (je ne sais toujours pas où c'est ! )


     


    Merci beaucoup pour le code !


  • AliGatorAliGator Membre, Modérateur
    Tu peux proposer plusieurs possibilités au choix de l'utilisateur, par décalage horaire, par nom court ou par nom long.

    Par exemple si tu prévois un UITextField pour choisir une TimeZone d'arrivée, tu mets sont inputView à  ton UIPickerView et la inputAccessoryView à  un UISegmentedControl. Tu prévois 3 segments pour le UISegmentedControl (Décalage/Nom court/Nom Long) et tu remplis ton UIPickerView en conséquence :
    - avec des décalages d'heure (-12 à  -12... quoiqu'il y a des pays qui ont un décalage horaire qui n'est pas entier donc ça va pas suffire...) dans le premier cas
    - la liste des noms longs (CET, PST, ...) dans le 2ème cas
    - une liste à  2 colonnes (via ton UIPickerViewDataSource tu lui dis que numberOfComponents = 2) pour le 3ème cas, avec les groupements/continents dans la première roulette (Africa, America, Europe, ...) et les villes correspondant au continent choisi dans la 2ème roulette. Bon faut juste que tu fasses un petit traitement sur le tableau que tu retournes knownTimeZoneNames pour les découper en un tableau de continents d'un côté, un NSDictionary de continent->ville de l'autre côté, pour te faciliter le code de remplissage de ton UIPickerViewDataSource, mais c'est 3x rien.

    Et comme ça, l'utilisateur pourra rentrer le fuseau horaire qu'il veut soit sous forme d'un décalage GMT (et tu utilises "timeZoneWithSecondsFromGMT:" pour construire ta NSTimeZone dans ton code), soit sous forme de nom court (-> "timeZoneWithAbbreviation:"), soit sous forme de Continent/Ville (-> "timeZoneWithName:"), il aura le choix selon ce qui lui convient le mieux (peut-être qu'il connaà®t le nombre d'heure de décalage et préférera le premier segment, peut-être qu'il ne la connaà®t pas et préférera choisir la ville la plus proche pour mieux choisir le fuseau horaire adéquat avec le 3e onglet, peut-être que le nom court de la timezone est marqué sur son billet comme c'est souvent le cas à  côté de l'heure d'arrivée (genre "07:00 PM - PST") et il choisira plus vite avec l'onglet du milieu... à  lui de voir)
  • Eh bien ! ça m'a fait cogiter tout ça ! merci AliGator


    Je suis obligé de faire suivant mes connaissances mais je comprends tout ce que tu m'as expliqué.


    bon ça vaut ce que ça vaut, mais j'obtiens ce que je veux : 


       


        NSDate *now = [NSDate date];


        NSDateFormatter *df = [[NSDateFormatter alloc] init];


        [df setTimeStyle:NSDateFormatterLongStyle];


        [df setTimeZone:[NSTimeZone timeZoneWithName:@Europe/France]];


        NSString *franceTime = [df stringFromDate:now];


        [df setTimeZone:[NSTimeZone timeZoneWithName:@Australia/Melbourne]];


        NSString *melbourneTime = [df stringFromDate:now];


        [df setTimeZone:[NSTimeZone timeZoneWithName:@Europe/Berlin]];


        NSString *berlinTime = [df stringFromDate:now];


        [df setTimeZone:[NSTimeZone timeZoneWithName:@America/Los_Angeles]];


        NSString *laTime = [df stringFromDate:now];


        NSLog(@France = %@", franceTime);


        NSLog(@Melbourne = %@", melbourneTime);


        NSLog(@Berlin = %@", berlinTime);


        NSLog(@Los Angeles = %@", laTime);


     


     


     Maintenant, j'aimerai proposer à  l'utilisateur qu'il tape juste le nom de la ville, qu'il la voit apparaà®tre dans une liste, qu'il la sélectionne et que ça génère de suite l'heure dans l'appli.


     


    ma question est comment faire un UITextField de recherche à  timeZoneWithName ? 


    et comment mettre la liste trouvée en dessous et en temps réel ? comme quand on modifie dans "Réglages ", "Date et heure" en manuel.


  • Vous auriez une idée ou une procédure à  me dévoiler ?


    Merci beaucoup de votre aide .


    Jean-Baptiste


  • AliGatorAliGator Membre, Modérateur
    Alors :
    - avec "[NSTimeZone knownTimeZoneNames]" que tu as déjà  découvert par toi-même, tu as la liste de tous les noms de TimeZones
    - A partir de là , tu peux construire un tableau contenant toutes les NSTimeZone possibles
    - Et pour chacune, utiliser la méthode "localizedName:locale:" pour avoir son localizedName, c'est à  dire son nom localisé / traduit dans la locale (~ langue) que tu veux (à  priori certainement [NSLocale currentLocale] ou un truc comme ça, en tout cas la langue dans laquelle est l'iPhone de l'utilisateur)

    Du coup avec ces outils tu as facilement une liste de NSTimeZone, et par exemple une UITableView qui liste leur localizedName, et un champ de recherche (pourquoi pas avec un UISearchResultController, mais pas obligatoirement) pour rentrer un nom partiel de timezone (comme "Paris"), pour la trouver plus facilement " comme dans l'interface des Réglages de l'iPhone quand on choisis le fuseau horaire manuellement.

    Et à  partir de là  c'est assez simple à  chaque fois que l'utilisateur tape qqch dans le champ de recherche de filtrer les NSTimeZone affichées en fonction de si leur localizedName, interprété dans la locale courante (le français pour nous), contient le texte recherché.

    Après, le choix de l'interface graphique (tableView ou autre) et de l'implémentation (un UITableViewController, UISearchResultController, composant maison, autre) c'est libre à  toi, mais le principe restera le même : récupérer toutes les NSTimeZone, filtrer en fonction de leur localizedName et n'afficher que celles dont ce dernier contient le texte recherché.
  • bonsoir, 


     


    J'épluche toujours ce que tu m'as dit, merci.


     


    là  je bloque dans la syntaxe que je dois mettre pour faire afficher la liste des pays dans le TableView.


     


    Est ce que tu peux m'aider ?


     


    self.objects = [[NSArray alloc]initWithArray:[NSTimeZone knownTimeZoneNames]];


     


    Je n'arrive pas à  bien lui parler comme il veut ;-)

  • AliGatorAliGator Membre, Modérateur
    Bah qu'est ce que t'as fait au juste, quel code tu as mis pour faire ce que je t'ai décris (à  part cette maigre ligne que t'as mis dans ton message je veux dire, qui en plus ne sert à  rien car tu construis un NSArray à  partir d'un truc qui est déjà  un NSArray...) ? Qu'est ce que tu as essayé, et qu'est ce que tu ne comprends pas ?
  • Je suis parti d'une construction de tableau simple et je voulais inclure la liste des TimeZoneName au lieu d'avoir la petite liste d'exemple.


     


    voilà  le code  .m: 


     


    #import "listCountriesTableView.h"


     


    @interface listCountriesTableView ()


     


    @end


     


    @implementation listCountriesTableView


     


    // declare objects et results


     


    - (NSMutableArray *) objects


    {


        if (!_objects) {


            _objects = [[NSMutableArray alloc]init];


        }


        return _objects;


    }


     


    - (NSMutableArray *) results


    {


        if (!_results) {


            _results = [[NSMutableArray alloc] init];


            


        }


        return _results;


    }


     // fin du test


     


     


     


    - (id)initWithStyle:(UITableViewStyle)style


    {


        self = [super initWithStyle:style];


        if (self) {


            // Custom initialization


        }


        return self;


    }


     


    - (void)viewDidLoad


    {


        [super viewDidLoad];


     


        // add countries


        [self.objects addObject:@youtube];


        [self.objects addObject:@climsy];


        [self.objects addObject:@tomatoe];


        [self.objects addObject:@reglisse];


        [self.objects addObject:@fiere];


        [self.objects addObject:@yousube];


        


        


        


        }


     


    - (void)didReceiveMemoryWarning


    {


        [super didReceiveMemoryWarning];


        // Dispose of any resources that can be recreated.


    }


     


     


     


    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView


    {


     


        return 1;


    }


     


    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section


    {


     


        return self.objects.count;


    }


     


    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath


    {


        static NSString *CellIdentifier = @Cell;


        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];


        


        // Configure the cell...


        


        cell.textLabel.text = self.objects[indexPath.row];


        


        


        return cell;


    }


     

     

    Ensuite je mets un UISearchBar pour trouver facilement le pays et que l'horloge de l'appli si mette à  l'heure du pays en question.

     

     

    Dans le même registre, 

    J'ai aussi un autre bout de code simple qui me trouve tout les pays dans une TableView, mais comme je l'ai dit plus haut il y a un AppDelegate qui appelle un rootViewController que je ne sais pas gérer puisque ce n'est pat mon NavigationController principal.

     


    #import "APLAppDelegate.h"


    #import "APLViewController.h"


     


    @implementation APLAppDelegate


     


    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions


    {


        /*


         The table view controller is the first (and in this example only) view controller in the navigation controller's array of view controllers.


         */


        UINavigationController *navController = (UINavigationController *)self.window.rootViewController;


        APLViewController *rootViewController = (APLViewController *)navController.viewControllers[0];


     


    // Retrieve the array of known time zone names, then sort the array and pass it to the root view controller.


    NSArray *timeZones = [NSTimeZone knownTimeZoneNames];


    rootViewController.timeZoneNames = [timeZones sortedArrayUsingSelector:@selector(localizedStandardCompare:)];


     


        return YES;


    }


     


     


    @end


     


    merci de ton aide

  • AliGatorAliGator Membre, Modérateur
    janvier 2014 modifié #23
    Alors :

    1) Je ne comprend pas grand chose à  la logique de ton code...

    - Tu affectes timeZoneNames dans le AppDelegate, c'est pas logique ni POO, c'est à  la responsabilité du ViewController qui va gérer/afficher les TimeZones (donc APLViewController) de créer un tableau de timeZones s'il a besoin de timeZones. L'AppDelegate n'a rien à  voir là  dedans il n'a pas à  savoir comment est organisé APLViewController et c'est pas très logique que ce soit l'AppDelegate qui lui fournisse ça. Chacun sa responsabilité, c'est le principe de base de la POO, car sinon tu obitens très vite du code spaghetti.

    - Et de toutes façon tu affectes des données en dur à  self.objects, et c'est elles que tu utilises dans ton TableViewDataSource : donc au final tu n'utilises jamais ce tableau timeZoneNames dans ton code...

    2) Et du coup en plus je ne vois pas en quoi dans ton code tu as essayé d'implémenter ce que je t'ai donné comme conseils. Le seul truc que tu as fait c'est d'appeler [NSTimeZone knownTimeZoneNames] mais c'est tout, rien de toutes les autres explications


    Du coup si tu n'as pas essayé grand chose et tu t'es contenté d'appeler [NSTimeZone knownTimeZoneNames] sans essayer de creuser + par toi-même, soit tu as essayé d'autres choses mais je peux pas le deviner si tu me dis pas. Soit il y a un point précis que tu n'as pas compris et tu ne me dis pas ce que c'est non plus.

    Il se trouve que ma boule de cristal n'a plus de piles, donc si tu me dis pas un peu plus ce que tu as essayé (je te conseille fortement de suivre les conseils de ce très bon article de Matt Gemmell d'ailleurs si tu veux avoir la réponse adéquate à  ta question).


    PS : Merci d'utiliser les balises "code" pour poster du code source sur les forums.
  • 1) j'en suis là , Tu m'as dit : 


     


    "Alors :
    - avec "[NSTimeZone knownTimeZoneNames]" que tu as déjà  découvert par toi-même, tu as la liste de tous les noms de TimeZones
    - A partir de là , tu peux construire un tableau contenant toutes les NSTimeZone possibles
    - Et pour chacune, utiliser la méthode "localizedName:locale:" pour avoir son localizedName, c'est à  dire son nom localisé / traduit dans la locale (~ langue) que tu veux (à  priori certainement [NSLocale currentLocale] ou un truc comme ça, en tout cas la langue dans laquelle est l'iPhone de l'utilisateur) "


     


    Je cherche la manière de faire un tableau avec tout les TimeZoneName ! 


     


    j'ai trouvé des code qui font des TableView, je suis allé sur Apple Developer qui me propose un exemple de tableView directement avec les TimeZoneName mais qui met du code dans le AppDelegate et je ne sais pas comment le transposer dans le code que je créé de mon appli qui contient déjà  un AppDelegate.


     


    Les données en dur de self.objects font parti de l'exemple qui me donne un tableView rempli dans mon appli. Maintenant je souhaite changer tout ces self.objects par la liste des TimeZoneName mais je ne connais pas la syntaxe à  écrire. c'est le conseil que je te demande : "comment faire apparaitre la liste des TimeZoneName dans le TableView, quelle est la syntaxe"


     


    J'ai l'impression qu'il y a 10 manières de faire un tableview avec ce que je vois sur youtube ou ce que propose apple Developer.


     


    Voilà  je n'ai pas beaucoup avancé parceque je ne savais pas comment faire un tableau, ni comment lui faire apparaitre des lignes écrites, ni quoi faire avec le Appdelegate.


     


    aujourd'hui, j'ai réalisé un tableau, avec une liste, qui sera cliquable plus tard et enverra une heure à  un label. 


    M


  • Ne mets pas les codes de ta TableView dans ton AppDelgate.


    Mets les dans une classe à  part, en fonction de ce dont tu as besoin, un nouveau UIViewController (donc potentiellement un UITableViewController), ou dans une UIView...


  • AliGatorAliGator Membre, Modérateur
    Et dans un premier temps oublie un peu le côté View d'ailleurs : que ta liste soit afficher dans une tableView ou ailleurs ou même juste dans un NSLog le problème que tu as restera le même.

    Ce que tu cherches à  faire c'est une question concernant les données, comment avoir un NSArray avec les noms localisés des timezones ; concentre toi déjà  à  résoudre cela car j'ai l'impression que même là  tu ne vois pas comm t t'y prendre alors que si tu décomposes ce problème tranquillement comme j'ai décrit ça se fait assez simplement.

    Seulement après tu pourras te poser la question de comment utiliser ce NSArray comme source de données pour une UITableview (ou pour un UIPickerView ou pour n'importe quel autre composant de ton choix)


    Tu cherches à  avoir un tableau avec tous les timeZoneName : bah tu l'as déjà , c'est [NSTimeZone knownTimeZoneNames]. Par contre il ne te retourne peut-être pas ces noms de manière localisée (= dans la langue de l'utilisateur et sous forme de texte user-friendly).


    Du coup il suffit de boucler sur ces knownTimeZoneNames ("for(... in ...)") et pour chacun, récupérer le nom localisé associé (en instanciant une NSTimeZone avec ce nom et en demandant à  cette instance son localizedName) et de le rajouter dans un NSMutableArray que tu remplis au fur et à  mesure.


    Bref ce que j'ai déjà  décrit plus haut quoi.


    Donc décompose tout ça étape par étape, concentre toi sur la création de ce tableau (ça devrait tenir en moins de 10 lignes de code à  priori) et garde l'autre problème de comment l'afficher ensuite dans une TableView pour plus tard, dans un 2ème temps.
  • Je vais suivre la procédure que tu m'indiques.


    Merci à  vous deux.


    C'est vrai que je suis impatient et un peu frustré car je n'ai pas de méthodes pour avancer. En fait seulement celles que vous voulez bien me donner. C'est comme si je me lançais dans la rédaction d'un roman et que je ne savais pas écrire. c'est super frustrant.


     


    Merci de votre  aide !


  • voici le code que j'ai de Apple pour travailler, dedans il y a le code avec le AppDelegate dont je ne sais quoi faire.


     


    https://developer.apple.com/library/ios/samplecode/TableViewSuite/Introduction/Intro.html


     


     


    pour le moment j'essaye de faire simplement l'exemple SimpleTableView dans mon appli mais sans succès ! Argh !



     
  • Ok ça y est j'arrive à  faire apparaitre la liste des TimeZones ! 


     


    J'ai deux soucis : 


    - NSArray et NSMutableArray lequel choisir ?


     


    si je mets dans le viewDidLoad : 


    NSArray *timeZones = [NSTimeZone knownTimeZoneNames];


    _timeZoneNames = [timeZones sortedArrayUsingSelector:@selector(localizedStandardCompare:)];


        


    est ce que c'est correct ? et si je veux faire une SearchBar est ce que ça pose un problème ?

    car lorsque j'en fait une elle ne me trie que la partie visible de ma TableView et non pas sur toutes les autres villes ?

     

    Le souci que j'ai c'est lorsque je mets un UISearchBar il ne me trie que les lignes visibles.


     


    la liste de départ est : 

     

    Africa/Abidgan

    Africa/Abbu dabi

    ....

    Africa/Blantyr

     

    et si je mets Paris : le trie ne le trouve pas 

     

    Est ce que le problème vient d'une mauvaise allocation de NSArray et NSMutableArray ?

     

    Gracias por su respuesta !


  • - une liste à  2 colonnes (via ton UIPickerViewDataSource tu lui dis que numberOfComponents = 2) pour le 3ème cas, avec les groupements/continents dans la première roulette (Africa, America, Europe, ...) et les villes correspondant au continent choisi dans la 2ème roulette. Bon faut juste que tu fasses un petit traitement sur le tableau que tu retournes knownTimeZoneNames pour les découper en un tableau de continents d'un côté, un NSDictionary de continent->ville de l'autre côté, pour te faciliter le code de remplissage de ton UIPickerViewDataSource, mais c'est 3x rien.

     



     


    bonsoir, 


     


    J'ai créé un UIPicker avec 2 colonnes et j'aimerai faire la première colonne avec les continents et la deuxième avec les villes.


    le problème est que mes listes se ressemblent. 


    Peux tu m'expliquer pour découper la liste quand il y a un "/" ? est ce que la fonction Enumerator est adéquate  ?


    Et le NSDictionary  continents->ville, puis je utiliser la fonction [NSTimeZone knownTimeZoneNames] aussi ?


    Là  je bloque !

  • AliGatorAliGator Membre, Modérateur
    janvier 2014 modifié #31
    - boucler sur les knownTimeZoneNames

    - pour chacune, séparer le continent de la ville avec componentsSeparatedByString:@/

    - remplir un nsmutabledictionary avec, où les clés sont les continents et la valeur associée est un NSMutableArray des villes de ce continent. Tu remplis donc ce dico au fur et à  mesure de ta boucle.


    À la fin tu as un dico dont allKeys est un tableau (non trié) de continents et pour chaque clé tu as un tableau des villes correspondant à  ce continent, donc tu as tout ce qu'il faut pour ton remplir tes 2 colonnes.


    C'est un algo assez basique je vois pas trop ce qui te bloque en fait...
Connectez-vous ou Inscrivez-vous pour répondre.