我通过遵循Mehdi为这个问题提供的解决方案,将SceneKit与SwiftUI一起使用:
SwiftUI - how to add a Scenekit Scene
通常,当创建一个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'
对此有什么解决方案?
找到此答案的解决方案:
SwiftUI – Passing data from SwiftUIView to SceneKit
在Andy问题的下半部分,他描述了如何使用协调器来实现委托方法。为方便起见,在此处复制:
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) { }
}