UIAlertViewEx et UIActionSheetEx (blocks)
AliGator
Membre, Modérateur
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 :
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 ? /biggrin.png' class='bbc_emoticon' alt=':D' />
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'extéieur du block<br />
<br />
[UIAlertViewEx showAlertWithTitle:@"Confirmation"<br />
message:[NSString stringWithFormat:@"Do something with object %@?",[obj description]]<br />
cancelButton:@"No"<br />
okButton:@"Yes"<br />
onButtonTapped:^(UIAlertViewEx* alert, NSInteger buttonIndex)<br />
{<br />
NSLog(@"button tapped: %d",buttonIndex);<br />
<br />
if (buttonIndex == alert.cancelButtonIndex) {<br />
NSLog(@"Cancel");<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 ? /biggrin.png' class='bbc_emoticon' alt=':D' />
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
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...
je suis moins "fan", pour la lisibilité du block je préfère le passer en argument.
En fait, c'est que pour iOS. :P
Tu parles de MacOS 10.6 par rapport au simulateur ?
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
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.
Peut-être un travail pas trop compliqué à faire pour faire soit hériter de NSAlertView soit de UIAlertView en analysant le contexte + macro ?
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 ^^
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 !
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)
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 : 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.
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
Merci Draken et AliGator pour les éclaircissements, je pense avoir bien compris la subtilité sur le scope du block.
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...
Du grand art. Je réitère mes propos.
Ni dans iOS 5 donc ? (pas encore téléchargé)
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 ?
self.view est la vue principale du VC... je vois pas ce que je peux faire de plus ?
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 !
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.
Oui, je le retrouve avec UIActionSheet.