pętla nie będzie w stanie zaktualizować UI w tym wątku głównego, chyba że sama pętla jest uruchomiony w innym wątku. Tak, możesz wysłać go do kolejki w tle. W 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)
}
}
}
w 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)
}
}
}
Jeśli aktualizacje interfejsu użytkownika pojawiają się szybciej z wątku w tle, niż interfejs użytkownika może sobie z nimi poradzić, główny wątek może zostać zignorowany za pomocą żądań aktualizacji (co sprawia, że wygląda znacznie wolniej niż w rzeczywistości). Aby rozwiązać ten problem, można rozważyć użycie źródła wysyłki do oddzielenia zadania "zaktualizuj interfejs użytkownika" od faktycznego procesu aktualizacji.
Można użyć DispatchSourceUserDataAdd
(w Swift 2, to dispatch_source_t
z DISPATCH_SOURCE_TYPE_DATA_ADD
), zakładać add
połączenia (dispatch_source_merge_data
w Swift 2) z gwintem tle tak często, jak to potrzebne, a interfejs użytkownika będzie przetwarzać je tak szybko jak to możliwe , ale połączy je razem, gdy wywoła data
(dispatch_source_get_data
w Swift 2), jeśli aktualizacje w tle pojawiają się szybciej niż interfejs może w inny sposób je przetworzyć. Zapewnia to maksymalną wydajność tła przy optymalnych aktualizacjach interfejsu użytkownika, ale co ważniejsze, gwarantuje to, że interfejs użytkownika nie stanie się wąskim gardłem.
Więc najpierw zadeklarować jakąś zmienną śledzić postęp:
var progressCounter: UInt = 0
A teraz pętla może utworzyć źródło, określić, co zrobić, gdy źródłem jest aktualizowany, a następnie uruchomić asynchroniczne pętlę, która aktualizuje źródło. W Swift 3 czyli:
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)
}
}
w 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);
}
}
Czy możesz potwierdzić, że wezwanie jest wypalanie setProgress? Spróbuj rzucić niektóre logowania tam lub punkt przerwania logowania. Zasadniczo lepiej jest używać NSOperation dla rzeczy, które używają kakao. – macshome
Interesujące, wrzuciłem część logowania i wygląda na to, że wywołanie setProgress nie uruchamia się. Dlaczego miałoby to być? – dslkfjsdlfjl
Cóż, kiedy dispatch_async to zależy od systemu, kiedy ma się wystrzelić. Jeśli potrzebujesz UI do aktualizacji w odpowiednim czasie, nie korzystaj z asynchronizacji. W Xcode możesz wstrzymać aplikację i obejrzeć również oczekujące bloki. – macshome