我在使用 Core Motion 和 SwiftUI 输出磁力计、加速度计和陀螺仪的数据时遇到问题。我假设我的问题与 startMagnetometerUpdates() 有关。
我尝试使用在堆栈溢出以及 GitHub/google 上找到的源代码。问题是我找到的所有代码都使用 UIKit 而不是 SwiftUI。是否可以在不使用 UIKit 的情况下实现这一点?
import CoreMotion
let motionManager = CMMotionManager()
var x = 0.0; var y = 0.0; var z = 0.0
func magnet() {
motionManager.magnetometerUpdateInterval = 1/60
motionManager.startMagnetometerUpdates()
if let magnetometerData = motionManager.magnetometerData {
x = magnetometerData.magneticField.x
y = magnetometerData.magneticField.y
z = magnetometerData.magneticField.z
}
}
struct Magnetometer: View {
var body: some View {
VStack {
Text("Magnetometer Data")
Text("X: \(x)")
Text("Y: \(y)")
Text("Z: \(z)")
}
}
}
struct Magnetometer_Previews: PreviewProvider {
static var previews: some View {
Magnetometer()
}
}
输出应仅显示传感器的 x、y 和 z 值,并以 1/60 的间隔更新。每个值的当前输出都是 0.00000,这是因为我已经将每个变量设置为 0。
最佳答案
您的代码存在一些问题。
您的第一个问题是您需要模型数据和 View 之间的绑定(bind) - 通过创建绑定(bind), View 将在模型更改时自动更新。
第二个问题是您仅通过 motionManager.magnetometerData
访问磁力计数据一次,而不是通过 startMagnetometerUpdates(to:withHandler:) 设置闭包来监视更新
>.
您可以使用 Combine
框架中的 ObservableObject
和 View 中的 @ObservedObject
来创建适当的绑定(bind)。
首先创建一个类来包装您的运动管理器:
import Foundation
import Combine
import CoreMotion
class MotionManager: ObservableObject {
private var motionManager: CMMotionManager
@Published
var x: Double = 0.0
@Published
var y: Double = 0.0
@Published
var z: Double = 0.0
init() {
self.motionManager = CMMotionManager()
self.motionManager.magnetometerUpdateInterval = 1/60
self.motionManager.startMagnetometerUpdates(to: .main) { (magnetometerData, error) in
guard error == nil else {
print(error!)
return
}
if let magnetData = magnetometerData {
self.x = magnetData.magneticField.x
self.y = magnetData.magneticField.y
self.z = magnetData.magneticField.z
}
}
}
}
此类符合 ObservableObject
和 @Publish
的三个属性 x、y 和 z。
简单地在磁力计更新闭包中为这些属性分配新值将导致发布者触发并更新任何观察者。
现在,在您看来,您可以为运动管理器类声明一个 @ObservedObject
并绑定(bind)属性。
struct ContentView: View {
@ObservedObject
var motion: MotionManager
var body: some View {
VStack {
Text("Magnetometer Data")
Text("X: \(motion.x)")
Text("Y: \(motion.y)")
Text("Z: \(motion.z)")
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView(motion: MotionManager())
}
}
请注意,您需要在 SceneDelegate.swift
文件中传递 MotionManager
实例:
let contentView = ContentView(motion: MotionManager())
关于ios - 如何使用 Core Motion 通过 SwiftUI 输出磁力计数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58366799/