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
MyUIAlertView
到MyUIAlertView
,添加一个静态(类)variablesBOOL alertIsShowing
,并覆盖-(void)show
select器。
在重写的show
select器中,检查alertIsShowing
variables。 如果是YES
则延迟后再试(使用dispatch_after
或设置NSTimer
)。 如果不是,则继续调用[super show]
并指定YES
来alertIsShowing
; 当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; }