【问题标题】:How get current keywindow equivalent for multi window SceneDelegate Xcode 11?如何获取多窗口 SceneDelegate Xcode 11 的当前键窗口等效项?
【发布时间】:2019-11-22 08:35:51
【问题描述】:

我正在将适用于 iPadOS 的 iOS13 应用程序转换为 SceneDelegate(多窗口)。

如何从当前的 SceneDelegate 获取当前的 UIWindow?

我知道 a 可以使用 UIView.windowUIViewController.view.window 访问当前场景,但我有一个非 UI 类(AppDelegate),我需要在其中获取窗口(直到 iOS12 之前的 keyWindow)以在顶部显示小吃店一切。

我以前是[UIApplication sharedApplication].keyWindow,但现在当然错了。

【问题讨论】:

    标签: xcode ios13 uiscenedelegate uiscene


    【解决方案1】:

    Swift 5.x / iOS 13.x

    受到许多解决方案的启发,为了找回我的旧窗口属性(在 connectedScenes 中搜索它),我实现了一个小扩展:

    extension UIApplication {
        var currentWindow: UIWindow? {
            connectedScenes
            .filter({$0.activationState == .foregroundActive})
            .map({$0 as? UIWindowScene})
            .compactMap({$0})
            .first?.windows
            .filter({$0.isKeyWindow}).first
        }
    }
    

    用法

    if let window = UIApplication.shared.currentWindow { 
       // do whatever you want with window
    }
    

    【讨论】:

    • 当窗口并排时,我认为在 ios13 上......两者都是“foregroundActive”,但我无法确认。
    • 是的,我可以确认这一点,仍然不知道如何访问活动(或谁点击了应用链接)
    • @JeffersonSetiawan 从最后一行删除.first 怎么样,并将这一行添加到扩展名的末尾:.filter({$0.isFocused == true}).first。你可以试试这个吗?
    • 无法使用 .filter({$0.isFocused == true}).first
    • 你可以用.compactMap { $0 as? UIWindowScene }折叠.map.compactMap
    【解决方案2】:

    您需要简单地遍历所有窗口并手动查找关键窗口。

    for (UIWindow *window in [UIApplication sharedApplication].windows) {
        if (window.isKeyWindow) {
            // you have the key window
            break;
        }
    }
    

    不要使用UISceneActivationStateForegroundActive 作为检查。这意味着一些不同的东西,人们通过使用逻辑找到第一个 UISceneActivationStateForegroundActive 窗口场景来引入错误。

    【讨论】:

      【解决方案3】:

      听起来您可能想将此逻辑移至您的 SceneDelegate。

      SceneDelegate 现在知道窗口是否连接到场景,因此让每个连接的场景监听驱动小吃店的任何事件并将其显示在其窗口上可能是有意义的。这将导致每个可见窗口都显示小吃店(1 个或更多)。

      【讨论】:

        【解决方案4】:

        你可以试试:

            if let window = UIApplication.shared.windows.first(where: { (window) -> Bool in window.isKeyWindow}) {
            //your code
            }
        

        希望这会有所帮助!

        【讨论】:

          【解决方案5】:

          现在您有多个窗口,每个场景一个。首先,您必须回答您在使用时需要哪一个。

          可能你想获取当前活动场景的窗口然后你可以使用这个:

              UIWindow* window = nil;
              if (@available(iOS 13.0, *))
              {
                  for (UIWindowScene* wScene in [UIApplication sharedApplication].connectedScenes)
                  {
                      if (wScene.activationState == UISceneActivationStateForegroundActive)
                      {
                          window = wScene.windows.firstObject;
          
                          break;
                      }
                  }
              }
          

          【讨论】:

          • 这是不正确的。这不是UISceneActivationStateForegroundActive 的意思。你想要window.isKeyWindow
          • 问题是“从非UI类获取UIWindow的方法是什么。另一方面,关键窗口是:”关键窗口接收键盘和其他非触摸相关事件。一次只有一个窗口可能是关键窗口。” 您可以在屏幕上同时拥有多个可触摸的活动窗口,其中只有一个是 keyWindow,但它可能不是想要的窗口。这个问题没有绝对正确的答案,这就是为什么我的解决方案是在一个具体场景中提出的。
          • 这就是 Apple 弃用 UIApplication 中的 keyWindow 属性的原因。
          • 我明白你在说什么。我想在一个快速堆栈溢出复制和粘贴的世界中,我想插话以避免人们误解和应用会导致错误的代码(就像我的开发人员将这段代码复制到我们的代码库一样)。我很抱歉推动您的意图是错误的,这是不公平的。
          【解决方案6】:

          我还没有尝试过,但是您应该能够使用[UIApplication sharedApplication].windows 获取所有窗口,然后选择是要在所有窗口上还是在一个窗口上显示小吃店。

          【讨论】:

          • 用这个方法你得到一个窗口数组...但是你不知道当前是什么
          猜你喜欢
          • 2019-11-19
          • 1970-01-01
          • 2017-08-26
          • 2011-10-31
          • 2011-12-02
          • 2011-05-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多