Найти UIAlertView без ссылки на него iOS 7

Я использовал фрагмент кода в моем проекте: UIAlertView без ссылки на него

Здесь код:

+ (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. Довольно сбивает с толку, потому что я не мог найти быстрой документации для этого класса представления.

Любые идеи, как я могу исправить эту проблему?

Ответ 1

В iOS7 окно UIAlertView не отображается в -[UIApplication windows]. Фактически, UIAlertView сам никогда не добавляется ни в какое окно, -[UIAlertView window] всегда nil. Вместо этого представление предупреждения управляет множеством недокументированных представлений, помещенных в -[UIApplication keyWindow] без ссылки на представление предупреждения.

Единственная реальная опция в iOS7 - фактически отслеживать ваши предупреждения.

Ответ 2

Решение iOS 7

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

Я не уверен, что он одобрен AppStore, но работает

Однострочный код UPD:

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

Ответ 3

Я столкнулся с аналогичной проблемой, и в моем случае предупреждения отображаются из разных экземпляров контроллера вида, поскольку Брайан уже упомянул, что окно UIAlertView не отображается в [UIApplication windows] в iOS7.

Таким образом, чтобы отслеживать этот следующий подход, можно следовать -

  • Определите константу BOOL в App Delegate -

    @property (nonatomic, assign) BOOL isAlertVisibleOnAppWindow;
    
  • Где присутствует "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 выдает ошибку, например: "доступ к недокументированному методу". Поэтому вы не можете его использовать, однако этот код работает хорошо.

Ответ 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
}