如何使用 Core Motion 使用 SwiftUI 输出磁力计数据? [英] How do I use Core Motion to output magnetometer data using SwiftUI?

查看:43
本文介绍了如何使用 Core Motion 使用 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 @Publishes 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