【问题标题】:KVO on SKView is not being calledSKView 上的 KVO 未被调用
【发布时间】:2021-07-29 10:09:46
【问题描述】:

我正在尝试对 SKView 的一个属性进行 KVO,但它不起作用。

我已经用 .frame 尝试过它,它就像一个魅力,那么为什么不在 .window 上呢?

为了澄清,我在 SwiftUI 应用程序中使用 SpriteView,我试图获取视图的边界。 我所追求的是在应用程序启动之前获得以下内容;

打印 (self.convertPoint(fromView: .zero) )。当我在

中使用它时
override func didMove

我会得到 Nan/NaN。然而,Apple Code Level Support 提到了关于使用 SpriteView 和获取视图边界的信息。

您收到 NaN 的原因是您正在调用这些方法 在 SwiftUI 实际呈现底层 SKView 之前, 这是您无法看到且无法调用的事件 发生时的代码。

但是,当此事件发生时,SKScene 的视图属性将 将它的窗口从 nil 设置为 UIWindow。因此,您可以使用 KVO 观察窗口属性何时改变,然后让你的 一旦存在非零窗口,就调用 convertPoint。

到目前为止,我有这个:

override func didMove(to view: SKView) {
    observe.observe(object: view )
}

class Observer:SKScene {
    var kvoToken: NSKeyValueObservation?
    
    func observe(object: SKView) {
    kvoToken = object.observe(\.window , options: [ .new] ) { (object, change) in

        guard let value = change.newValue else { return }
        print("New value is: \(value)")
        print ("NEW", self.convertPoint(fromView: .zero) )
        
      }
    }
    
  deinit {
    kvoToken?.invalidate()
  }
}

我也尝试过像这样添加观察者:

NotificationCenter.default.addObserver(view.window, selector: #selector(test(_:)), name: NSNotification.Name(rawValue: "TestNotification"), object: nil)

上面似乎没有做任何事情。所以我有点卡住了,任何帮助将不胜感激。

【问题讨论】:

  • 我把我的问题澄清了一点,也许上下文会有所帮助?
  • 哦,我明白了,所以 SwiftUI 先将场景移动到视图,然后再呈现视图。很公平。代码如何不起作用?它什么都不做吗?
  • 它没有被调用,它适用于 \.frame 但不适用于 \.windows,我不知道为什么。也许我做错了什么......说真的我不知道。
  • 来自this,看来window 不符合KVO 的可能性很大,你根本观察不到。是谁告诉你可以观察到的?
  • Apple 提供的代码级支持,是的,我也看到了。这就是我来这里寻求帮助的原因:)

标签: swift sprite-kit key-value-observing skview


【解决方案1】:

答案(可能)..

我无法读取 UIView 的 '.window' 属性,因此我开始寻找另一个可观察的属性,一旦 UIWindow 为 != nil 就会改变。我想我在 SKScene.view.frame 中找到了它。我不完全确定这是一个 100% 好的答案,但它确实有效。

class Observer: NSObject {
    dynamic var kvoToken: NSKeyValueObservation?
    
    func observe(object: SKScene )  {
        kvoToken = object.observe(\.view?.frame , options: [ .new] ) { (object, change) in

        guard let value = change.newValue else { return }
        print("New value is: \(value)")
        print ("CONVERTING", object.convertPoint(fromView: .zero) )
        
      }
    }
    
  deinit {
    kvoToken?.invalidate()
  }
}

override func didMove(to view: SKView) {
    
    viewer = view.scene

    observe.observe(object: viewer )

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多