UIActionSheet déprécié brutalement!!!

Bonjour,


 


Je me sers beaucoup de UIActionSheet dans mes applis. Horreur et consternation (mais vraiment, c'est incroyable), cette classe est brutalement dépréciée dans iOS8 et remplacée par une autre inconnue auparavant. (Qui apparait avec iOS8)


Résultat, des fonctions centrales dans mes applis ne sont tout simplement plus utilisables!!! Plus moyen de sélectionner un type de patch dans Dazibao, rendant le synthé inutilisable!! Plus moyen de créer un nouveau dessin dans mon futur Geometrix iPad.



Je suis totalement abasourdi! Comment se fait-il qu'une classe aussi importante soit supprimée et remplacée sans temps de transition??? A mon sens, il faut protester auprès d'Apple, ils bousillent notre travail d'un coup. Quelle honte!


Réponses

  • Heu, si je ne me trompe pas, "deprecated" ne veut pas dire que ce n'est plus du tout utilisable. Normalement tu as des warnings mais çà  doit continuer de fonctionner. Tu devrais donc avoir le temps de passer à  l'autre classe tranquillement.


  • AliGatorAliGator Membre, Modérateur
    Oui elle n'est même pas dépréciée avec un __attribute__(deprecated), c'est juste indiqué dans la doc, tellement ils savent qu'elle est centrale et qu'on va mettre du temps à  l'abandonner.
  • D'après la doc, il faut utiliser UIAlertController avec le bon "preferredStyle"...


  • HerveHerve Membre
    octobre 2014 modifié #6

    Oui, mais alors pourquoi ces boutons ne fonctionnent plus sur mon iPad?? Cela ne marche plus du tout!!


     


    Pour l'afficher, j'utilisais cette méthode :



    UIWindow* window = [[[UIApplication sharedApplication] delegate] window];


    if ([window.subviews containsObject:self.view]) {
    [typePatchAlert showInView:self.view];

    } else {
    [typePatchAlert showInView:window];
    }

    C'est la méthode "else" qui est maintenant utilisée. Auparavant, la première fonctionnait très bien. Bizarre, non? 


     


    La console m'indique ceci :



     


    Attempt to present <UIAlertController: 0x156e094c0> on <PatchEditor: 0x156d2d390> whose view is not in the window hierarchy!


  • HerveHerve Membre
    octobre 2014 modifié #7

    Bon, sur une des applis, la méthode initiale de mon bouquin fonctionne, sur la seconde non, je ne sais pas pourquoi.



    UIActionSheet *typePatchAlert = [[UIActionSheet alloc]initWithTitle:nouvFig delegate:self cancelButtonTitle:NSLocalizedString(@YES, @"") destructiveButtonTitle:NSLocalizedString(@YES, @"") otherButtonTitles:NSLocalizedString(@CANCEL, @""),nil];
    //nouvelFig est une NSString
    typePatchAlert.actionSheetStyle = UIActionSheetStyleDefault;
    [typePatchAlert showInView:self.view];

  • AliGatorAliGator Membre, Modérateur

    Oui, mais alors pourquoi ces boutons ne fonctionnent plus sur mon iPad?? Cela ne marche plus du tout!!
     
    Pour l'afficher, j'utilisais cette méthode :


    UIWindow* window = [[[UIApplication sharedApplication] delegate] window];

    if ([window.subviews containsObject:self.view]) {
    [typePatchAlert showInView:self.view];

    } else {
    [typePatchAlert showInView:window];
    }
    C'est la méthode "else" qui est maintenant utilisée. Auparavant, la première fonctionnait très bien. Bizarre, non?

    Heu c'est ta façon de faire qui est très très bizarre !!!

    Ca vient d'où cette idée de cette condition ?

    1) Si tu veux savoir si ta self.view est affichée à  l'écran, il ne faut pas vérifier si elle est descendante directe de ta window (car il se peut tout à  fait " et c'est d'ailleurs certainement le cas sous iOS8 avec une vue intermédiaire qui a été insérée dans la hiérarchie pour faciliter les ViewController Custom Transitions " que ta vue ne soit pas une subview directe de ta window, mais une sous-subview.
    Non, à  la place, si tu veux savoir si ta self.view est visible à  l'écran, il faut faire l'inverse : il faut regarder si ta self.view a une window : if (self.view.window != nil)

    2) Je ne suis pas sûr que ce soit une bonne idée d'afficher une UIAlertView & UIActionSheet sur une UIWindow directement. Ce n'est pas prévu pour. D'autant que si je ne dis pas de bêtises, historiquement, une UIAlertView s'affiche dans sa propre UIWindow (par dessus la mainWindow, et avec son propre windowLevel spécifique), lui permettant d'être au dessus de tout (même du clavier, etc), et je me demande si ce n'est pas pareil pour une UIActionSheet du coup.

    A la limite tu pourrais l'afficher dans la [UIApplication sharedApplication].delegate.window.rootViewController.view mais bon, ça reste discutable quand même ce test...


    En bref, ton test est très bizarre, et tu as eu de la chance que ça marche sous iOS7, c'était une bidouille et un coup de bol, car ce n'était pas sensé marcher (du moins ce n'était pas sensé passer retourner YES dans le "if", et le code dans le "else" n'était pas garanti de marcher non plus).
  • Merci AliGator,


     


    Je ne sais plus pourquoi j'ai fait cette bidouille "à  l'époque". En effet, avec le recul c'est étonnant. En console, je m'aperçois aussi que l'UIActionSheet est crée mais avec un CGrect large et haut de zéro!!! Là  encore, c'est étonnant!! :))


    Pour le nouveau soft, le problème est réglé, pour le synthé, je m'y colle maintenant.


     


    Auriez-vous une doc au sujet de la hiérarchie des vues? Apparemment, il me faudrait réviser (je croyais avoir compris pourtant...)


  • CéroceCéroce Membre, Modérateur


     je m'aperçois aussi que l'UIActionSheet est crée mais avec un CGrect large et haut de zéro!!! Là  encore, c'est étonnant!! :))




    Pas tellement en fait.


    Avec l'avènement de l'Autolayout, la frame n'a pas trop de sens à  l'init, puisqu'elle sera calculée par la suite.

  • Merci Céroce.


    En fait, la méthode classique "self.view" fonctionne partout, sauf avec l'alerte pour choisir le type de patch.


    Je pense que le problème vient que cette alerte s'ouvre automatiquement dès l'ouverture de la page. A t-elle eu le temps d'être "mise dans la "window hierarchy"?


     


    Je lis cette info dans la console :



     


    2014-10-08 15:39:16.005 Dazibao[1094:27424] view = <UIView: 0x7b8bb540; frame = (0 0; 1024 768); autoresize = RM+BM; layer = <CALayer: 0x7b8bb5b0>>, alert = <UIActionSheet: 0x7b8bc670; frame = (0 0; 0 0); layer = <CALayer: 0x7b8aeec0>>



    //ce qui précède est la réponse à  mon NSLog, description de self.view et de l'UIActionSheet



    2014-10-08 15:39:16.007 Dazibao[1094:27424] Warning: Attempt to present <UIAlertController: 0x7b8300c0> on <PatchEditor: 0x7aea0440> whose view is not in the window hierarchy!



    //Ce qui précède est le message d'erreur. Là , j'ai eu de la chance, cela n'a pas planté le logiciel...


     


    (La fenêtre a été programmée avec Storyboard/IB. Elle dépend d'un UIViewController normal.)


  • AliGatorAliGator Membre, Modérateur
    octobre 2014 modifié #12
    Bah le log me semble clair tu essayes d'afficher une alert view ou actionsheet sur un VC bien trop tôt, alors qu'il n'a même pas encore chargé sa vue...


    Fait peut-être réviser le life-cycle d'un ViewController (viewDidLoad puis viewWillAppear puis viewDidAppear etc) tu dois certainement mettre ton code pour afficher ton UIAlertController/UIActionSheet dans la mauvaise méthode...
  • Oui, c'est bien cela. Je viens de tester un nouveau truc : la méthode de dessin d'une subview envoie une notification si la condition qui fait que l'on a besoin d'utiliser cette UIActionSheet a cours :


    (si "int typePatch == 0">> NSNotification >> UIActionSheet dans la fenêtre principale.  Avant c'était à  l'ouverture, maintenant c'est durant une méthode dessin)


    Par contre, j'ai une boucle!! La réponse dans 



    - (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex{
    //...
    if ([actionSheet.title isEqualToString:@Which kind of patch do you want to create?]){
    //initialisation de valeurs;}
    }

    était appelée deux fois sans raison, en mettant une réponse non possible (typePatch à  5, alors que le max est à  4) la seconde fois!!! J'ai dû mettre :



    int valPatch = (int) buttonIndex + 1;
    if (valPatch > 4)return;

    mais c'est franchement du bricolage! Pourquoi donc est-ce qu'il y a une boucle non attendue là ???


    La première réponse (celle cliquée) est correctement traitée, la seconde n'a jamais été déclenchée à  l'écran et détruit la première action!!


  • AliGatorAliGator Membre, Modérateur
    Quelle idée d'utiliser les NSNotifications aussi !

    A tous les coups soit ta notification est observée 2 fois, soit je sais pas ce que tu appelles "ta méthode de dessin" mais j'espère que c'est surtout pas "drawRect:" car sinon ça serait du grand n'importe quoi de l'appeler là  dedans !
  • HerveHerve Membre
    octobre 2014 modifié #15

    J'ai donc fait n'importe quoi!  Bon, cherchons encore...


     


    Merci AliGator.


     


    Je n'ai pas trouvé une méthode qui indique que la vue a fini d'être chargée. je pensais que "viewDidLoad" était la bonne (elle marchait d'ailleurs précédemment) mais là  je ne vois pas.


     


    La méthode "isViewLoaded" indique YES, que faire?


  • Bon, j'ai trouvé.


     


    Cela marche (enfin) en implémentant 



    - (void) viewDidAppear:(BOOL)animated{
    if (typePatch == 0) //méthode de sélection.
    }

    Merci à  tous pour votre aide (et vos utiles mises en garde!)


    :)


     


    Problème résolu. C'est juste les premiers acheteurs de mon synthé qui doivent être coincés... Faut que je me grouille...


  • AliGatorAliGator Membre, Modérateur
    Quand on surcharge viewDidAppear il faut toujours appeler super.

    C'est bien ce que je disais, il faut peut-être réviser le Life-Cycle des ViewControllers, que tu sois bien au clair sur le cycle de vie d'un VC et quelles méthodes sont appellées et quand parmi toutes celles-là .

    - viewDidLoad est appellée quand la vue a été chargée (instanciée par son VC, en se servant du XIB). Ca veut pas pour autant dire que la vue est visible à  l'écran, mais ça veut dire que la vue a été instanciée
    - Une fois que viewDidLoad a été appellée, isViewLoaded retournera alors YES. Du moins jusqu'à  ce que la vue soit déchargée (et que viewDidUnload soit appellée) dans le cas où il y aurait une alerte mémoire pendant que la vue n'est plus à  l'écran et que tu aies alors décidé de libérer un peu la mémoire en relâchant la vue pour la recharger plus tard si jamais elle devait reservir
    - viewWillAppear & viewDidAppear indiquent que la vue (qui a forcément à  ce stade été instanciée, donc) va apparaà®tre à  l'écran / est apparue à  l'écran

    La vue d'un UIViewController peut tout à  fait être loaded mais pas affichée, donc. Un tour dans la doc et les tutos sur ce cycle de vie t'éclaircira certainement les idées sur ces concepts de base utilisés partout dans toute application iOS
  • HerveHerve Membre
    octobre 2014 modifié #18

    Je constate un nouveau problème général à  toutes les UIActionSheet. Là , il va falloir sans doute adopter les nouvelles méthodes :


     


    Quel que soit l'UIActionSheet, la méthode 



    - (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex

    est appelée deux fois. La première fois, elle donne l'item sélectionné, la seconde fois elle donne le nombre d'items dans l'UIActionSheet, et ce dans tous les cas de figure. Bref, cette méthode dysfonctionne manifestement. (sous iOS7, elle marchait très bien)


    Je précise que l'UIActionSheet n'a été instanciée qu'une fois. (vérif en console)


    Il semble que c'est lorsqu'elle se ferme que la méthode est appelée de nouveau. Apparemment, la méthode est bien dépréciée...


  • HerveHerve Membre
    octobre 2014 modifié #19

    Pouvez-vous vérifier chez vous?



    - (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex

    est appelée deux fois, même dans les UITableView.


    Catastrophe!


     


    J'ai trouvé ceici :


    http://stackoverflow.com/questions/25946407/uiactionsheet-delegate-method-calling-twice-in-ios8


     


    et cela :


    https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIModalViewDelegate_Protocol/index.html


     


    C'est vache tout de même non? De quoi bousiller le travail de nous tous, au moins!!!


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