ios 检查 UIAlertView 是否显示

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2528929/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 17:04:12  来源:igfitidea点击:

Check if a UIAlertView is showing

iosiphoneobjective-cuialertview

提问by Ricibald

I have a method that posts HTTP data and displays a UIAlertView if there is an error. If I have multiple HTTP post I will show multiple UIAlertView for every error.

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

I want to show a UIAlertView only if is not showing other UIAlertView. How can I determine this?

仅当不显示其他 UIAlertView 时,我才想显示 UIAlertView。我如何确定这一点?

回答by Koen

Why not just check the visible property, maintained by the UIAlertView class?

为什么不检查 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];
}

回答by Chip Coons

On the object that calls set an ivar before invoking the show method on your 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];
}

...

Then in your delegate method for the alert manage setting your flag ivar to no:

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

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

If you want the alerts to show sequentially, I would post notifications to add each message to a queue and then only take a message off the queue after an alert is dismissed.

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

回答by kennytm

If you can control the other alert views, check the visibleproperty for each of them.

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



In iOS 6 or before, when an alert appears, it will be moved to a _UIAlertOverlayWindow. Therefore, a pretty fragile method is to iterate through all windows and check if there's any UIAlertView subviews.

在 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;

This is undocumented as it depends on internal view hierarchy, although Apple cannot complain about this. A more reliable but even more undocumented method is to check if [_UIAlertManager visibleAlert]is nil.

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

These methods can't check if a UIAlertView from SpringBoard is shown.

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

回答by Javen.Yang

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

回答by damian

Another option that works across the entire app and doesn't involve walking the view stack is to subclass UIAlertViewto MyUIAlertView, add a static (class) variable BOOL alertIsShowing, and override the -(void)showselector.

横跨整个应用的工作方式,并不涉及行走视图栈的另一个选项是子类UIAlertViewMyUIAlertView添加一个静态(类)变量BOOL alertIsShowing,并覆盖-(void)show选择。

In your overridden showselector, check the alertIsShowingvariable. If it's YESthen try again after a delay (use dispatch_afteror set an NSTimer). If it's NO, go ahead and call [super show]and assign YESto alertIsShowing; when the alert view is hidden, set alertIsShowingback to NO(you'll need to be clever about handling the delegate).

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

Finally, go through and replace all UIAlertViewinstances with MyUIAlertView.

最后,通过并替换所有UIAlertView实例MyUIAlertView

回答by Manab Kumar Mal

I think it will work:

我认为它会起作用:

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

回答by Morgan

Swift:

迅速:

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

回答by Jemythehigh

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

回答by Pach

+ (BOOL)checkAlertExist {

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

回答by kgaidis

Some notes on my quest to find the UIAlertView in the view hierarchy:

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

I tried to loop through all of the [UIApplication sharedApplication].windowsview's recursively but couldn't find anything.

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

The windowsproperty of UIApplicationdocs states the following:

docs的windows属性UIApplication说明如下:

This property contains the UIWindow objects currently associated with the app. This list does not include windows created and managed by the system, such as the window used to display the status bar.

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

So this made me realize that the UIWindowwhere UIAlertViewcould be located is not even presented to us.

因此,这让我意识到,UIWindow这里UIAlertView可能位于甚至没有呈现在我们面前。

HOWEVER, there is also a property on UIApplicationcalled keyWindow. Upon looping through that, I found private classes that would compose an alert view:

但是,也有一个UIApplication名为的属性keyWindow。在循环遍历之后,我找到了可以组成警报视图的私有类:

On iOS 7: _UIModalItemHostingWindow, _UIModalItemAlertContentView, _UIBackdropEffectViewetc.

在iOS 7: ,,等。_UIModalItemHostingWindow_UIModalItemAlertContentView_UIBackdropEffectView

On iOS 8: _UIAlertControllerActionView, _UIAlertControllerShadowedScrollView, _UIBackdropViewetc.

在iOS 8: ,,等。_UIAlertControllerActionView_UIAlertControllerShadowedScrollView_UIBackdropView

I could not find the UIAlertViewthat I presented, but rather, a bunch of classes that compose it internally. So to answer the original question, you can probably use the keyWindowproperty and see if you notice these classes, but your app could get rejected for trying to check for private classes.

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

For folks using, the newer, UIAlertControlleravailable for iOS 8 could get the reference to it using: [UIApplication sharedApplication].keyWindow.rootViewController.presentedViewController.

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