微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

SwiftUI从嵌套在类中的后台进程更新视图

如何解决SwiftUI从嵌套在类中的后台进程更新视图

我正在尝试学习SwiftUI并使用我的第一个应用程序(iOS13)。通常我正在使用c ++进行编码,但是这里有一些我需要了解的新功能...

我的目标是创建多个视图选项卡,并在所有视图中使用一些imu数据。

我的问题是传感器数据正在.main循环中更新,因此我的UI不响应并冻结。因此,我在Google上进行了搜索,发现其中的一些代码已被删除,从而允许在后台更新imu数据并在视图上显示数据。

struct MotionSensors: View {
    
    let motionManager = cmmotionmanager()
    let queue = OperationQueue()
    
    @State private var gyrocope = CMAttitude.init()
    
    var body: some View {
        vstack{
            Text("Pitch: \(rad2deg(self.pitch))")
            Text("Yaw: \(rad2deg(self.yaw))")
            Text("Roll: \(rad2deg(self.roll))")
        }//vstack
        .onAppear {
                print("ON APPEAR")
                self.motionManager.startDeviceMotionUpdates(to: self.queue) { (data: CMDeviceMotion?,error: Error?) in
                    guard let data = data else {
                        print("Error: \(error!)")
                        return
                    }
                    let attitude: CMAttitude = data.attitude

                    print("pitch: \(rad2deg(attitude.pitch))")
                    print("yaw: \(rad2deg(attitude.yaw))")
                    print("roll: \(rad2deg(attitude.roll))")

                    dispatchQueue.main.async {
                        
                        self.gyrocope = attitude
                      
                    }
                }
            }//.onappear
    }
}

下一步,我想将CoreMotion的基本功能导出到另一个类/结构,访问传感器数据并更新我的视图。 像这样的东西:

import SwiftUI
import CoreMotion

class MotionClass : ObservableObject {
    
    let motionManager = cmmotionmanager()
    let queue = OperationQueue()
    
    @Published var roll = Double.zero // test property to call it in the main view

    var gyrocope = CMAttitude.init()

    
    init(){
        print("INIT MotionClass")
        self.motionManager.startDeviceMotionUpdates(to: self.queue) { (data: CMDeviceMotion?,error: Error?) in
            guard let data = data else {
                print("Error: \(error!)")
                return
            }
            let attitude: CMAttitude = data.attitude

//            print("pitch: \(rad2deg(attitude.pitch))")
//            print("yaw: \(rad2deg(attitude.yaw))")
//            print("roll: \(rad2deg(attitude.roll))")

            dispatchQueue.main.async {
                
                self.gyrocope = attitude
                self.roll = self.gyrocope.roll 

                
            }
        }
    }
}

struct ContentView: View {
     
    // SceneDelegate.swift has been updated ... 
    @EnvironmentObject var attitude : MotionClass

    @State var roll : Double = 0
      
    @State private var selection = 1
    
    @State private var viewNames : [String] = ["View1","View2","View3","View4"]
    
    var body: some View {
        
        TabView(selection: $selection){
            
            View0(viewName: $viewNames[0]).tag(0)

            vstack {
                Text("Second View")
                Text("roll: \(self.attitude.roll)")

            .tabItem {vstack {
                    Image(systemName:"star")
                    Text("View1")}}

            .tag(1)
            
            View2(viewName: $viewNames[2]).tag(2)
            
            View3(viewName: $viewNames[3]).tag(3)
            
        }
    }
}

使用自定义类运行代码时,我看到传感器数据正在后台更新,但是无法将当前值输入到视图中。我收到此错误

[SwiftUI]不允许从后台线程发布更改;确保在模型更新时从主线程(通过诸如receive(on :)之类的运算符)发布值。

我知道原因,但我不知道该如何解决...

有人给我一些小费吗?一些搜索关键词或最小示例或其他。 非常感谢!

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。