42

我有一个方法可以发布 HTTP 数据并在出现错误时显示 UIAlertView。如果我有多个 HTTP 帖子,我将为每个错误显示多个 UIAlertView。

我只想在不显示其他 UIAlertView 的情况下显示 UIAlertView。我怎样才能确定这一点?

4

10 回答 10

60

为什么不只检查由 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];
}
于 2012-04-19T12:55:39.213 回答
52

在调用 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];
}

...

然后在警报管理的委托方法中将标志 ivar 设置为 no:

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

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

于 2010-03-27T14:27:15.657 回答
26

如果您可以控制其他警报视图,请检查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;

这是未记录的,因为它取决于内部视图层次结构,尽管 Apple 不能抱怨这一点。一种更可靠但更无证的方法是检查是否[_UIAlertManager visibleAlert]为 nil

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

于 2010-03-27T14:49:06.437 回答
9
- (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;
}
于 2013-03-01T06:28:14.433 回答
4

另一个适用于整个应用程序且不涉及遍历视图堆栈的选项是子类化UIAlertViewMyUIAlertView,添加静态(类)变量BOOL alertIsShowing,并覆盖-(void)show选择器。

在覆盖show的选择器中,检查alertIsShowing变量。如果是,YES则在延迟后重试(使用dispatch_after或设置一个NSTimer)。如果是NO,请继续调用[super show]并分配YESalertIsShowing; 当警报视图被隐藏时,设置alertIsShowingNO(你需要聪明地处理委托)。

最后,遍历所有UIAlertView实例并将其替换为MyUIAlertView.

于 2013-10-03T09:24:35.003 回答
3

迅速:

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)
    }
}
于 2016-07-12T12:35:12.720 回答
3

我认为它会起作用:

-(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
}
于 2016-08-25T06:09:32.693 回答
2
// 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
}
于 2014-07-01T12:44:59.073 回答
2
+ (BOOL)checkAlertExist {

    for (UIWindow* window in [UIApplication sharedApplication].windows) {
        if ([window.rootViewController.presentedViewController isKindOfClass:[UIAlertController class]]) {
            return YES;
        }
    }
    return NO;
}
于 2016-03-23T16:14:57.243 回答
1

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

我试图[UIApplication sharedApplication].windows递归地遍历所有视图,但找不到任何东西。

docs的windows属性UIApplication说明如下:

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

所以这让我意识到,甚至没有向我们UIWindow展示UIAlertView可以定位的位置。

UIApplication但是,在called上也有一个属性keyWindow。通过循环,我发现了可以组成警报视图的私有类:

在 iOS 7 上:_UIModalItemHostingWindow、、_UIModalItemAlertContentView_UIBackdropEffectView

在 iOS 8 上:_UIAlertControllerActionView、、_UIAlertControllerShadowedScrollView_UIBackdropView

我找不到UIAlertView我提出的那个,而是一堆在内部组成它的类。因此,要回答最初的问题,您可能可以使用该keyWindow属性并查看是否注意到这些类,但您的应用程序可能会因为尝试检查私有类而被拒绝。

对于使用UIAlertControlleriOS 8 的较新版本的人来说,可以使用以下方式获得对它的引用: [UIApplication sharedApplication].keyWindow.rootViewController.presentedViewController.

于 2015-09-22T19:55:38.123 回答