How to present UIAlertController when not in a view controller?

前端 未结 30 3130
庸人自扰
庸人自扰 2020-11-22 06:21

Scenario: The user taps on a button on a view controller. The view controller is the topmost (obviously) in the navigation stack. The tap invokes a utility class method call

30条回答
  •  长情又很酷
    2020-11-22 06:57

    In addition to great answers given (agilityvision, adib, malhal). To reach queueing behaviour like in good old UIAlertViews (avoid alert windows overlap), use this block to observe window level availability:

    @interface UIWindow (WLWindowLevel)
    
    + (void)notifyWindowLevelIsAvailable:(UIWindowLevel)level withBlock:(void (^)())block;
    
    @end
    
    @implementation UIWindow (WLWindowLevel)
    
    + (void)notifyWindowLevelIsAvailable:(UIWindowLevel)level withBlock:(void (^)())block {
        UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow;
        if (keyWindow.windowLevel == level) {
            // window level is occupied, listen for windows to hide
            id observer;
            observer = [[NSNotificationCenter defaultCenter] addObserverForName:UIWindowDidBecomeHiddenNotification object:keyWindow queue:nil usingBlock:^(NSNotification *note) {
                [[NSNotificationCenter defaultCenter] removeObserver:observer];
                [self notifyWindowLevelIsAvailable:level withBlock:block]; // recursive retry
            }];
    
        } else {
            block(); // window level is available
        }
    }
    
    @end
    

    Complete example:

    [UIWindow notifyWindowLevelIsAvailable:UIWindowLevelAlert withBlock:^{
        UIWindow *alertWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
        alertWindow.windowLevel = UIWindowLevelAlert;
        alertWindow.rootViewController = [UIViewController new];
        [alertWindow makeKeyAndVisible];
    
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Alert" message:nil preferredStyle:UIAlertControllerStyleAlert];
        [alertController addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
            alertWindow.hidden = YES;
        }]];
    
        [alertWindow.rootViewController presentViewController:alertController animated:YES completion:nil];
    }];
    

    This will allow you to avoid alert windows overlap. Same method can be used to separate and put in queue view controllers for any number of window layers.

提交回复
热议问题