Swift - принудительное синхронное выполнение работы и последующий рендеринг пользовательского интерфейса - PullRequest
0 голосов
/ 01 сентября 2018

У меня есть фрагмент кода, который следует за рабочим процессом:

for index in 0..<self!.recordedData.count {
//Do work here that involves fetching data from coredata and prerendering an image for each index
}
reloadUIWithData()

Рабочий процесс предназначен для:

  1. Все работы в цикле for должны быть завершены

  2. ReloadUIWithData для выполнения.

Однако функция reloadUIWithData вызывается до завершения работы в цикле. Есть ли способ обеспечить полное завершение всей работы внутри цикла for, а затем выполнить reloadUIWithData?

Я пробовал следующее расширение DispatchQueue:

static func background(delay: Double = 0.0, background: (()->Void)? = nil, completion: (() -> Void)? = nil) {

    DispatchQueue.global(qos: .background).sync {
        background?()
        if let completion = completion {
            DispatchQueue.main.asyncAfter(deadline: .now() + delay, execute: {
                completion()
            })
        }
    }
}

С помощью:

DispatchQueue.background(delay: 0.01, background: {
for index in 0..<self!.recordedData.count {
    //Do work here that involves fetching data from coredata and rendering an image for each index
    }
}, completion:{
reloadUIWithData()
}

Но, похоже, это не работает масштабируемым образом. Хотя это работает, если параметр задержки установлен на что-то вроде 0,5, установка параметра задержки на небольшое значение, например 0,01, вызывает такую ​​же проблему. Я хотел бы использовать более надежный метод, чем установка случайной задержки, и надеюсь, что вся работа будет выполнена за этот промежуток времени.

Любая помощь будет принята с благодарностью. Спасибо!

1 Ответ

0 голосов
/ 01 сентября 2018

Для этого существует специальный API DispatchGroup. Однако это не делает асинхронные задачи синхронными. Это похоже на счетчик, который увеличивается на enter, уменьшается на leave и уведомляет notify о завершении всех задач в цикле ( counter == 0).

let group = DispatchGroup()
for index in 0..<self!.recordedData.count {
    group.enter()
    doAsynchronousStuff { result in
        // do something with result
        group.leave()
    }
}
group.notify(queue: DispatchQueue.main) {
    self.reloadUIWithData()
}
...