J'ai une méthode qui publie des données HTTP et affiche un UIAlertView s'il y a une erreur. Si j'ai plusieurs publications HTTP, j'afficherai plusieurs UIAlertView pour chaque erreur.
Je souhaite afficher un UIAlertView uniquement s'il ne montre pas un autre UIAlertView. Comment puis-je déterminer cela?
Sur l'objet qui appelle, définissez un ivar avant d'appeler la méthode show sur votre UIAlertView.
...
if (!self.alertShowing) {
theAlert = [[UIAlertView alloc] initWithTitle:title message:details delegate:self cancelButtonTitle:nil otherButtonTitles:@"Okay", nil];
self.alertShowing = YES;
[theAlert show];
}
...
Ensuite, dans votre méthode déléguée pour l'alerte, définissez votre indicateur ivar sur non:
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
...
self.alertShowing = NO;
}
Si vous souhaitez que les alertes s'affichent séquentiellement, je publierais des notifications pour ajouter chaque message à une file d'attente, puis ne retirerais un message de la file d'attente qu'après le rejet d'une alerte.
- (BOOL)checkAlertExist {
for (UIWindow* window in [UIApplication sharedApplication].windows) {
NSArray* subviews = window.subviews;
if ([subviews count] > 0) {
for (id cc in subviews) {
if ([cc isKindOfClass:[UIAlertView class]]) {
return YES;
}
}
}
}
return NO;
}
Une autre option qui fonctionne sur l'ensemble de l'application et n'implique pas de parcourir la pile de vues consiste à sous-classer UIAlertView
à MyUIAlertView
, à ajouter une variable statique (classe) BOOL alertIsShowing
Et à remplacer le sélecteur -(void)show
.
Dans votre sélecteur show
substitué, vérifiez la variable alertIsShowing
. Si c'est YES
, essayez à nouveau après un délai (utilisez dispatch_after
Ou définissez un NSTimer
). Si c'est NO
, allez-y et appelez [super show]
Et affectez YES
à alertIsShowing
; lorsque la vue d'alerte est masquée, redéfinissez alertIsShowing
sur NO
(vous devrez être intelligent pour gérer le délégué).
Enfin, parcourez et remplacez toutes les instances de UIAlertView
par MyUIAlertView
.
Je pense que cela va fonctionner:
-(BOOL) doesAlertViewExist {
if ([[UIApplication sharedApplication].keyWindow isMemberOfClass:[UIWindow class]])
{
return NO;//AlertView does not exist on current window
}
return YES;//AlertView exist on current window
}
Rapide:
func showAlert(withTitle title: String, message: String, viewController: UIViewController) {
if viewController.presentedViewController == nil { // Prevent multiple alerts at the same time
let localizedTitle = NSLocalizedString(title, comment: "")
let localizedMessage = NSLocalizedString(message, comment: "")
let alert = UIAlertController(title: localizedTitle, message: localizedMessage, preferredStyle: .Alert)
let action = UIAlertAction(title: "OK", style: .Default, handler: nil)
alert.addAction(action)
viewController.presentViewController(alert, animated: true, completion: nil)
}
}
+ (BOOL)checkAlertExist {
for (UIWindow* window in [UIApplication sharedApplication].windows) {
if ([window.rootViewController.presentedViewController isKindOfClass:[UIAlertController class]]) {
return YES;
}
}
return NO;
}
// initialize default flag for alert... If alert is not open set isOpenAlert as NO
BOOL isAlertOpen;
isAlertOpen = NO;
if (isAlertOpen == NO) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Alert" message:@"Alert is Open" delegate:self cancelButtonTitle:@"Okay!!" otherButtonTitles: nil];
[alert show];
// Now set isAlertOpen to YES
isAlertOpen = YES;
}
else
{
//Do something
}
Quelques notes sur ma quête pour trouver le UIAlertView dans la hiérarchie des vues:
J'ai essayé de parcourir tous les [UIApplication sharedApplication].windows
la vue est récursive mais n'a rien trouvé.
La propriété windows
de UIApplication
docs indique ce qui suit:
Cette propriété contient les objets UIWindow actuellement associés à l'application. Cette liste n'inclut pas les fenêtres créées et gérées par le système, comme la fenêtre utilisée pour afficher la barre d'état.
Cela m'a donc fait réaliser que le UIWindow
où UIAlertView
pouvait être localisé ne nous est même pas présenté.
TOUTEFOIS, il y a aussi une propriété sur UIApplication
appelée keyWindow
. En parcourant cela, j'ai trouvé des classes privées qui composaient une vue d'alerte:
Sur iOS 7: _UIModalItemHostingWindow
, _UIModalItemAlertContentView
, _UIBackdropEffectView
etc.
Sur iOS 8: _UIAlertControllerActionView
, _UIAlertControllerShadowedScrollView
, _UIBackdropView
etc.
Je n'ai pas pu trouver le UIAlertView
que j'ai présenté, mais plutôt un tas de classes qui le composent en interne. Donc, pour répondre à la question d'origine, vous pouvez probablement utiliser la propriété keyWindow
et voir si vous remarquez ces classes, mais votre application pourrait être rejetée pour avoir essayé de rechercher des classes privées.
Pour les personnes utilisant, la plus récente, UIAlertController
disponible pour iOS 8 pourrait obtenir la référence en utilisant: [UIApplication sharedApplication].keyWindow.rootViewController.presentedViewController
.