7

UIScene连接多个场景时,我无法获取电流。

具体来说,我的应用程序(iOS 13)支持 iPad 上的多个窗口。当我有两个并排的窗口并访问应用程序连接的场景(使用UIApplication.shared.connectedScenes)时,它们都activationState设置为.foregroundActive. 但我实际上只与其中一个互动。

我在 stackoverflow 上找到了一些代码来检索当前的关键窗口(不记得是谁发布的),但正如你所见,它总是会返回两个窗口之一。

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

我是否缺少一些方法来确定与之交互的最后一个窗口,或者多个.foregroundActive状态是否是错误?

谢谢!

4

4 回答 4

2

虽然UIApplication.shared.keyWindow在 iOS 13.0 之后被 Apple 弃用,但似乎此属性可以帮助您在前景中有多个场景时通过以下方式找到活动的:

UIApplication.shared.keyWindow?.windowScene
于 2021-03-29T13:50:17.113 回答
2

我通过重构代码找到了解决问题的方法,现在我可以通过任何视图或视图控制器UIScene的属性访问当前的 s 窗口。window这样我就不再需要keyWindow了。

我认为两个相邻打开的窗口都有activationState .foregroundActive

如果有人需要,这两个扩展帮助我从应用程序的任何位置访问当前窗口:

extension UIViewController {
  var window: UIWindow? {
    return view.window
  }
}

extension UIScene {
  var window: UIWindow? {
    return (delegate as? SceneDelegate)?.window
  }
}

但是,如果您无法访问 a或UIView,问题仍然存在。例如,在不引用视图或场景的数据模型中。然后我看不到一种方法可以始终如一地访问用户正在与之交互的正确窗口。UIViewControllerUIScene

于 2019-08-29T09:37:02.990 回答
1

我在我的项目中使用这个扩展

// MARK: - Scene Delegate helpers

@available(iOS 13.0, *)
extension UIApplication {
    static var firstScene: UIScene? {
        UIApplication.shared.connectedScenes.first
    }

    static var firstSceneDelegate: SceneDelegate? {
        UIApplication.firstScene?.delegate as? SceneDelegate
    }

    static var firstWindowScene: UIWindowScene? {
        UIApplication.firstSceneDelegate?.windowScene
    }
}

// MARK: - Window Scene sugar

@available(iOS 13.0, *)
protocol WindowSceneDependable {
    var windowScene: UIWindowScene? { get }
    var window: UIWindow? { get }
}

@available(iOS 13.0, *)
extension WindowSceneDependable {
    var windowScene: UIWindowScene? {
        window?.windowScene
    }
}

@available(iOS 13.0, *)
extension UIScene: WindowSceneDependable { }

@available(iOS 13.0, *)
extension SceneDelegate: WindowSceneDependable { }

@available(iOS 13.0, *)
extension UIViewController: WindowSceneDependable { }

// MARK: - Window sugar

@available(iOS 13.0, *)
extension UIScene {
    var window: UIWindow? {
        (delegate as? SceneDelegate)?.window
    }
}

extension UIViewController {
    var window: UIWindow? {
        view.window
    }
}

然后当我必须展示一些东西时,我可以这样做:

func present(from navigation: UINavigationController) {
    self.navigation = navigation

    if #available(iOS 13.0, *) {
        guard let currentWindowScene = navigation.windowScene else { return }
        myPresenter.present(in: currentWindowScene)
    } else {
        myPresenter.present()
    }
}

使用它,我几乎可以从任何地方获得一个窗口。但问题是,如果我根本无法访问与视图相关的对象,这是不可能的。例如,在我的身份验证服务中,我必须使用这个废话:

func authorize() {
    if #available(iOS 13.0, *) {
        guard let currentWindowScene = UIApplication.firstWindowScene else { return }
        presenter.present(in: currentWindowScene)
    } else {
        presenter.present()
    }
}

这对我来说看起来不正确,它仅适用于第一个 windowScene。最好不要像我一样这样做,你必须详细说明这个解决方案。

于 2019-11-14T10:11:00.450 回答
0

该解决方案为您提供了最后一次交互,UIScene无需依赖任何东西,而是UIWindow为所有场景使用子类。

class Window: UIWindow
{
    static var lastActive: Window?

    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView?
    {
        Self.lastActive = self
        return super.hitTest(point, with: event)
    }
}

现在您可以访问Window.lastActive及其关联的windowScene( UIWindowScene/ UIScene)。

于 2020-04-21T22:38:21.203 回答