簡體   English   中英

Swift:如何將工人放入單獨的線程中,在主視圖中顯示結果?

[英]Swift: How to put worker into separate thread, show results in main view?

我想知道是否有一種簡單的方法可以做到這一點:將一個長時間運行的工作人員放入一個單獨的線程中,以免阻塞 UI。 並在主視圖中顯示結果。 在 SwiftUI 或 UIKit 下。 我在 web 上發現的一切都非常復雜。 或者 Swift 中是否有完全不同的方法?

我制作了一個簡約的 Python 程序來展示我想要做什么。 它在 MacOS 中顯示 WiFi 信號強度。

import time
import sys
import subprocess
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QHBoxLayout
from PyQt5.QtCore import QObject, pyqtSignal, QThread

class Worker(QObject):
    send_output = pyqtSignal(str)
    def __init__(self):
        super().__init__()

    def worker(self):
        while True:
            _out = subprocess.check_output(
                ["/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport",
                 "-I"])\
                .decode("utf-8")
            self.send_output.emit("RSSI: " + _out.splitlines()[0][-3:] + " dBm")
            time.sleep(2)

class MainWindow(QWidget):
    do_work = pyqtSignal(object)
    def __init__(self):
        super().__init__()

        self.label = QLabel()
        layout = QHBoxLayout()
        self.setLayout(layout)
        layout.addWidget(self.label)
        self.show()

        self.app_thread = QThread()
        self.app = Worker()
        self.app.moveToThread(self.app_thread)
        self.app.send_output.connect(self.output_label)
        self.app_thread.started.connect(self.app.worker)
        self.app_thread.start()

    def output_label(self, _str):
        self.label.setText(_str)

if __name__ == '__main__':
    application = QApplication(sys.argv)
    mainwindow = MainWindow()
    sys.exit(application.exec())

我現在正試圖找到進入 Swift 的方法。 這很令人興奮,但確實是一件大事。 提前致謝!

這是一個非常廣泛的問題,所以我也將相當廣泛地回答它。

是的,您可以在單獨的線程中運行任務,然后將數據返回到主線程。 有很多方法可以做到這一點,一種常見的方法是DispatchQueue

讓我們舉一個過於簡單的例子(絕對不是真實世界的代碼):

struct ContentView : View {
    @State var result = ""
    
    var body: some View {
        Text("Result: \(result)")
            .onAppear {
                DispatchQueue.global(qos: .background).async {
                    //do your long-running code
                    var innerResult = 0
                    for i in 0...1000000 {
                        innerResult += 5
                        print(i)
                        //use DispatchQueue.main.async here if you want to update during the task
                    }
                    
                    //update at the end:
                    DispatchQueue.main.async {
                        result = "Done! \(innerResult)"
                    }
                }
            }
    }
}

在此示例中,當視圖出現時,任務通過DispatchQueue在后台線程中運行。 在這種情況下,我只是利用了這樣一個事實,即打印到控制台是一項相當昂貴的操作,如果完成一百萬次。

完成后,它會分派回主線程並更新 state 變量中的結果。

DispatchQueue並非特定於 UIKit 或 SwiftUI ——使用 SwiftUI 將演示放在一起是最簡單的。

如果您要真正開始編寫代碼來執行此操作,您會想要對 DispatchQueues 的工作方式進行一些研究,包括使用哪個隊列、是否創建自己的隊列、是否要串行完成任務等,但是對於可以做到這一點(以及如何容易)的廣泛問題的目的,這至少顯示了基礎知識。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM