ios - 如何使用 Core Motion 通过 SwiftUI 输出磁力计数据?

标签 ios swift swiftui core-motion magnetometer

我在使用 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/

相关文章:

objective-c - 浮点工作正常......大多数时候

ios - 在 UIImageView IOS 中加载动画 gif

iphone - 如何模糊UIImage,但保留清晰的对象边界?

ios - cellForRow(在 : indexPath) returns nil and crashes my swift app

ios - 如何使用 SwiftUI 制作自定义图像 resizable()

ios - SwiftUI iOS 14 日期选择器奇怪的行为

iphone - 在 UITableView 中按字母顺序显示 .plist 键值

ios - Eureka Forms 基于 SegmentedRow 隐藏验证错误

ios - 无法快速提取模型类型

swift - 如何在 SwiftUI 中为演示文稿定位器调整内容大小