【问题标题】:SwiftUI Publishing from background process to main viewSwiftUI 从后台进程发布到主视图
【发布时间】:2020-12-19 01:06:36
【问题描述】:

我正在尝试从后台运行循环中获取数据到主视图。

我可以看到计数器会增加(在终端中打印),但视图不会刷新当前值。每次显示值仍然为零。

我的代码 sn-p 如下:

struct ContentView: View {
    @EnvironmentObject var loop : Loop
    
    var body: some View {
        VStack {
            Text("Content View")
            LoopView()
        }
    }
}
struct LoopView: View {
    @EnvironmentObject var loop : Loop
    
    var body: some View {
        VStack {
            Text("Loop View")
            HStack {
                Text("i = ")
                Text("\(loop.i)")
            }
        }
    }
}
class Loop: ObservableObject {
    @Published var i: Int
    
    func startLoop() {
        while true {
            print("i = \(self.i)")
            self.i += 1
            
            sleep(1)
        }
    }
    
    init() {
        DispatchQueue.main.async {
            self.startLoop()
        }
    }
}

【问题讨论】:

    标签: swift mvvm swiftui observable


    【解决方案1】:

    这是因为您的 sleep 实际上是在主线程 (DispatchQueue.main) 上运行的。如果你真的想使用sleep 在后台运行它使用DispatchQueue.global()。但是你需要再次使用DispatchQueue.main 来更新@Published 变量:

    class Loop: ObservableObject {
        @Published var i: Int
    
        func startLoop() {
            while true {
                print("i = \(self.i)")
                DispatchQueue.main.async {
                    self.i += 1
                }
    
                sleep(1)
            }
        }
    
        init() {
            DispatchQueue.global(qos: .background).async {
                self.startLoop()
            }
        }
    }
    

    或者,您可以查看可以为您完成工作的重复计时器:

    【讨论】:

    • 只使用DispatchQueue.global() 就可以让系统选择any 队列,所以它可能又是main 队列。因此,最好明确指定要使用的哪种队列,即。 background 在这种情况下。
    猜你喜欢
    • 1970-01-01
    • 2022-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-28
    • 1970-01-01
    • 2013-04-02
    • 2020-10-07
    相关资源
    最近更新 更多