Как получить доступ к методам SCNSceneRendererDelegate при использовании SceneKit с SwiftUI? - PullRequest
1 голос
/ 28 марта 2020

Я использую SceneKit с SwiftUI, используя следующее решение, предоставленное Мехди для этого вопроса:

SwiftUI - как добавить сцену Scenekit

Обычно при создании Проект SceneKit, реализующий методы рендерера, так же прост, как простое добавление следующего расширения в файл GameViewController и реализация каждого из методов рендерера:

extension GameViewController: SCNSceneRendererDelegate {
  // 2
  func renderer(renderer: SCNSceneRenderer, updateAtTime time: NSTimeInterval) {
    // 3
    doWhatever()
  }
}

Но при использовании SwiftUI мы используем структуру вместо класс (см. выше связанный вопрос), поэтому мы не можем просто добавить расширение, потому что XCode жалуется:

Non-class type 'ScenekitView" cannot conform to class protocol 'NSObjectProtocol'
Non-class type 'ScenekitView' cannot conform to class protocol 'SCNSceneRendererDelegate'

Какое решение для этого?

1 Ответ

1 голос
/ 28 марта 2020

Нашел решение в этом ответе:

SwiftUI - Передача данных из SwiftUIView в SceneKit

В нижней части вопроса Энди он описывает, как использовать координатор реализовать методы делегата. Воспроизведение здесь для удобства:

struct ScenekitView: NSViewRepresentable {

    @Binding var showStats: Bool
    let sceneView = SCNView(frame: .zero)
    let scene = SCNScene(named: "art.scnassets/ship.scn")!

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    final class Coordinator: NSObject, SCNSceneRendererDelegate {
        var control: ScenekitView

        init(_ control: ScenekitView) {
            self.control = control
        }

        func renderer(_ renderer: SCNSceneRenderer,
               updateAtTime time: TimeInterval) {

            control.sceneView.showsStatistics = control.showStats

            for i in 0...255 {
                control.sceneView.backgroundColor = NSColor(
                                  red: CGFloat(arc4random_uniform(UInt32(i))),
                                green: CGFloat(arc4random_uniform(UInt32(i))),
                                 blue: CGFloat(arc4random_uniform(UInt32(i))),
                                alpha: 1.0)
            }
        }
    }

    func scnScene(stat: Bool, context: Context) -> SCNView {
        sceneView.scene = scene
        sceneView.showsStatistics = stat
        sceneView.delegate = context.coordinator
        return sceneView
    }

    func makeNSView(context: Context) -> SCNView {
        scnScene(stat: true, context: context)
    }

    func updateNSView(_ uiView: SCNView, context: Context) { }
}
...