web-dev-qa-db-fra.com

Vérifiez si un UIAlertView s'affiche

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?

41
Ricibald

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.

53
Chip Coons
- (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;
}
9
Javen.Yang

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.

4
damian

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
}
4
Manab Kumar Mal

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)
    }
}
3
Morgan
+ (BOOL)checkAlertExist {

    for (UIWindow* window in [UIApplication sharedApplication].windows) {
        if ([window.rootViewController.presentedViewController isKindOfClass:[UIAlertController class]]) {
            return YES;
        }
    }
    return NO;
}
2
Pach
// 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
}
2
Jemythehigh

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 UIWindowUIAlertView 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.

1
kgaidis