Ihre Schleife wird die Benutzeroberfläche in diesem Haupt-Thread zu aktualisieren, es sei denn, die Schleife selbst läuft auf einem anderen Thread nicht in der Lage sein. Sie können es also an eine Hintergrundwarteschlange senden. In Swift 3:
DispatchQueue.global(qos: .utility).async {
for i in 0 ..< kNumberOfIterations {
// do something time consuming here
DispatchQueue.main.async {
// now update UI on main thread
self.progressView.setProgress(Float(i)/Float(kNumberOfIterations), animated: true)
}
}
}
In Swift 2:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
for i in 0 ..< kNumberOfIterations {
// do something time consuming here
dispatch_async(dispatch_get_main_queue()) {
// now update UI on main thread
self.progressView.setProgress(Float(i)/Float(kNumberOfIterations), animated: true)
}
}
}
Wenn UI-Aktualisierungen schneller aus dem Hintergrundthread kommen, als die UI sie verarbeiten kann, kann der Hauptthread mit Aktualisierungsanforderungen zurückgestoßen werden (wodurch er viel langsamer aussieht als er wirklich ist). Um dies zu beheben, könnte man die Verteilungsquelle verwenden, um die Aufgabe "update UI" von dem tatsächlichen Hintergrundaktualisierungsprozess zu entkoppeln.
kann man verwenden, um ein DispatchSourceUserDataAdd
(in Swift 2, es ist ein dispatch_source_t
von DISPATCH_SOURCE_TYPE_DATA_ADD
ist), post add
Anrufe (dispatch_source_merge_data
in Swift 2) aus dem Hintergrund-Thread so oft wie gewünscht, und die UI wird sie so schnell verarbeiten, wie es kann , aber wird sie zusammen zusammenführen, wenn es data
(dispatch_source_get_data
in Swift 2) aufruft, wenn die Hintergrundaktualisierungen schneller kommen, als die UI sie andernfalls verarbeiten kann. Dadurch wird eine maximale Hintergrundleistung mit optimierten UI-Aktualisierungen erreicht. Vor allem aber wird sichergestellt, dass die Benutzeroberfläche nicht zu einem Engpass wird. So
erklären zunächst einige variable Spur des Fortschritts zu halten:
var progressCounter: UInt = 0
Und jetzt Ihre Schleife eine Quelle erstellen können, definieren, was zu tun ist, wenn die Quelle aktualisiert wird, und dann die asynchrone Schleife starten die aktualisiert die Quelle. In Swift 3, das ist:
progressCounter = 0
// create dispatch source that will handle events on main queue
let source = DispatchSource.makeUserDataAddSource(queue: .main)
// tell it what to do when source events take place
source.setEventHandler() { [unowned self] in
self.progressCounter += source.data
self.progressView.setProgress(Float(self.progressCounter)/Float(kNumberOfIterations), animated: true)
}
// start the source
source.resume()
// now start loop in the background
DispatchQueue.global(qos: .utility).async {
for i in 0 ..< kNumberOfIterations {
// do something time consuming here
// now update the dispatch source
source.add(data: 1)
}
}
In Swift 2:
progressCounter = 0
// create dispatch source that will handle events on main queue
let source = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, dispatch_get_main_queue());
// tell it what to do when source events take place
dispatch_source_set_event_handler(source) { [unowned self] in
self.progressCounter += dispatch_source_get_data(source)
self.progressView.setProgress(Float(self.progressCounter)/Float(kNumberOfIterations), animated: true)
}
// start the source
dispatch_resume(source)
// now start loop in the background
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
for i in 0 ..< kNumberOfIterations {
// do something time consuming here
// now update the dispatch source
dispatch_source_merge_data(source, 1);
}
}
Können Sie bestätigen, dass die setProgress Anruf feuert? Versuchen Sie, sich dort einzuloggen oder einen Logging Breakpoint zu verwenden. Außerdem ist es im Allgemeinen vorzuziehen, NSOperation für Dinge zu verwenden, die Kakao verwenden. – macshome
Interessant, ich warf einige Logging und es scheint, dass der Aufruf setProgress nicht feuert. Warum sollte das sein? – dslkfjsdlfjl
Nun, wenn Sie dispatch_async, ist es an das System, als ob es feuern wird. Wenn Sie die Benutzeroberfläche rechtzeitig aktualisieren müssen, verwenden Sie keine Asynchronisierung. In Xcode können Sie die App pausieren und sich die ausstehenden Blöcke ansehen. – macshome