如何使用 Core Motion 使用 SwiftUI 输出磁力计数据? [英] How do I use Core Motion to output magnetometer data using SwiftUI?
问题描述
我在使用 Core Motion 和 SwiftUI 输出磁力计、加速度计和陀螺仪的数据时遇到问题.我假设我的问题与 startMagnetometerUpdates() 有关.
I am having trouble outputting the data for the magnetometer, accelerometer and gyroscope using Core Motion with SwiftUI. I'm assuming my problem has something to do with the startMagnetometerUpdates().
我尝试使用在堆栈溢出以及 GitHub/google 上找到的源代码.问题是我发现的所有代码都使用 UIKit 而不是 SwiftUI.是否可以在不使用 UIKit 的情况下实现这一点?
I've tried using source code found here on stack overflow, as well as on GitHub/google. The problem is all the code I'm finding uses UIKit instead of SwiftUI. Is it possible to implement this without using 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.
The output should just display the x, y and z values for the sensor and update on an interval of 1/60. The current output is 0.00000 for every value, which is because I set each variable to 0 already.
推荐答案
您的代码有几个问题.
您的第一个问题是您需要在模型数据和视图之间进行绑定 - 通过创建绑定,视图将在模型更改时自动更新.
Your first problem is that you need a binding between your model data and your view - By creating a binding, the view will be updated automatically when the model changes.
第二个问题是您只能通过motionManager.magnetometerData
访问磁力计数据一次,而不是通过startMagnetometerUpdates(to:withHandler:)
.
The second problem is that you are only accessing the magnetometer data once via motionManager.magnetometerData
rather than setting up a closure to monitor updates via startMagnetometerUpdates(to:withHandler:)
.
您可以使用 Combine
框架中的 ObservableObject
和视图中的 @ObservedObject
来创建适当的绑定.
You can use ObservableObject
from the Combine
framework and @ObservedObject
in your view to create the appropriate binding.
首先创建一个类来包装您的运动管理器:
Start by creating a class to wrap your motion manager:
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.
This class conforms to ObservableObject
and @Publish
es its three properties, x,y and z.
在磁力计更新闭包中简单地为这些属性分配新值将导致发布者触发并更新任何观察者.
Simply assigning new values to these properties in the magnetometer update closure will cause the publisher to fire and update any observers.
现在,在您看来,您可以为您的运动管理器类声明一个 @ObservedObject
并绑定属性.
Now, in your view, you can declare an @ObservedObject
for your motion manager class and bind the properties.
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
的实例:
Note that you will need to pass an instance of MotionManager
in your SceneDelegate.swift
file:
let contentView = ContentView(motion: MotionManager())
这篇关于如何使用 Core Motion 使用 SwiftUI 输出磁力计数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!