Sous-classment UIAlertView

Je tente de sous-classr UIAlertView pour mieux gérer les états d'erreur dans mon application. Le problème est avec le paramètre otherButtonTitles terminé, quand je crée ma sous-class, il ne prend que la première string de la list plutôt que toutes les strings

+ (ErrorAlertView *)displayErrorAlertViewWithTitle:(NSSsortingng *)title message:(NSSsortingng *)message delegate:(id<UIAlertViewDelegate>)delegate errorDelegate:(id<ErrorAlertViewDelegate>)errorDelegate cancelButtonTitle:(NSSsortingng *)cancelButtonTitle displayNow:(BOOL)displayNow tag:(NSUInteger)tag otherButtonTitles:(NSSsortingng *)otherButtonTitles, ...; { ErrorAlertView *errorAlertView = [[ErrorAlertView alloc] initWithTitle:title message:message delegate:delegate cancelButtonTitle:cancelButtonTitle otherButtonTitles:otherButtonTitles, nil]; errorAlertView.errorDelegate = errorDelegate; errorAlertView.tag = tag; if (displayNow) { [errorAlertView show]; } return [errorAlertView autorelease]; } 

Si je fais l'appel suivant la méthode ci-dessus:

 [ErrorAlertView displayErrorAlertViewWithTitle:[self noInternetConnectionAlertViewTitle] message:[self noInternetConnectionAlertViewMessage] delegate:self errorDelegate:errorDelegate cancelButtonTitle:@"OK" displayNow:YES tag:ErrorAlertTagInternetConnectionError @"Try again",@"Setting", nil]; 

L'UIAlertView est affiché avec seulement le button @ "Try again" affiché.

Vous ne pouvez pas envoyer un set de parameters variables comme ça.

Quand j'ai sous-classé UIAlertView, j'ai fait ceci:

 va_list args; va_start(args, otherButtonTitles); for (NSSsortingng *anOtherButtonTitle = otherButtonTitles; anOtherButtonTitle != nil; anOtherButtonTitle = va_arg(args, NSSsortingng*)) { [self addButtonWithTitle:anOtherButtonTitle]; } 

Vous pouvez également créer une variante de votre fonction qui accepte une list va_list en tant que paramètre (unique), puis exécute le code ci-dessus.

Généralement, lors de l'écriture d'une fonction variadique, vous devez inclure une alternative pour gérer cette éventualité. Apple fournit la méthode addButtonWithTitle: dans ce cas.

À partir de la reference de class UIAlertView

Notes de sous-classment

La class UIAlertView est destinée à être utilisée telle quelle et ne supporte pas les sous-classs. La hiérarchie de vue de cette class est privée et ne doit pas être modifiée.

Il y a, cependant, beaucoup d'autres implémentations de vue d'alerte que vous pourriez find utiles, publiées ici sur CocoaControls .

Au lieu de sous-classr UIAlertView, je préfère créer des classs simples qui ont typiquement une méthode show qui prend un paramètre delegate. Le protocole délégué a alors des methods expressives qui correspondent aux options disponibles.

Bien que cette approche se traduise par plus de fonctions déléguées que l'approche typique de délégué de vue d'alerte, je pense que cela rend le code beaucoup plus lisible.

Le code ressemble généralement à ceci (Swift):

 @objc protocol DeleteUniverseAlertViewDelegate { func deleteUniverseAlertViewDidConfirmDelete(view: DeleteUniverseAlertView) } class DeleteUniverseAlertView : NSObject, UIAlertViewDelegate { private weak var delegate: DeleteUniverseAlertViewDelegate? = nil class func showWithDelegate(delegate: DeleteUniverseAlertViewDelegate) -> DeleteUniverseAlertView { let view = DeleteUniverseAlertView() view.delegate = delegate UIAlertView(title: "Delete universe?", message: "Are you really, really sure about this?", delegate: view, cancelButtonTitle: "Cancel", otherButtonTitles: "Yes, delete!").show() return view } func alertView(alertView: UIAlertView, clickedButtonAtIndex buttonIndex: Int) { if (buttonIndex > 0) { delegate?.deleteUniverseAlertViewDidConfirmDelete(self) } } } 

Lorsque vous devez ensuite afficher cette alerte, implémentez simplement le protocole et affichez l'alerte personnalisée comme ceci (n'oubliez pas de conserver une reference forte à la vue d'alerte):

 deleteAlert = DeletePlaceAlertView.showWithDelegate(self)