SKView 集成到 UIViewController 中,UITextFields 滞后
SKView integrated into UIViewController with UITextFields lagging
我正在尝试在我的登录 UI 中使用 SKView
来制作一些动画。 SKView
作为子视图添加到 LoginContainerView
以及包含 UITextFields 和登录按钮的视图。所有子视图都使用自动布局定位,附加到 SKView
的 FireScene
的 scaleMode 设置为 .resizeFill
.
从这个剪辑中可以很清楚地观察到我遇到的问题:https://streamable.com/5it17。
Clip explanation: Whenever I double tap any of the UITextFields (to trigger the
UIMenuController / Paste button) the FireScene
freezes for a brief
amount of time (yet it's very noticeable) and the FPS drops down to around 30 for 1-2 seconds.
FireScene
添加为其子节点的唯一节点是修改过的萤火虫 SKEmitterNode 模板。我相当确定这与实际代码无关(因为它非常简单明了)并且可能是 UIKit 与 SpriteKit 错误的混合。
相关代码:
class FireScene: SKScene {
// MARK: - Properties
var fireSparkEmitter: SKEmitterNode? = nil
// MARK: - Inherited
override func didChangeSize(_ oldSize: CGSize) {
// position the emitter to scene's center
fireSparkEmitter?.position = CGPoint(x: size.width/2, y: size.height/2)
}
override func didMove(to view: SKView) {
if let emitter = fireSparkEmitter {
emitter.resetSimulation()
} else {
guard let emitter = SKEmitterNode(fileNamed: "FireSparks.sks") else { return }
addChild(emitter)
fireSparkEmitter = emitter
}
}
}
class LoginContainerView: UIView {
/// ...
let fireBackgroundScene: FireScene = {
let scene = FireScene(size: .zero)
scene.scaleMode = .resizeFill
return scene
}()
/// ...
// MARK: - Inherited
// called after view initialization
func setupSubviews() {
let skView = SKView(frame: .zero)
skView.translatesAutoresizingMaskIntoConstraints = false
addSubview(skView)
skView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
skView.topAnchor.constraint(equalTo: topAnchor).isActive = true
skView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
skView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
skView.showsFPS = true
skView.presentScene(fireBackgroundScene)
}
}
PS:我尝试使用 Time Profiler 分析应用程序,瓶颈似乎是 UIKit 本身处理的 UITextField 手势。
您的问题似乎与 SKView
和其他 UIKit
对象之间的不同布局同步有关。
SKView
有一个名为 isAsynchronous 的 属性(default = true)表示
内容是否异步呈现。
你可以尝试设置:
skView.isAsynchronous = false
将您的 SKView
与核心动画更新同步。
这可能还不够,因为您将 SKView
与项目的 核心动画 同步,但总是有 UIKit 风格的动画 可能不同步。
如果 属性 不能解决您的问题,您还可以更改 preferredFramesPerSecond 属性。请记住,当您尝试混合使用两个框架(sprite-kit
和 UIKit
)时,您将不可避免地遇到不愉快的故障。
我正在尝试在我的登录 UI 中使用 SKView
来制作一些动画。 SKView
作为子视图添加到 LoginContainerView
以及包含 UITextFields 和登录按钮的视图。所有子视图都使用自动布局定位,附加到 SKView
的 FireScene
的 scaleMode 设置为 .resizeFill
.
从这个剪辑中可以很清楚地观察到我遇到的问题:https://streamable.com/5it17。
Clip explanation: Whenever I double tap any of the UITextFields (to trigger the UIMenuController / Paste button) the
FireScene
freezes for a brief amount of time (yet it's very noticeable) and the FPS drops down to around 30 for 1-2 seconds.
FireScene
添加为其子节点的唯一节点是修改过的萤火虫 SKEmitterNode 模板。我相当确定这与实际代码无关(因为它非常简单明了)并且可能是 UIKit 与 SpriteKit 错误的混合。
相关代码:
class FireScene: SKScene {
// MARK: - Properties
var fireSparkEmitter: SKEmitterNode? = nil
// MARK: - Inherited
override func didChangeSize(_ oldSize: CGSize) {
// position the emitter to scene's center
fireSparkEmitter?.position = CGPoint(x: size.width/2, y: size.height/2)
}
override func didMove(to view: SKView) {
if let emitter = fireSparkEmitter {
emitter.resetSimulation()
} else {
guard let emitter = SKEmitterNode(fileNamed: "FireSparks.sks") else { return }
addChild(emitter)
fireSparkEmitter = emitter
}
}
}
class LoginContainerView: UIView {
/// ...
let fireBackgroundScene: FireScene = {
let scene = FireScene(size: .zero)
scene.scaleMode = .resizeFill
return scene
}()
/// ...
// MARK: - Inherited
// called after view initialization
func setupSubviews() {
let skView = SKView(frame: .zero)
skView.translatesAutoresizingMaskIntoConstraints = false
addSubview(skView)
skView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
skView.topAnchor.constraint(equalTo: topAnchor).isActive = true
skView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
skView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
skView.showsFPS = true
skView.presentScene(fireBackgroundScene)
}
}
PS:我尝试使用 Time Profiler 分析应用程序,瓶颈似乎是 UIKit 本身处理的 UITextField 手势。
您的问题似乎与 SKView
和其他 UIKit
对象之间的不同布局同步有关。
SKView
有一个名为 isAsynchronous 的 属性(default = true)表示
内容是否异步呈现。
你可以尝试设置:
skView.isAsynchronous = false
将您的 SKView
与核心动画更新同步。
这可能还不够,因为您将 SKView
与项目的 核心动画 同步,但总是有 UIKit 风格的动画 可能不同步。
如果 属性 不能解决您的问题,您还可以更改 preferredFramesPerSecond 属性。请记住,当您尝试混合使用两个框架(sprite-kit
和 UIKit
)时,您将不可避免地遇到不愉快的故障。