如果已经显示警报,则显示 UIAlertController
Posted
技术标签:
【中文标题】如果已经显示警报,则显示 UIAlertController【英文标题】:Show UIAlertController if already showing an Alert 【发布时间】:2014-10-17 06:53:30 【问题描述】:旧版UIAlertView
和新版UIAlertController
的区别在于后者需要使用presentViewController:animated:completion:
呈现到特定的视图控制器上。这给我的用例带来了一个尴尬的问题:如果出现第二个视图控制器(例如由于网络连接失败而导致的错误对话框)时已经显示了UIAlertController
(例如评级对话框)怎么办。我经历过,在这种情况下,第二个 UIAlertController
只是没有显示。
编辑:目前我尝试显示警报,我不知道当前是否有任何显示。
你如何应对这种情况?
【问题讨论】:
[本帖][1]正确解释如何解决类似问题[1]:***.com/questions/21179922/… 其他线程中的解决方案脆弱丑陋,在ios8中可能会崩溃。 【参考方案1】:我找到了一种解决方法来找出我可以在哪个视图控制器上显示警报。我也贴出答案here:
@implementation UIViewController (visibleViewController)
- (UIViewController *)my_visibleViewController
if ([self isKindOfClass:[UINavigationController class]])
// do not use method visibleViewController as the presentedViewController could beingDismissed
return [[(UINavigationController *)self topViewController] my_visibleViewController];
if ([self isKindOfClass:[UITabBarController class]])
return [[(UITabBarController *)self selectedViewController] my_visibleViewController];
if (self.presentedViewController == nil || self.presentedViewController.isBeingDismissed)
return self;
return [self.presentedViewController my_visibleViewController];
@end
// To show a UIAlertController, present on the following viewcontroller:
UIViewController *visibleViewController = [[UIApplication sharedApplication].delegate.window.rootViewController my_visibleViewController];
【讨论】:
【参考方案2】:由于UIAlertController
本身就是UIViewController
,因此您可以在第一个UIAlertController
的基础上通过现有的呈现来呈现第二个UIAlertController
:
alertController.PresentViewController(alertController2, animated: true, completionHandler: null)
【讨论】:
问题是必须先找出最上面的viewcontroller。假设我不知道是否显示了 amy 警报或其他显示的视图控制器。 使用这个来获取***ViewController: private UIViewController GetTopPresentedViewController() UIViewController currentVC = this.viewController; while (true) UIViewController nextVC = currentVC.PresentedViewController; if (nextVC == null) return currentVC; currentVC = nextVC; 查看我的答案 - 不要忘记isBeingDismissed
标志。【参考方案3】:
当应用程序必须在窗口上显示一些警报时,此代码满足要求,并且在显示之前检查是否已经显示了任何其他 AlertController,如果已显示,则在出现的 Alertcontroller 上显示警报,否则在窗口上显示。
这里还有另一种选择,您可以根据需要对其进行优化。
func showAlert(message:String)
if let alert = self.checkIfAlertViewHasPresented()
alert.presentViewController(alertController, animated: true, completion: nil)
else
self.window?.rootViewController!.presentViewController(alertController, animated: true, completion: nil)
func checkIfAlertViewHasPresented() -> UIAlertController?
if var topController = UIApplication.sharedApplication().keyWindow?.rootViewController
while let presentedViewController = topController.presentedViewController
topController = presentedViewController
if topController is UIAlertController
return (topController as! UIAlertController)
else
return nil
return nil
【讨论】:
这不包括接受的答案中涵盖的一些特殊情况。 @fabb 同意你的看法。我在编写代码之前已经说明了该代码块满足的条件。如果一些新手开发人员在理解其他复杂情况时遇到问题,我认为我的答案是次要选择。 恕我直言,尤其是新手应该被教导正确做事,不要冒犯 @fabb 同意你的看法。我会在以后的答案中关注您的建议,稍后我将使用更优化的答案编辑我的答案。 :)【参考方案4】:这就是我正在使用的。这样,如果警报已经显示, 我更喜欢用户关闭它而不是应用程序。 因此,如果视图已经显示警报,我只需等待 5 秒再试一次。
我只是想补充一下,我没有测试太多,但它有效。(从我做的1个测试中),所以我希望我没有遗漏什么,因为我考虑了这个问题很长时间,并且这个解决方案听起来太简单了:)
-(void) alertUserWithTitle:(NSString*) title Message:(NSString*) message
UIAlertController* alert = [UIAlertController alertControllerWithTitle:title message:message
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) ];
[alert addAction:defaultAction];
if(self.presentedViewController == nil)
[self presentViewController:alert animated:YES completion:nil];
else
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void)
[self alertUserWithTitle:title Message:message];
);
【讨论】:
适用于某些用例。如果警报应该阻止进一步的用户交互,那就不太理想了。【参考方案5】:这是我在 Swift 3 中使用的一个解决方案。它是一个向用户显示警报的函数,如果您在用户解除警报之前多次调用它,它会将新的警报文本添加到警报中已经呈现。如果正在呈现其他视图,则不会出现警报。并非所有人都同意这种行为,但它适用于简单的情况。
extension UIViewController
func showAlert(_ msg: String, title: String = "")
if let currentAlert = self.presentedViewController as? UIAlertController
currentAlert.message = (currentAlert.message ?? "") + "\n\nUpdate:\(title): \(msg)"
return
// create the alert
let alert = UIAlertController(title: title, message: msg, preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))
// show the alert
self.present(alert, animated: true, completion: nil)
【讨论】:
以上是关于如果已经显示警报,则显示 UIAlertController的主要内容,如果未能解决你的问题,请参考以下文章