Обновление пользовательского интерфейса при работе с OperationQueue
У меня есть следующая настройка очереди операций:
let queue = OperationQueue()
queue.name = "com.company.myQueue"
queue.qualityOfService = .userInitiated
queue.maxConcurrentOperationCount = 64
...
var current = 0
var totalCount = someArray.count
for i in someArray {
...
let op = BlockOperation {
... // do some database queries
current += 1
}
op.completionBlock = {
DispatchQueue.main.async {
let nData: [String: CGFloat] = ["value": CGFloat(current/totalCount)]
NotificationCenter.default.post(name:Notification.Name(rawValue: "update"), object: nil, userInfo: nData)
}
queue.addOperation(op)
}
В моем ViewController
Я слушаю уведомление и обновляю UILabel
с процентом. Проблема в том, что я не получаю промежуточных значений...0
прямо к 100
после того, как все операции будут выполнены.
Что я делаю не так?
Благодарность
2 ответа
Проблема в CGFloat(current / totalCount)
. Сначала выполняется целочисленная математика, а затем она преобразуется в число с плавающей запятой. Вы должны перевернуть это, чтобыCGFloat(current) / CGFloat(totalCount)
.
Вы можете переместить функцию отправки уведомлений прямо в op.completionBlock (не отправляя ее в основной поток).
Изменить (комментарии):
let queue = OperationQueue()
queue.name = "com.company.myQueue"
queue.qualityOfService = .userInitiated
queue.maxConcurrentOperationCount = 64
let array = ["", "", "", "", "", ]
var current = 0
var totalCount = array.count
for _ in array {
let op = BlockOperation { current += 1 ; print(current) }
op.completionBlock = {
DispatchQueue.main.async {
NotificationCenter.default.post(name: Notification.Name(rawValue: "update"), object: nil, userInfo: ["value": CGFloat(current / totalCount)])
}
}
queue.addOperation(op)
}
NotificationCenter.default.addObserver(forName: Notification.Name(rawValue: "update"), object: nil, queue: nil) { (notification) in
print(notification.userInfo)
}
Редактировать 2 (комментарии): вы должны сделать свой процент, используя текущее значение float и totalCount, прежде чем разделить их.
CGFloat(current) / CGFloat(totalCount)
'''