前提
SwiftUIのonAppear内でクラスの変数を参照し、その値に応じてクラスの関数を実行するプログラムを作成しています。
クラスでは端末のジャイロセンサーの値を一定間隔で取得して、ビューではその値をTextに反映する処理を記述しています。
クラスの関数は実行されているようなのですが、Textの内容が全く更新されない状態です。
実現したいこと
- onAppearでクラスの関数を実行して、クラスで取得したセンサーの値をビューのTextに反映する。
発生している問題・エラーメッセージ
onAppearでは上記の通りビューが更新できないのですが、同様の内容をButtonのaction内で実行するとジャイロセンサーの値がビューのTextに反映されるようになります。
onAppearで実行した時のみ今回の不具合が発生しています。
該当のソースコード
【FirstView.swift】
swift
1import SwiftUI 2 3struct FirstView: View { 4 @ObservedObject var gyroSensor = GyroSensor() 5 var body: some View{ 6 VStack(){ 7 Spacer() 8 // ジャイロセンサーの値を表示 9 VStack(){ 10 Text(self.gyroSensor.xData) 11 .font(.largeTitle) 12 .fontWeight(.bold) 13 Text(self.gyroSensor.yData) 14 .font(.largeTitle) 15 .fontWeight(.bold) 16 Text(self.gyroSensor.zData) 17 .font(.largeTitle) 18 .fontWeight(.bold) 19 Text(String(self.gyroSensor.xAction)) 20 .font(.largeTitle) 21 .fontWeight(.bold) 22 Button(action: { 23 self.gyroSensor.isStarted ? self.gyroSensor.stop() : self.gyroSensor.start() 24 }) { 25 self.gyroSensor.isStarted ? Text("STOP") : Text("START") 26 } 27 } 28 Spacer(minLength: 50) 29 } 30 .onChange(of: self.gyroSensor.xAction){ newData in 31 print("F:newData:\(newData)") 32 } 33 .onAppear { 34 self.gyroSensor.isStarted ? self.gyroSensor.stop() : self.gyroSensor.start() 35 print("F:onAppear()") 36 } 37 } 38} 39 40struct FirstView_Previews: PreviewProvider { 41 static var previews: some View { 42 FirstView() 43 } 44}
【GyroSensor.swift】
swift
1import UIKit 2import CoreMotion 3 4class GyroSensor: NSObject, ObservableObject { 5 @Published var isStarted = false 6 @Published var xAction = false 7 @Published var xData = "0.0" 8 @Published var yData = "0.0" 9 @Published var zData = "0.0" 10 let motionManager = CMMotionManager() 11 func start() { 12 if motionManager.isGyroAvailable { 13 print("G:isGyroAvailable") 14 motionManager.gyroUpdateInterval = 0.1 15 motionManager.startGyroUpdates(to: OperationQueue.current!, withHandler: {(gyroData: CMGyroData?, error: Error?) in 16 self.updateData(gyro: gyroData!) 17 }) 18 } 19 isStarted = true 20 print("G:start()") 21 } 22 func stop() { 23 self.motionManager.stopGyroUpdates() 24 isStarted = false 25 print("G:stop()") 26 } 27 private func updateData(gyro: CMGyroData){ 28 xData = String(format:"%.1f", gyro.rotationRate.x) 29 yData = String(format:"%.1f", gyro.rotationRate.y) 30 zData = String(format:"%.1f", gyro.rotationRate.z) 31 if(gyro.rotationRate.x < -2){ 32 xAction = true 33 print("G:xAction = true") 34 } 35 else{ 36 xAction = false 37 } 38 print("G:updateData") 39 } 40} 41
試したこと
print()を使ってコンソール内で処理の流れを確認したところ、クラスの関数は問題なく実行されており、値の更新もされているようでした。
また、「.onChange」を使ってクラスの変数を直接取得してみたりもしましたが、ビューが更新されないのと同じで、onChangeも動作しませんでした。
ですが、こちらもButtonから関数を実行すると正常に動作しました。
参考サイト
- CoreMotionフレームワーク
- GytoScope
- CoreMotionでモーションセンサーの値を取得する方法
- Viewが更新されるようにする
- @StateにonAppearで代入しても反映されない
補足情報(FW/ツールのバージョンなど)
- Xcode:13.1
- iOS:15.7
あなたの回答
tips
プレビュー