SKView интегрирован в UIViewController с задержкой UITextFields - PullRequest
0 голосов
/ 04 сентября 2018

Я пытаюсь использовать SKView в моем интерфейсе входа для некоторых анимаций. SKView добавляется как подпредставление к LoginContainerView, а также к представлению, содержащему поля UITextFields и кнопку входа. Все подпредставления позиционируются с помощью автоматического размещения, а FireScene, прикрепленный к SKView, имеет scaleMode, установленный в .resizeFill.

Проблема, с которой я столкнулся, очень понятна из этого клипа: https://streamable.com/5it17.

Описание клипа: всякий раз, когда я дважды нажимаю любое из полей UITextField (чтобы вызвать Кнопка UIMenuController / Paste) FireScene останавливается на короткое время количество времени (но это очень заметно) и FPS падает до 30 в течение 1-2 секунд.

Единственный узел, который 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, и кажется, что узким местом является обработка жестов UITextField самой UIKit.

1 Ответ

0 голосов
/ 04 сентября 2018

Ваша проблема связана с другой синхронизацией макета между SKView и другими UIKit объектами. SKView имеет свойство с именем isAsynchronous ( default = true ), которое указывает отображается ли контент асинхронно. Вы можете попробовать установить:

skView.isAsynchronous = false

для синхронизации вашего SKView с обновлениями основной анимации. Этого может быть недостаточно, потому что вы синхронизируете SKView с Core Animations вашего проекта, но всегда есть анимации в стиле UIKit , которые могут быть не синхронизированы. Если это свойство не решает вашу проблему, вы можете также изменить свойство предпочитаемый фреймPerSecond Помните, что при попытке смешать два фреймворка (sprite-kit и UIKit) вы неизбежно столкнетесь с неприятными заминками.

...