Question

J'ai une classe Utils qui affiche UIAlertView lorsque certaines notifications sont déclenchées.Existe-t-il un moyen de supprimer les UIAlertViews ouvertes avant d'en afficher un nouveau?

Actuellement, je fais cela lorsque l'application entre en arrière-plan en utilisant

[self checkViews:application.windows];

sur applicationDidEnterBackground

- (void)checkViews:(NSArray *)subviews {
    Class AVClass = [UIAlertView class];
    Class ASClass = [UIActionSheet class];
    for (UIView * subview in subviews){
        if ([subview isKindOfClass:AVClass]){
            [(UIAlertView *)subview dismissWithClickedButtonIndex:[(UIAlertView *)subview cancelButtonIndex] animated:NO];
        } else if ([subview isKindOfClass:ASClass]){
            [(UIActionSheet *)subview dismissWithClickedButtonIndex:[(UIActionSheet *)subview cancelButtonIndex] animated:NO];
        } else {
            [self checkViews:subview.subviews];
        }
    }
}

Cela facilite la tâche sur applicationDidEnterBackground car je peux utiliser application.windows

Puis-je utiliser AppDelegate ou quelque chose de similaire pour obtenir toutes les vues, les parcourir en boucle et ignorer les UIAlertViews?

Était-ce utile?

La solution

for (UIWindow* window in [UIApplication sharedApplication].windows) {
  NSArray* subviews = window.subviews;
  if ([subviews count] > 0)
    if ([[subviews objectAtIndex:0] isKindOfClass:[UIAlertView class]])
      [(UIAlertView *)[subviews objectAtIndex:0] dismissWithClickedButtonIndex:[(UIAlertView *)[subviews objectAtIndex:0] cancelButtonIndex] animated:NO];
}

Autres conseils

Version compatible iOS6:

for (UIWindow* w in UIApplication.sharedApplication.windows)
    for (NSObject* o in w.subviews)
        if ([o isKindOfClass:UIAlertView.class])
            [(UIAlertView*)o dismissWithClickedButtonIndex:[(UIAlertView*)o cancelButtonIndex] animated:YES];

Version compatible iOS7:

J'ai créé une interface de catégorie qui stocke toutes les instances dans la méthode init.

Je sais que c'est une manière très inefficace.

#import <objc/runtime.h>
#import <objc/message.h>

@interface UIAlertView(EnumView)

+ (void)startInstanceMonitor;
+ (void)stopInstanceMonitor;
+ (void)dismissAll;
@end

@implementation UIAlertView(EnumView)
static BOOL _isInstanceMonitorStarted = NO;

+ (NSMutableArray *)instances
{
    static NSMutableArray *array = nil;
    if (array == nil)
        array = [NSMutableArray array];

    return array;
}


- (void)_newInit
{
    [[UIAlertView instances] addObject:[NSValue valueWithNonretainedObject:self]];
    [self _oldInit];
}

- (void)_oldInit
{
    // dummy method for storing original init IMP.
}

- (void)_newDealloc
{
    [[UIAlertView instances] removeObject:[NSValue valueWithNonretainedObject:self]];
    [self _oldDealloc];

}
- (void)_oldDealloc
{
    // dummy method for storing original dealloc IMP.
}

static void replaceMethod(Class c, SEL old, SEL new)
{
    Method newMethod = class_getInstanceMethod(c, new);
    class_replaceMethod(c, old, method_getImplementation(newMethod), method_getTypeEncoding(newMethod));
}

+ (void)startInstanceMonitor
{
    if (!_isInstanceMonitorStarted) {
        _isInstanceMonitorStarted = YES;
        replaceMethod(UIAlertView.class, @selector(_oldInit), @selector(init));
        replaceMethod(UIAlertView.class, @selector(init), @selector(_newInit));

        replaceMethod(UIAlertView.class, @selector(_oldDealloc), NSSelectorFromString(@"dealloc"));
        replaceMethod(UIAlertView.class, NSSelectorFromString(@"dealloc"), @selector(_newDealloc));
    }
}

