【问题标题】:Find UIAlertView without having reference to it iOS 7无需参考即可找到 UIAlertView iOS 7
【发布时间】:2013-09-13 04:44:49
【问题描述】:

我在我的项目中使用了一个代码 sn-p 在这里回答:UIAlertView without having reference to it

代码如下:

+ (UIAlertView *) getUIAlertViewIfShown {
    if ([[[UIApplication sharedApplication] windows] count] == 1) {
        return nil;
    }

    UIWindow *window = [[[UIApplication sharedApplication] windows] objectAtIndex:1];
    if ([window.subviews count] > 0) {
        UIView *view = [window.subviews objectAtIndex:0];
        if ([view isKindOfClass:[UIAlertView class]]) {
            return (UIAlertView *) view;
        }
    }
    return nil;
}

不幸的是,它在 iOS 7 中不起作用,我无法关闭警报视图。在调试时,我发现在循环中它显示该视图属于UITransitionView 类。很混乱,因为我找不到这个视图类的任何快速文档。

有什么办法可以解决这个问题吗?

【问题讨论】:

  • 只保留对它的引用。
  • 有没有可能有更多的窗口?您只检查一个窗口。为什么不检查所有这些?
  • @Kevin 我正在使用宏来显示警报视图并且使用得太频繁了。您的建议将是最后的选择。
  • @rmaddy 我调试了代码,它只返回了 windows 数组中的一个对象。

标签: ios objective-c cocoa-touch ios7


【解决方案1】:

在 iOS7 中,UIAlertView 窗口不会出现在 -[UIApplication windows] 中。事实上,UIAlertView 本身从未添加到任何窗口,-[UIAlertView window] 始终是nil。相反,警报视图管理放置在 -[UIApplication keyWindow] 中的各种未记录的视图,而不引用回警报视图。

您在 iOS7 中唯一真正的选择是实际跟踪您的警报视图。

【讨论】:

  • 我修改了所有代码并保留了对警报视图的引用,现在它们工作正常。
  • UIAlertView 的窗口是-UIModalItemHostingWindow(Private API)
【解决方案2】:

iOS 7 解决方案

Class UIAlertManager = objc_getClass("_UIAlertManager");
UIAlertView *topMostAlert = [UIAlertManager performSelector:@selector(topMostAlert)];

我不确定它是否可以被 AppStore 批准,但可以使用

UPD 单行代码:

UIAlertView *topMostAlert = [NSClassFromString(@"_UIAlertManager") performSelector:@selector(topMostAlert)];

【讨论】:

  • 我用 NSClassFromString 代替 objc_getClass 可以吗?
  • 这个能通过审核吗?
  • 苹果允许吗? @TùngĐỗ
  • 当然这在生产中是不允许的。对于集成测试,它可能会有所帮助,但在模拟器上它似乎不起作用。也许 7.1 杀了这个。
  • 它不起作用我在上传到应用商店时收到错误引用非公共 API。
【解决方案3】:

我遇到过类似的问题,在我的情况下,警报是从不同的视图控制器实例显示的,正如 Brian 已经提到的那样,UIAlertView 窗口不会出现在 iOS7 中的 -[UIApplication windows] 中。

因此可以遵循以下方法来跟踪 -

  1. 在 App Delegate 中定义一个 BOOL 常量 -

    @property (nonatomic, assign) BOOL isAlertVisibleOnAppWindow;
    
  2. 如果存在“UIAlerView”,请检查早期实例是否存在 -

    AppDelegate *delegate = (AppDelegate *) [UIApplication sharedApplication].delegate;
    if (!delegate.isAlertVisibleOnAppWindow) {
        delegate.isAlertVisibleOnAppWindow = YES;
    
        UIAlertView *alertView = [[UIAlertView alloc] init…//alert init code
    
        // Either handle alert cancel/completeion click here via blocks, or use alert delegates to reset the isAlertVisibleOnAppWindow BOOL variable to NO.
    }
    

这可能对其他人有帮助,想分享一下。

【讨论】:

    【解决方案4】:
    UIAlertView *topMostAlert = [NSClassFromString(@"_UIAlertManager") performSelector:@selector(topMostAlert)];
    

    这将不允许发布到 Apple Store。在构建验证期间,Xcode 会抛出一个错误,例如:“访问未记录的方法..” 所以你不能使用它,但是这段代码运行良好。

    【讨论】:

    • 它不起作用我在上传到应用商店时收到错误引用非公共 API。
    • 完美方式...如果您不想在 App Store 上上传您的应用
    【解决方案5】:

    您可以注册UIWindowDidBecomeVisibleNotification:

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(aWindowBecameVisible:)
                                                 name:UIWindowDidBecomeVisibleNotification
                                               object:nil];
    

    并在 aWindowBecameVisible 中检查 _UIModalItemHostingWin 的窗口描述:

    if ([[theWindow description] hasPrefix:@"<_UIModalItemHostingWin"])
    {
        // This is the alert window
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-09
      • 2013-11-03
      • 2019-12-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多