解决适配 iOS13 后 UIMenuController 不能正常弹出的问题

Feb 02, 2020 • 预计阅读时间 1 分钟

在 iOS13 以前,大家的 Window 都是在 AppDelegate 里进行初始化:

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        window = UIWindow(frame: UIScreen.main.bounds)
        if let window = window {
            window.rootViewController = MainViewController()
            window.makeKeyAndVisible()
        }
    }
}

到了 iOS13 增加了多窗口模式,Window 的初始化由原来的 AppDelegate 改到了新的 SceneDelegate

为了兼容之前的系统,Window 的初始化一般都这么写:

@available(iOS 13.0, *)
class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let windowScene = (scene as? UIWindowScene) else { return }

        if let shardWindow = UIApplication.shared.delegate?.window {
            window = shardWindow
            window?.windowScene = windowScene
            window?.makeKeyAndVisible()
        }
    }
}

运行的很好,看似没有什么问题。

很快你会发现,所有的 UIMenuController 都不能正常显示出来了。

原因是因为 Window 并不是 keyWindow,UIMenuController 只能在 keyWindow 上显示,所以系统菜单无法显示出来。

造成这个问题的原因是因为在 AppDelegate 过早的调用了 makeKeyAndVisible

然后在 SceneDelegate 里连接上 windowScene 后再调用 makeKeyAndVisible 是无效的。

这个问题从 iOS 13.0 到目前(iOS 13.3.1)都存在,看来是系统特性而不是 BUG。

解决方案很简单,iOS 13 下延迟调用 makeKeyAndVisible 就行了。

AppDelegate 里调整一下,如果是 iOS 13 就延迟设置为 keyWindow:

if let window = window {
    window.rootViewController = MainViewController()

    if #available(iOS 13.0, *) {
        window.isHidden = false
    } else {
        window.makeKeyAndVisible()
    }
}

问题解决,希望能帮助遇到同样问题的同学早点脱坑。

iOS
版权声明:如果转发请带上本文链接和注明来源。

lvv.me

iOS/macOS Developer

iOS 显示模态 VC 时保持状态栏的风格不变

Git 的 core.autocrlf 设置说明