Как решить: "keyWindow" устарела в iOS 13.0

Я использую Core Data с Cloud Kit, и поэтому должен проверять статус пользователя iCloud во время запуска приложения. В случае проблем я хочу выдать диалог пользователю, и я делаю это, используя UIApplication.shared.keyWindow?.rootViewController?.present(...) до сих пор.

В Xcode 11 beta 4 появилось новое сообщение об устаревании:

"keyWindow" устарело в iOS 13.0: его не следует использовать для приложений, которые поддерживают несколько сцен, поскольку оно возвращает ключевое окно для всех связанных сцен

Как мне представить диалог вместо этого?

Ответ 1

Это мое решение:

let keyWindow = UIApplication.shared.connectedScenes
        .filter({$0.activationState == .foregroundActive})
        .map({$0 as? UIWindowScene})
        .compactMap({$0})
        .first?.windows
        .filter({$0.isKeyWindow}).first

Использование, например:

keyWindow?.endEditing(true)

Ответ 2

Принятый ответ, хотя и гениальный, может быть слишком сложным. Вы можете получить точно такой же результат намного проще:

UIApplication.shared.windows.filter {$0.isKeyWindow}.first

Я также хотел бы предупредить, что к износу keyWindow не следует относиться слишком серьезно. Полное предупреждающее сообщение гласит:

"keyWindow" устарело в iOS 13.0: его не следует использовать для приложений, которые поддерживают несколько сцен, поскольку оно возвращает ключевое окно для всех связанных сцен

Так что, если вы не поддерживаете несколько окон на iPad, нет никаких сомнений в том, что вы будете продолжать и продолжать использовать keyWindow.

Ответ 3

Немного улучшив матовый отличный ответ, это еще проще, короче и элегантнее:

UIApplication.shared.windows.first { $0.isKeyWindow }

Ответ 4

В идеале, поскольку оно устарело, я бы посоветовал вам сохранить окно в SceneDelegate. Однако, если вам нужен временный обходной путь, вы можете создать фильтр и получить keyWindow, как показано ниже.

let window = UIApplication.shared.windows.filter {$0.isKeyWindow}.first

Ответ 5

Я не знаю, какие у тебя настройки. Но обычно это может помочь:

UIApplication.shared.windows[0].rootViewController.present(...)

Ответ 6

Для объективного решения C

+(UIWindow*)keyWindow
{
    UIWindow        *foundWindow = nil;
    NSArray         *windows = [[UIApplication sharedApplication]windows];
    for (UIWindow   *window in windows) {
        if (window.isKeyWindow) {
            foundWindow = window;
            break;
        }
    }
    return foundWindow;
}