+ (void)stopInstanceMonitor
{
    if (_isInstanceMonitorStarted) {
        _isInstanceMonitorStarted = NO;
        replaceMethod(UIAlertView.class, @selector(init), @selector(_oldInit));
        replaceMethod(UIAlertView.class, NSSelectorFromString(@"dealloc"), @selector(_oldDealloc));
    }
}

+ (void)dismissAll
{
    for (NSValue *value in [UIAlertView instances]) {
        UIAlertView *view = [value nonretainedObjectValue];

        if ([view isVisible]) {
            [view dismissWithClickedButtonIndex:view.cancelButtonIndex animated:NO];
        }
    }
}
@end

Démarrez la surveillance de l'instance avant d'utiliser UIAlertView.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
   //...  
   //...

    [UIAlertView startInstanceMonitor];

    return YES;
}

Appelez "Ignorer tout" avant d'en afficher un autre.

[UIAlertView dismissAll];

Il est préférable d'utiliser un modèle singleton si vous pouvez contrôler toutes les UIAlertViews.

Mais dans mon cas, j'ai besoin de ce code pour fermer la boîte de dialogue d'alerte javascript dans une UIWebView.

Puisque UIAlertView est obsolète dans iOS8 au profit de UIAlertController (qui est un UIViewController, présenté de manière modale), vous ne pouvez pas prérégler 2 alertes en même temps (à partir du même viewController au moins).La deuxième alerte ne sera tout simplement pas présentée.

Je voulais émuler partiellement le comportement de UIAlertView, ainsi qu'empêcher d'afficher plusieurs alertes à la fois.Ci-dessous est ma solution, qui utilise le rootViewController de window pour présenter les alertes (généralement, c'est le contrôleur de navigation d'appDelegate).J'ai déclaré cela dans AppDelegate, mais vous pouvez le placer où vous le souhaitez.

Si vous rencontrez des problèmes lors de son utilisation, veuillez le signaler ici dans les commentaires.

@interface UIViewController (UIAlertController)

// these are made class methods, just for shorter semantics. In reality, alertControllers
// will be presented by window's rootViewController (appdelegate.navigationController)
+ (UIAlertController *)presentAlertWithTitle:(NSString *)title
                                     message:(NSString *)message
                           cancelButtonTitle:(NSString *)cancelButtonTitle
                           otherButtonTitles:(NSArray *)otherButtonTitles
                                     handler:(void (^)(NSInteger buttonIndex))block;
+ (UIAlertController *)presentAlertWithTitle:(NSString *)title
                                     message:(NSString *)message
                           cancelButtonTitle:(NSString *)cancelButtonTitle;

@end

@implementation UIViewController (UIAlertController)

+ (UIAlertController *)presentAlertWithTitle:(NSString *)title
                                     message:(NSString *)message
                           cancelButtonTitle:(NSString *)cancelButtonTitle
{
    return [self presentAlertWithTitle:title message:message cancelButtonTitle:cancelButtonTitle
                     otherButtonTitles:nil handler:nil];
}
+ (UIAlertController *)presentAlertWithTitle:(NSString *)title
                                     message:(NSString *)message
                           cancelButtonTitle:(NSString *)cancelButtonTitle
                           otherButtonTitles:(NSArray *)otherButtonTitles
                                     handler:(void (^)(NSInteger buttonIndex))block
{
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:message
                                                            preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:cancelButtonTitle style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
        if (block)
            block(0);
    }];
    [alert addAction:cancelAction];
    [otherButtonTitles enumerateObjectsUsingBlock:^(NSString *title, NSUInteger idx, BOOL *stop) {
        UIAlertAction *action = [UIAlertAction actionWithTitle:title style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
            if (block)
                block(idx + 1); // 0 is cancel
        }];
        [alert addAction:action];
    }];

    id<UIApplicationDelegate> appDelegate = [[UIApplication sharedApplication] delegate];
    UIViewController *rootViewController = appDelegate.window.rootViewController;
    if (rootViewController.presentedViewController) {
        [rootViewController dismissViewControllerAnimated:NO completion:^{
            [rootViewController presentViewController:alert animated:YES completion:nil];
        }];
    } else {
        [rootViewController presentViewController:alert animated:YES completion:nil];
    }
    return alert;
}

@end
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top