首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用Core Motion通过SwiftUI输出磁力仪数据?

如何使用Core Motion通过SwiftUI输出磁力仪数据?
EN

Stack Overflow用户
提问于 2019-10-14 02:56:06
回答 2查看 2.7K关注 0票数 4

我在输出磁力计、加速度计和陀螺仪的数据时遇到了问题,使用SwiftUI的Core Motion。我假设我的问题与startMagnetometerUpdates()有关。

我已经尝试使用在stack overflow以及GitHub/google上找到的源代码。问题是我发现的所有代码都使用UIKit而不是SwiftUI。有没有可能在不使用UIKit的情况下实现这一点?

代码语言:javascript
复制
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。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-10-14 08:22:31

你的代码有几个问题。

您的第一个问题是,您需要在模型数据和视图之间建立绑定-通过创建绑定,视图将在模型更改时自动更新。

第二个问题是,您只能通过motionManager.magnetometerData访问一次磁力仪数据,而不是通过startMagnetometerUpdates(to:withHandler:)设置一个闭包来监视更新。

您可以使用Combine框架中的ObservableObject和视图中的@ObservedObject来创建适当的绑定。

首先创建一个类来包装您的运动管理器:

代码语言:javascript
复制
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并绑定属性。

代码语言:javascript
复制
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实例:

代码语言:javascript
复制
let contentView = ContentView(motion: MotionManager())
票数 10
EN

Stack Overflow用户

发布于 2019-10-14 04:57:03

您可以使用Combine来构建一个类来提供数据:

代码语言:javascript
复制
import Combine

public class MagneicFieldProvider: NSObject, ObservableObject {

    public let objectWillChange = PassthroughSubject<CMMagneticField,Never>()

    public private(set) var magneticField: CMMagneticField = CMMagneticField() {
        willSet {
            objectWillChange.send(newValue)
        }
    }

    deinit {
        motionManager.stopMagnetometerUpdates()
    }

    private let motionManager: CMMotionManager

    public override init(){
        self.motionManager = CMMotionManager()
        super.init()
        motionManager.magnetometerUpdateInterval = 1/60
    }

    public func startUpdates() {
        motionManager.startMagnetometerUpdates(to: OperationQueue.main) { this, that in
            if let magneticField = self.motionManager.magnetometerData?.magneticField {
                self.magneticField = magneticField
            }
        }
    }
}

然后在视图中使用它:

代码语言:javascript
复制
struct MagnetometerView: View {

    @ObservedObject var magnetometer = MagneicFieldProvider()

    var body: some View {
        VStack(alignment: .leading) {
            Text("Magnetometer Data")
            Text("X: \(magnetometer.magneticField.x)")
            Text("Y: \(magnetometer.magneticField.y)")
            Text("Z: \(magnetometer.magneticField.z)")
        }   .onAppear(perform: { self.magnetometer.startUpdates() })
    }
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58366799

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档