UIAlertViewEx et UIActionSheetEx (blocks)

AliGatorAliGator Membre, Modérateur
mars 2012 modifié dans Objective-C, Swift, C, C++ #1
Hello,



Pour les intéressés, j'ai rajouté dans mes repositories GitHub deux classes : UIAlertViewEx et UIActionSheetEx.

Leur principe c'est d'utiliser les blocks (eh oui, encore, je suis fan j'y peux rien c'est tellement pratique) pour simplifier le code et faciliter la gestion de la callback (quand l'utilisateur choisit une des options proposées par l'alerte ou la sheet).



Ainsi, au lieu de devoir déclarer un delegate et implémenter les méthodes comme "...didDismissWithButtonIndex", et de commencer à  être le boxon quand on veux afficher plusieurs UIAlertViews avec un même delegate qui doit du coup les différencier, maintenant avec ces classes c'est plus simple :
id obj = ... // soit un objet quelconque à  l&#39;extéieur du block<br />
<br />
[UIAlertViewEx showAlertWithTitle:@&quot;Confirmation&quot;<br />
                          message:[NSString stringWithFormat:@&quot;Do something with object %@?&quot;,[obj description]]<br />
                     cancelButton:@&quot;No&quot;<br />
                         okButton:@&quot;Yes&quot;<br />
                   onButtonTapped:^(UIAlertViewEx* alert, NSInteger buttonIndex)<br />
    {<br />
        NSLog(@&quot;button tapped: %d&quot;,buttonIndex);<br />
<br />
        if (buttonIndex == alert.cancelButtonIndex) {<br />
            NSLog(@&quot;Cancel&quot;);<br />
        } else {<br />
            [obj doSomething];<br />
        }<br />
    }];
Et hop, tout est au même endroit, pas besoin de faire une méthode séparée pour récupérer la réponse, et ça ne marche pas sur les platebandes d'une autre UIAlertViewEx si on veut en mettre une autre dans le même fichier.m.

