我有一个方法用于发布HTTP数据,并在出现错误时显示UIAlertView。如果我进行多个HTTP post,每次出现错误时都会显示多个UIAlertView。
我希望只有没有其他UIAlertView正在显示时才显示UIAlertView。如何确定这一点?
我有一个方法用于发布HTTP数据,并在出现错误时显示UIAlertView。如果我进行多个HTTP post,每次出现错误时都会显示多个UIAlertView。
我希望只有没有其他UIAlertView正在显示时才显示UIAlertView。如何确定这一点?
为什么不直接检查UIAlertView类维护的visible属性呢?
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];
}
在调用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];
}
...
然后在你的警告视图的委托方法中,将你的标记实例变量设为否:
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
...
self.alertShowing = NO;
}
如果您希望警报按顺序显示,我建议将通知发布到队列中以添加每条消息,然后只有在警报被取消后才从队列中取出一条消息。visible
属性,就像下面的答案一样。 - sam-w如果你可以控制其他警示框,检查每个警示框的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;
这是未记录在案的,因为它取决于内部视图层次结构,尽管苹果不会抱怨此事。更可靠但更不受记录的方法是检查[_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
,添加静态(类)变量BOOL alertIsShowing
并重写-(void)show
选择器。
在您重写的show
选择器中,检查alertIsShowing
变量。如果它是YES
,那么延迟一段时间后再尝试(使用dispatch_after
或设置NSTimer
)。如果是NO
,那么继续调用[super show]
并分配YES
给alertIsShowing
;当警报视图被隐藏时,将alertIsShowing
设置回NO
(您需要聪明地处理委托)。
最后,逐个替换所有UIAlertView
实例为MyUIAlertView
。
UIAlertController
- 如果你同时使用两者,我认为你需要跟踪两者)。最终我使用了一个计数器而不是布尔值。这样,如果您尝试同时显示两个警报,则不会在出现/消失方法与您的预期不同步时意外将布尔值设置为 false。 - garieSwift:
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
}
-(BOOL) doesAlertViewExist { return ![[UIApplication sharedApplication].keyWindow isMemberOfClass:[UIWindow class]]; }
- Popmedic// 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
}
+ (BOOL)checkAlertExist {
for (UIWindow* window in [UIApplication sharedApplication].windows) {
if ([window.rootViewController.presentedViewController isKindOfClass:[UIAlertController class]]) {
return YES;
}
}
return NO;
}
在寻找视图层次结构中的UIAlertView时,我有一些笔记:
我试图递归遍历所有[UIApplication sharedApplication].windows
视图,但是找不到任何东西。
UIApplication
文档中的windows
属性说明如下:
此属性包含当前与应用程序关联的UIWindow对象。 此列表不包括由系统创建和管理的窗口,例如用于显示状态栏的窗口。
这使我意识到,UIAlertView
可能位于的UIWindow
甚至没有呈现给我们。
然而,UIApplication
还有一个名为keyWindow
的属性。 在循环遍历该属性时,我发现了组成警报视图的私有类:
iOS 7上:_UIModalItemHostingWindow
,_UIModalItemAlertContentView
,_UIBackdropEffectView
等。
iOS 8上:_UIAlertControllerActionView
,_UIAlertControllerShadowedScrollView
,_UIBackdropView
等。
UIAlertView
,但是实际上,有一堆内部组成它的类。因此回答最初的问题,你可能可以使用keyWindow
属性并查看是否注意到这些类,但是尝试检查私有类可能会导致你的应用被拒绝。[UIApplication sharedApplication].keyWindow.rootViewController.presentedViewController
来获取对其的引用。