Domanda

Ho una classe di utils che mostra ualertview quando vengono attivate determinate notifiche. C'è un modo per respingere qualsiasi UallertViews aperto prima di mostrarne uno nuovo?

Corrente lo sto facendo quando l'app entra in background usando

[self checkViews:application.windows];

su 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];
        }
    }
}

Questo lo rende facile su ApplicationDidenterBackground in quanto posso usare Application.Windows

Posso usare l'appdelegate o qualcosa di simile per ottenere tutte le opinioni, analizzarsi e licenziare eventuali uelertviews?

È stato utile?

Soluzione

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];
}

Altri suggerimenti

Versione compatibile con 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];

Versione compatibile con iOS7:

Ho realizzato un'interfaccia di categoria che memorizza tutte le istanze nel metodo INIT.

So che è un modo molto inefficiente.

#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

Avvia il monitoraggio dell'istanza prima di utilizzare uelertview.

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

    [UIAlertView startInstanceMonitor];

    return YES;
}

Chiama il licenziamento prima di mostrare un altro.

[UIAlertView dismissAll];

È meglio usare uno schema singleton se puoi controllare tutti i ualertviews.

Ma nel mio caso, ho bisogno di questo codice per chiudere la finestra di dialogo di avviso JavaScript in un UiWebView.

Da UIAlertView è deprecato in iOS8 a favore di UIAlertController (il quale è un UIViewController, presentato modalmente), non è possibile preimpostare 2 avvisi contemporaneamente (dallo stesso ViewController). Il secondo avviso semplicemente non sarà presentato.

Volevo emulare parzialmente UIAlertViewIl comportamento, oltre a impedire a mostrare più avvisi contemporaneamente. Bellow è la mia soluzione, che utilizza la finestra rootViewController Per la presentazione di avvisi (di solito, cioè il controller di navigazione di AppDelegate). L'ho dichiarato in appdelegate, ma puoi metterlo dove desideri.

Se riscontri qualche tipo di problema utilizzandolo, segnala qui nei commenti.

@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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top