我试图在设备屏幕顶部显示相机跟踪状态信息,但我的所有努力仍然出现错误。我对 ARView 如何与 SwiftUI 配合使用感到非常困惑,显示 AR 体验并在其上添加按钮图标很简单,但从会话中获取数据看起来需要做更多工作,有人可以帮助我吗?谢谢!
ViewModel 中的错误:“描述是仅获取属性”
内容视图
import SwiftUI
import ARKit
import RealityKit
struct ContentView: View {
@StateObject var vm = ViewModel()
var body: some View {
ZStack{
ARViewContainer()
.edgesIgnoringSafeArea(.all)
.environmentObject(vm)
VStack{
Text(vm.sessionInfoLabel)
.font(.title3)
.foregroundColor(.red)
Spacer()
HStack{
Button{
} label: {
Image(systemName: "person.2")
.padding()
.font(.title)
}
Spacer()
Button{
} label: {
Image(systemName: "target")
.padding()
.font(.title)
}
}
.padding()
}
}
}
}
struct ARViewContainer: UIViewRepresentable {
@EnvironmentObject var vm: ViewModel
func makeUIView(context: Context) -> ARView {
return vm.arView
}
func updateUIView(_ uiView: ARView, context: Context) {
}
}
视图模型
import SwiftUI
import ARKit
import RealityKit
class ViewModel: ObservableObject {
@Published var arView: ARView
var sessionInfoLabel = ""
init() {
arView = ARView.init(frame: .zero)
let config = ARWorldTrackingConfiguration()
config.planeDetection = .horizontal
arView.session.delegate = arView
arView.session.run(config)
}
}
extension ARView: ARSessionDelegate {
public func session(_ session: ARSession, cameraDidChangeTrackingState camera: ARCamera) {
camera.trackingState.description = ViewModel().sessionInfoLabel
}
}
extension ARCamera.TrackingState: CustomStringConvertible {
public var description: String {
switch self {
case .normal:
return "Normal"
case .notAvailable:
return "Not Available"
case .limited(.initializing):
return "Initializing"
case .limited(.excessiveMotion):
return "Excessive Motion"
case .limited(.insufficientFeatures):
return "Insufficient Features"
case .limited(.relocalizing):
return "Relocalizing"
case .limited:
return "Unspecified Reason"
}
}
}
将此 SwiftUI 代码与协调器一起使用来表示 AR 相机的所有七种跟踪状态。
import SwiftUI
import ARKit
import RealityKit
struct ARContainer : UIViewRepresentable {
@Binding var string: String
var arView: ARView
final class Coordinator : NSObject, ARSessionDelegate {
var control: ARContainer
init(_ control: ARContainer) {
self.control = control
}
func session(_ session: ARSession,
cameraDidChangeTrackingState camera: ARCamera) {
control.string = camera.trackingState.description
}
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIView(context: Context) -> ARView {
arView.session.delegate = context.coordinator
arView.automaticallyConfigureSession = false
let config = ARWorldTrackingConfiguration()
config.planeDetection = .horizontal
arView.session.run(config)
return arView
}
func updateUIView(_ view: ARView, context: Context) { }
}
struct ContentView : View {
@State var string = "Camera Trackimg State"
let arView = ARView(frame: .zero)
var body: some View {
ZStack {
ARContainer(string: $string, arView: arView)
.ignoresSafeArea()
Text(string)
.font(.largeTitle)
.foregroundStyle(.white)
}
}
}
extension ARCamera.TrackingState : CustomStringConvertible {
public var description: String {
switch self {
case .normal:
return "Normal"
case .notAvailable:
return "Not Available"
case .limited(.initializing):
return "Initializing"
case .limited(.excessiveMotion):
return "Excessive Motion"
case .limited(.insufficientFeatures):
return "Insufficient Features"
case .limited(.relocalizing):
return "Relocalizing"
case .limited:
return "Unspecified Reason"
}
}
}