SKView 集成到 UIViewController 中,UITextFields 滞后

SKView integrated into UIViewController with UITextFields lagging

我正在尝试在我的登录 UI 中使用 SKView 来制作一些动画。 SKView 作为子视图添加到 LoginContainerView 以及包含 UITextFields 和登录按钮的视图。所有子视图都使用自动布局定位,附加到 SKViewFireScene 的 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-kitUIKit)时,您将不可避免地遇到不愉快的故障。