问题描述
我正在尝试对 SKView 的一个属性执行 KVO,但它不起作用。
我已经用 .frame 尝试过它,它的作用就像一个魅力,那么为什么不在 .window 上呢?
澄清一下,我在 SwiftUI 应用程序中使用 SpriteView,我试图获取视图的边界。 我所追求的是在应用程序启动之前获得以下内容;
打印(self.convertPoint(fromView: .zero))。当我在
中使用它时override func didMove
我会得到 Nan/NaN。然而,Apple Code Level Support 说这是关于使用 SpriteView 和获取视图的边界。
您收到 NaN 的原因是您正在调用这些方法 在 SwiftUI 实际呈现底层 SKView 之前, 这是一个您无法看到的事件,也无法调用 发生时编码。
然而,当这个事件确实发生时,SKScene 的 view 属性将 将它的窗口从 nil 设置为 UIWindow。因此,您可以使用 KVO观察window属性什么时候改变,然后让你的 一旦有一个非 nil 窗口就调用 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)
以上似乎没有做任何事情。所以我有点卡住了,任何帮助将不胜感激。
解决方法
答案(可能)..
我无法读取 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 )
}