iPhone SDK:检查是否显示UIAlertView

我有一个方法,张贴HTTP数据,并显示一个UIAlertView如果有错误。 如果我有多个HTTP发布,我会为每个错误显示多个UIAlertView。

如果不显示其他UIAlertView,我只想显示一个UIAlertView。 我怎样才能确定这一点?

在呼叫的对象上,在调用UIAlertView的show方法之前设置一个ivar。

... if (!self.alertShowing) { theAlert = [[UIAlertView alloc] initWithTitle:title message:details delegate:self cancelButtonTitle:nil otherButtonTitles:@"Okay", nil]; self.alertShowing = YES; [theAlert show]; } ... 

然后在你的代理方法警告pipe理设置你的国旗伊娃不:

 - (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex { ... self.alertShowing = NO; } 

如果您希望按顺序显示警报,我会发布通知将每条消息添加到队列中,然后在警报解除后仅从队列中取消消息。

为什么不只是检查由UIAlertView类维护的可视属性?

 if (_alert) //alert is a retained property { self.alert = [[[UIAlertView alloc] initWithTitle:@"Your Title" message:@"Your message" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK"] autorelease]; } if (!_alert.visible) { [_alert show]; } 

如果您可以控制其他警报视图,请检查每个视图的visible属性。


在iOS 6或之前,当出现警报时,它将被移动到_UIAlertOverlayWindow。 因此,一个非常脆弱的方法是遍历所有窗口,并检查是否有任何UIAlertView子视图。

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

这是无证的,因为它取决于内部视图层次,虽然苹果不能抱怨这一点。 一个更可靠,但更没有logging的方法是检查[_UIAlertManager visibleAlert]是否为零 。

这些方法不能检查是否显示来自SpringBoard的UIAlertView。

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

另一个在整个应用程序中工作的选项,并不涉及走视图堆栈是将UIAlertView MyUIAlertViewMyUIAlertView ,添加一个静态(类)variablesBOOL alertIsShowing ,并覆盖-(void)showselect器。

在重写的showselect器中,检查alertIsShowingvariables。 如果是YES则延迟后再试(使用dispatch_after或设置NSTimer )。 如果不是,则继续调用[super show]并指定YESalertIsShowing ; 当alert视图被隐藏时,将alertIsShowing设置回NO (你需要聪明的处理委托)。

最后,通过MyUIAlertView来replace所有的UIAlertView实例。

迅速:

 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) } } 

我认为这将起作用:

 -(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 } 
 // 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 } 

关于我在查看层次结构中查找UIAlertView的一些注意事项:

我试图循环遍历所有[UIApplication sharedApplication].windows视图的recursion,但找不到任何东西。

UIApplication文档的windows属性声明如下:

该属性包含当前与应用程序关联的UIWindow对象。 该列表不包括由系统创build和pipe理的窗口,例如用于显示状态栏的窗口。

所以这让我意识到UIAlertView所在的UIWindow甚至没有呈现给我们。

但是,在UIApplication上也有一个名为keyWindow的属性。 通过循环,我发现私人类将构成一个警报视图:

在iOS 7上: _UIModalItemHostingWindow_UIModalItemAlertContentView_UIBackdropEffectView

在iOS 8上: _UIAlertControllerActionView_UIAlertControllerShadowedScrollView_UIBackdropView

我无法find我提出的UIAlertView ,而是一堆内部组成的类。 因此,要回答原来的问题 ,你可以使用keyWindow属性,看看你是否注意到这些类,但是你的应用程序可能会因为试图检查私有类而被拒绝。

对于UIAlertController来说,较新的iOS 8可用的UIAlertController可以使用: [UIApplication sharedApplication].keyWindow.rootViewController.presentedViewController

 + (BOOL)checkAlertExist { for (UIWindow* window in [UIApplication sharedApplication].windows) { if ([window.rootViewController.presentedViewController isKindOfClass:[UIAlertController class]]) { return YES; } } return NO; }