De plus comme à  chaque fois avec les blocks, on peut récupérer la valeur d'une variable extérieure au block, comme ici obj, pour effectuer ce qu'on veut dessus selon la réponse à  la question (alors qu'avec un delegate...)



Comme d'hab, seul inconvénient, ce n'est compatible qu'à  partir de iOS 4.0, mais avec tous les avantages qu'apportent les blocks, vous êtes encore à  faire mumuse avec iOS 3.x vous ? image/biggrin.png' class='bbc_emoticon' alt=':D' />

Réponses

  • muqaddarmuqaddar Administrateur
    14:50 modifié #2
    C'est tellement un truc de fou que je me demande comment Apple ne fournit pas des choses comme ça maintenant ?  :o

    J'ai pas le temps d'aller voir ta moulinette, mais ça me dépasse techniquement. 

    C'est clair qu'il m'arrive d'avoir 3 ou 4 AlertView et que c'est le bordel avec la gestion du delegate.

    Je ne comprends pas MAC OS 10.6 ? ça s'appelle quand même UI et pas NS ? (ou bien tu ne l'as pas cité je suppose) Et si t'as fait un truc générique en fonction du contexte, je te propose UINSAlertView...
  • cyranocyrano Membre
    14:50 modifié #3
    De plus comme à  chaque fois avec les blocks, on peut récupérer la valeur d'une variable extérieure au block, comme ici obj, pour effectuer ce qu'on veut dessus selon la réponse à  la question (alors qu'avec un delegate...)


    je suis moins "fan", pour la lisibilité du block je préfère le passer en argument.
  • muqaddarmuqaddar Administrateur
    14:50 modifié #4
    Ayé, j'ai fait le curieux et je suis allé voir ton code.
    En fait, c'est que pour iOS.  :P

    Tu parles de MacOS 10.6 par rapport au simulateur ?

    #warning UIActionSheetEx uses blocks that are supported only since iOS 4.0 and MacOSX 10.6<br />@interface UIActionSheetEx : UIActionSheet @end<br />#endif
    


  • AliGatorAliGator Membre, Modérateur
    14:50 modifié #5
    Merde t'as raison en fait ma classe n'est dispo (et testée) que pour iOS
    En fait mon petit passage concernant "OSX.6" c'est le passage générique sur les "blocks" qui sont apparus donc avec iOS4 côté iOS et avec 10.6 côté OSX, mais c'est vrai que là  pour ce cas ma classe n'est compatible que iOS ;)
  • AliGatorAliGator Membre, Modérateur
    14:50 modifié #6
    dans 1296553302:

    De plus comme à  chaque fois avec les blocks, on peut récupérer la valeur d'une variable extérieure au block, comme ici obj, pour effectuer ce qu'on veut dessus selon la réponse à  la question (alors qu'avec un delegate...)


    je suis moins "fan", pour la lisibilité du block je préfère le passer en argument.
    Il se trouve que pour UIAlertViewEx j'ai aussi rajouté (aussi pour ceux qui voudraient l'utiliser en pré-iOS4) la possibilité.
    En effet, UIAlertViewEx possède une propriété "userInfo" dans laquelle tu mets ce que tu veux, et qui te permet donc d'associer un objet quelconque (un dictionnaire contenant un peu tout ce dont tu as besoin) à  ta AlertView, et donc de le récupérer au moment du delegate.
    C'est comme ça que je faisait avant l'existance les blocks, j'utilisais les tags de la AlertView pour différencier mes UIAlertViews dans les méthodes de delegate, et le userInfo que j'ai rajouté pour balader des objets et les récupérer dans le delegate (bien plus propre que les mettre en variable d'instance)
    D'ailleurs pour UIAlertViewEx je suis aussi allé jusqu'à  rajouter la possibilité de définir le selector que l'on veut appeler à  la place du alertView:didDismissWithButtonIndex:, comme ça on peut avoir 3 AlertViews dans son code qui appellent chacune leur propre @selector, c'est déjà  ça pour avoir un code plus propre.
  • muqaddarmuqaddar Administrateur
    14:50 modifié #7
    dans 1296555184:

    Merde t'as raison en fait ma classe n'est dispo (et testée) que pour iOS
    En fait mon petit passage concernant "OSX.6" c'est le passage générique sur les "blocks" qui sont apparus donc avec iOS4 côté iOS et avec 10.6 côté OSX, mais c'est vrai que là  pour ce cas ma classe n'est compatible que iOS ;)


    Peut-être un travail pas trop compliqué à  faire pour faire soit hériter de NSAlertView soit de UIAlertView en analysant le contexte + macro ?
  • AliGatorAliGator Membre, Modérateur
    14:50 modifié #8
    Non en effet je pense que c'est jouable, mais comme je suis pas mal au taquet et concentré sur du dev iOS pour l'instant, cette généralisation attendra un peu :D

    Là  je suis au taquet pour FoodReporter donc j'ai mis cette classe parce qu'elle était déjà  prête sous la forme sous laquelle je l'utilise, mais pour OSX faudrait que je prenne le temps de le rajouter et le tester


    Après, libre à  toi ou qui veut de le faire et participer ceci dit :) Ca vous entraà®nera sur les blocks au passage ^^
  • chkdskschkdsks Membre
    février 2011 modifié #9
    J'ai déjà  vu des blocks (c'est le ^ ?) mais je crois que cela est seulement compatible avec le Mac OS X 10.6 SDK, je développe une appli mac Universelle 10.5-10.6, est ce que je peux les utiliser ? le [completion copy] fait très fort, un block dérive de NSObject (ce qui est assez bizarre) ou c'est simplement du sucre syntaxique ? (ce n'est pas clair dans la doc pour moi)

    Autre question mais purement au sujet d'iOS, j'aimerais tester des applications iOS dans le simulateur iOS (je n'ai pas d'iPhone), faut il obligatoirement avoir le code source ? et faut il un certificat de développeur spécial comme avec ses propres extensions avec Safari ? (j'ai juste un compte gratuit de développeur apple) En fait je me suis re-posé la question parce que le code du projet vient de FoodReporter...

    Merci !
  • DrakenDraken Membre
    14:50 modifié #10
    Oui, il faut forcément avoir le code source d'une application pour la tester avec le simulateur. Un compte gratuit suffit pour cela. Par contre, pour tester l'application sur un iPhone, il faut forcément un certificat de développeur et un compte payant à  99$/an.

  • AliGatorAliGator Membre, Modérateur
    février 2011 modifié #11
    dans 1296815360:
    J'ai déjà  vu des blocks (c'est le ^ ?) mais je crois que cela est seulement compatible avec le Mac OS X 10.6 SDK, je développe une appli mac Universelle 10.5-10.6, est ce que je peux les utiliser ?
    En effet, comme je l'ai mentionné ici :
    1) les blocks ne sont apparus que depuis MacOSX 10.6 et iOS 4.0 et ne sont pas compatibles avec les versions précédentes
    2) UIAlertView et UIActionSheetEx dérivent de UIAlertView et UIAcionSheet, qui son des classes disponibles uniquement sous iOS. Je pourrais un de ces 4 faire la classe équivalente pour NSAlertView en effet, mais j'ai pas trop le temps en ce moment (et comme je n'en ai pas besoin pour l'instant, je vous laisse l'exercice :P)

    dans 1296815360:
    le [completion copy] fait très fort, un block dérive de NSObject (ce qui est assez bizarre) ou c'est simplement du sucre syntaxique ? (ce n'est pas clair dans la doc pour moi)
    En fait un peu des deux. A proprement parler, on ne peut pas dire que "un block dérive de NSObject", mais en fait c'est tout comme : en interne les structures créées par le compilateur quand il compile les blocks se trouvent avoir la même structure interne qu'un NSObject et répondent aux méthodes retain, release et copy. C'est donc en effet un peu comme du sucre syntaxique.
    Appeler "copy" sur un block revient à  appeler la fonction C "Block_copy", et appeler "release" revient à  appeler "Block_release".



    Le seul piège auquel il faut faire gaffe avec les blocks, c'est que bien souvent comme ils sont déclarés "inline" directement dans le code, le block n'existe que dans le scope dans lequel il a été défini. On aurait le même cas avec des pointeurs d'ailleurs, par exemple :
    int * pointeur;<br />if (test) {<br />&nbsp; int i = 5;<br />&nbsp; pointeur = &amp;i;<br />} else {<br />&nbsp; int j = 8;<br />&nbsp; pointeur = &amp;j;<br />}<br />// une fois sorti du &quot;if&quot;, i et j n&#39;existent plus et ont été déruits,<br />// et du coup &#39;pointeur&#39; pointe vers un truc qui n&#39;existe plus<br />//(plantage assuré si on l&#39;utilise et le déréférence)
    
    Avec les blocks c'est pareil il y a le même risque, puisqu'en substance c'est un peu comme un pointeur de fonction, fonction déclarée "en inline", dans un scope donné et qui donc disparaà®tra quand on va en sortir.
    C'est pour cela qu'il faut toujours faire un "copy" sur un block plutôt qu'un "retain" en fait, car par contre faire un "copy" permet de copier le block sur le tas et donc que cette copie persiste même en dehors du scope.

    En résumé, ne jamais faire un "retain" sur un block, mais bien un "copy". Et même si on voulais pas retenir le block mais juste l'affecter, faut même mieux parfois faire un "ivar = [[monBlock copy] autorelease];" que "ivar = monBlock".

    C'est à  mon sens LE détail piège avec les blocks, parce qu'à  part ça une fois qu'on a intégré cette subtilité, le reste c'est rien de bien particulier.



    dans 1296815360:
    Autre question mais purement au sujet d'iOS, j'aimerais tester des applications iOS dans le simulateur iOS (je n'ai pas d'iPhone), faut il obligatoirement avoir le code source ? et faut il un certificat de développeur spécial comme avec ses propres extensions avec Safari ? (j'ai juste un compte gratuit de développeur apple) En fait je me suis re-posé la question parce que le code du projet vient de FoodReporter...

    Merci !
    Malheureusement non on ne peut pas "installer des applications de l'AppStore sur le simulateur", la seule façon est d'avoir le code source ;)
  • chkdskschkdsks Membre
    février 2011 modifié #12
    J'avais cru comprendre avant votre post que l'on pouvait les utiliser sur la 10.5 en faisant des appels systèmes en C pur dans son code Objective-C mais c'est une nouveauté dans les fondations de la 10.6, ce n'est pas seulement une nouveauté du SDK. En fait je pensais que le C ne faisait pas parti du SDK, qu'il était géré à  part, ce qui est encore faux, je m'embrouille... B) J'ai du regarder dans /Developer/SDKs :o

    Merci Draken et AliGator pour les éclaircissements, je pense avoir bien compris la subtilité sur le scope du block. :)
  • AliGatorAliGator Membre, Modérateur
    février 2011 modifié #13
    En fait non le C ne fait pas partie du SDK.

    Mais pour être précis, les blocks sont une nouveauté du compilateur gcc et une évolution du langage C, et nécessitent pour fonctionner des évolutions des libs C qui n'ont été apportées qu'avec OSX.6 et iOS.4
    Après le fait qu'on utilise ces constructions spécifiques, venant de cette évolution du C, dans Objective-C, n'est que la suite logique (ça serait bête de pas profiter dans Objective-C des évolutions du langage C apportées par ces nouvelles libs)

    Mais c'est vrai que tu as raison (et pour tout de dire tu me mets le doute) on pourrait aussi se dire que c'est du pur sucre syntaxique et qu'une fois le code source qui utilise les blocks est compilé en fichier objet, et donc converti en un binaire exécutable, il pourrait tout à  fait être exécuté sur une machine sous OSX.5 puisqu'au niveau du binaire la notion de "blocks" est plus trop présente... (après tout on peut voir les blocks comme des structures contenant un pointeur de fonction et quelques méta-données et variables associées à  ce pointeur de fonction, tout cela construit automatiquement par le compilateur) mais je ne sais si c'est aussi simple que cela...
  • muqaddarmuqaddar Administrateur
    14:50 modifié #14
    Quelqu'un connaà®t la part de marché d'iOS 4.x par rapport au 3.x pour savoir si on peut intégrer la fantaisie d'Ali ?
  • AliGatorAliGator Membre, Modérateur
    14:50 modifié #15
    dans 1296923472:

    Quelqu'un connaà®t la part de marché d'iOS 4.x par rapport au 3.x pour savoir si on peut intégrer la fantaisie d'Ali ?
    iOS4 déployé à  hauteur de 90% sur les iPhone et iPod Touch
  • muqaddarmuqaddar Administrateur
    14:50 modifié #16
    Merci Ali ! :)
  • muqaddarmuqaddar Administrateur
    14:50 modifié #17
    Je viens d'intégrer les 2 pépites dans la prochaine version de Vinocela qui sera iOS > 4.x.
    Du grand art. Je réitère mes propos. 
  • AliGatorAliGator Membre, Modérateur
    14:50 modifié #18
    Merci :) C'est tellement plus simple à  utiliser, on se demande pourquoi Apple ne les a pas encore intégrés
  • muqaddarmuqaddar Administrateur
    14:50 modifié #19
    dans 1309336175:

    Merci :) C'est tellement plus simple à  utiliser, on se demande pourquoi Apple ne les a pas encore intégrés


    Ni dans iOS 5 donc ? (pas encore téléchargé)
  • AliGatorAliGator Membre, Modérateur
    14:50 modifié #20
    dans 1309338592:

    (pas encore téléchargé)
    Moi non plus
  • muqaddarmuqaddar Administrateur

    Salut Ali,


     


    Tu n'as pas remarqué quelques problèmes avec UIActionSheetEX sous iOS 8 ?


    Elle ne s'affiche plus et me réclame des contraintes... mais lesquelles ?



    - (IBAction)wantToShare:(id)sender
    {
      [UIActionSheetEx showSheetInView:self.view
                                 title:_T(SHARE)
                     cancelButtonTitle:_T(CANCEL)
                destructiveButtonTitle:_T(EMAIL)
                     otherButtonTitles:[NSArray arrayWithObjects:_T(FACEBOOK), _T(TWITTER), nil]
                            completion:^(UIActionSheetEx* alert, NSInteger buttonIndex)
       {
         if (buttonIndex == alert.cancelButtonIndex) { /* do nothing */ }
         else
         {
           if (buttonIndex == alert.destructiveButtonIndex)
           {
             [self wantToShareToEmail:nil];
           }
           else
           {
             if (buttonIndex == 1) [self wantToShareToFacebook:nil];
             if (buttonIndex == 2) [self wantToShareToTwitter:nil];
           }
         }
       }]; 
    }

    self.view est la vue principale du VC... je vois pas ce que je peux faire de plus ?


     



    2014-07-24 10:37:19.617 AppD[4140:7506468] Unable to simultaneously satisfy constraints.


    Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 


    (


        "<NSLayoutConstraint:0x7faf6c861f10 H:[UIView:0x7faf6a4e24e0(304)]>",


        "<NSLayoutConstraint:0x7faf6c862c30 _UIAlertControllerView:0x7faf6a4dc940'Share'.width >= UIView:0x7faf6a4e24e0.width>",


        "<NSLayoutConstraint:0x7faf6c89ed60 _UIAlertControllerView:0x7faf6a4dc940'Share'.width == UIView:0x7faf6c852e40.width>",


        "<NSAutoresizingMaskLayoutConstraint:0x7faf6c8bf480 h=--& v=--& H:[UIView:0x7faf6c852e40(0)]>"


    )


     


    Will attempt to recover by breaking constraint 


    <NSLayoutConstraint:0x7faf6c861f10 H:[UIView:0x7faf6a4e24e0(304)]>


     


    Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.


    The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.


     



     


  • AliGatorAliGator Membre, Modérateur
    juillet 2014 modifié #22
    Ces classes ont été renommées (en OHActionSheet et OHAlertView) histoire d'y mettre mon préfixe plutôt qu'un nom générique.


    Du coup elles ont changé de repository sur GitHub maintenant elles en ont un chacun (et un pod chacun aussi) et c'est elles que je fais évoluer et non plus UIActionSheetEx et UIAlertViewEx



    Du coup commencé par mettre à  jour vers ça (depuis le temps, ça doit faire bien 2 ans ^^)


    Ensuite tu verras il y a une issue ouverte sur OHActionSheet mais qui en fait est un bug Apple qu'on a aussi sur UIActionSheet depuis iOS8, mais rien à  voir avec des pb de contraintes que tu décris ici.
  • muqaddarmuqaddar Administrateur


    Ces classes ont été renommées (en OHActionSheet et OHAlertView) histoire d'y mettre mon préfixe plutôt qu'un nom générique.


    Du coup elles ont changé de repository sur GitHub maintenant elles en ont un chacun (et un pod chacun aussi) et c'est elles que je fais évoluer et non plus UIActionSheetEx et UIAlertViewEx



    Du coup commencé par mettre à  jour vers ça (depuis le temps, ça doit faire bien 2 ans ^^)


    Ensuite tu verras il y a une issue ouverte sur OHActionSheet mais qui en fait est un bug Apple qu'on a aussi sur UIActionSheet depuis iOS8, mais rien à  voir avec des pb de contraintes que tu décris ici.




     


    J'avais loupé les nouvelles versions, je vais télécharger ça et je reviens à  la charge si besoin !

  • muqaddarmuqaddar Administrateur


    Ensuite tu verras il y a une issue ouverte sur OHActionSheet mais qui en fait est un bug Apple qu'on a aussi sur UIActionSheet depuis iOS8, mais rien à  voir avec des pb de contraintes que tu décris ici.




     


    Oui, plus de problèmes de contraintes.


     


    Par contre, je te confirme le bug sur iPad uniquement sur:


    - iOS 8.0 (ne semble pas rentrer dans le completion block !)


    - iOS 7.1 (rentre dans le block mais n'affiche rien...)


    Pas de plantages.

  • AliGatorAliGator Membre, Modérateur
    Oui mais ce bug là  sur iOS8 si tu utilises avec UIAlertView / UIActionSheet tu l'as aussi non ? Il vient d'Apple pas de moi.
  • muqaddarmuqaddar Administrateur


    Oui mais ce bug là  sur iOS8 si tu utilises avec UIAlertView / UIActionSheet tu l'as aussi non ? Il vient d'Apple pas de moi.




     


    Oui, je le retrouve avec UIActionSheet.

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