Il tuo ciclo non sarà in grado di aggiornare l'interfaccia utente in quel thread principale a meno che il circuito stesso è in esecuzione su un altro thread. Quindi, puoi inviarlo a qualche coda in background. 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)
}
}
}
a 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)
}
}
}
Se gli aggiornamenti dell'interfaccia utente derivano più rapidamente dal thread in background di quello in cui l'interfaccia utente è in grado di gestirli, il thread principale può essere retrocesso con le richieste di aggiornamento (facendolo sembrare molto più lento di quello che è realmente). Per risolvere questo problema, si potrebbe prendere in considerazione l'utilizzo dell'origine di invio per disaccoppiare l'attività di "aggiornamento dell'interfaccia utente" dall'effettivo processo di aggiornamento in background.
Si può usare un DispatchSourceUserDataAdd
(a Swift 2, è un dispatch_source_t
di DISPATCH_SOURCE_TYPE_DATA_ADD
), inviare add
chiamate (dispatch_source_merge_data
a Swift 2) dal thread in background con la frequenza desiderata, e l'interfaccia utente li elaborerà così rapidamente come è possibile ma li unirà insieme quando chiama data
(dispatch_source_get_data
in Swift 2) se gli aggiornamenti in background arrivano più rapidamente di quanto l'UI possa altrimenti elaborarli. Ciò consente di ottenere le massime prestazioni in background con aggiornamenti UI ottimali, ma soprattutto, ciò garantisce che l'UI non diventi un collo di bottiglia.
Quindi, prima di dichiarare una variabile per tenere traccia dei progressi:
var progressCounter: UInt = 0
E ora il ciclo in grado di creare una fonte, definire che cosa fare quando la sorgente viene aggiornato, e quindi lanciare il ciclo asincrono che aggiorna la fonte. In Swift 3 cioè:
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)
}
}
a 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);
}
}
Puoi confermare che la chiamata setProgress sta sparando? Prova a lanciare qualche accesso o un punto di interruzione della registrazione. Inoltre è generalmente preferibile usare NSOperation per le cose che usano Cocoa. – macshome
Interessante, ho buttato un po 'di accesso e sembra che la chiamata setProgress non stia sparando. Perché dovrebbe essere? – dslkfjsdlfjl
Bene, quando si invia dispatch_async dipende dal sistema quando deve sparare. Se è necessario aggiornare l'interfaccia in modo tempestivo, non utilizzare async. In Xcode puoi mettere in pausa l'app e dare un'occhiata anche ai blocchi in sospeso. – macshome