I wrote this code to show the sensors data and to read and show them in swiftui, it doesn't work unfortunately. can someone help me ?? there's some bugs in swiftui and I have some errors but the most important is first to get the sensor data. is it the correct code to read data for accelerometer and gyroscope ?
'''
HStack{
Button("Start") {
// start()
} .padding()
Button("Stop") {
// start()
} .padding()
}
}
}
func start(){
self.motionManager.gyroUpdateInterval = 0.5
motionManager.startGyroUpdates(to: OperationQueue.current!) { (data, error) in
print(data as Any)
if let data = self.motionManager.gyroData {
let xG = data.rotationRate.x
let yG = data.rotationRate.y
let zG = data.rotationRate.z
self.appendReadingGyroscope(x: xG, y: yG, z: zG)
// Use the gyroscope data in your app.
}
}
self.motionManager.accelerometerUpdateInterval = 0.5
motionManager.startAccelerometerUpdates(to: OperationQueue.current!) { (data, error) in
print(data as Any)
if let data = self.motionManager.accelerometerData {
let xA = data.acceleration.x
let yA = data.acceleration.y
let zA = data.acceleration.z
self.appendReadingAccelerometer(x: xA, y: yA, z: zA)
// Use the accelerometer data in your app.
}
}
}
func stop() {
self.motionManager.stopGyroUpdates()
self.motionManager.stopAccelerometerUpdates()
}
'''
You've got a couple of problems with your code.
First, try to separate your MotionManager
from your ContentView
and use Combine
to read the properties when they update.
I built a MotionManager
class.
MotionManager
class is an ObservableObject (Combine) because we need to implement x, y and z as @Published properties in order to read them in our ContentView
when they update.
Here's the class MotionManager
:
class MotionManager: ObservableObject {
// MotionManager use the ObservableObject Combine property.
private var motionManager: CMMotionManager
@Published
var x: Double = 0.0
@Published
var y: Double = 0.0
@Published
var z: Double = 0.0
// x, y and z use are Published so ContentView can read the values when they update.
// init
init() {
self.motionManager = CMMotionManager()
self.motionManager.magnetometerUpdateInterval = 0.5
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
}
}
}
}
And now here's your ContentView
. It's way more cleaner.
Here you can implement your buttons if you want to.
In your ContentView, you now need to instanciate the MotionManager
class in order to access x, y and z @Published
properties.
struct ContentView: View {
@ObservedObject var motion: MotionManager
// You need to instanciate your MotionManager class as an ObservedObject to use x, y and z when the update
var body: some View {
VStack {
Text("Magnetometer Data")
Text("X: \(motion.x)")
Text("Y: \(motion.y)")
Text("Z: \(motion.z)")
}
}
}
Please note that you'll need to pass your MotionManager()
into the preview code and in the WindowGroup
in order to compile :
ContentView(motion: MotionManager())
I hope my code will help you understand what's going wrong in yours. If not, feel free to ask.
------- EDIT
I implemented start()
and stop()
functions.
//
// ContentView.swift
// todeletenow
//
// Created by Théo Voglimacci on 29/09/2020.
//
import SwiftUI
import Combine
import CoreMotion
struct ContentView: View {
@ObservedObject var motion: MotionManager
// You need to instanciate your MotionManager class as an ObservedObject to use x, y and z when the update
var body: some View {
HStack {
Button("Start") {
motion.start()
} .padding()
Button("Stop") {
motion.stop()
} .padding()
}
VStack {
Text("Magnetometer Data")
Text("X: \(motion.x)")
Text("Y: \(motion.y)")
Text("Z: \(motion.z)")
}
}
}
class MotionManager: ObservableObject {
// MotionManager use the ObservableObject Combine property.
private var motionManager: CMMotionManager
@Published
var x: Double = 0.0
@Published
var y: Double = 0.0
@Published
var z: Double = 0.0
// x, y and z use are Published so ContentView can read the values when they update.
func start() {
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
}
}
}
func stop() {
motionManager.stopMagnetometerUpdates()
}
// init
init() {
self.motionManager = CMMotionManager()
self.motionManager.magnetometerUpdateInterval = 0.5
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
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView(motion: MotionManager())
}
}