【问题标题】:Updating UI when working with OperationQueue使用 OperationQueue 时更新 UI
【发布时间】:2020-09-15 21:23:01
【问题描述】:

我有一个操作队列设置如下:

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

我做错了什么?

谢谢

【问题讨论】:

  • 无关,但我可能会建议extension Notification.Name { static let update = Notification.Name(rawValue: "update") }。然后你可以做NotificationCenter.default.post(name: .update, object: nil, userInfo: nData)之类的事情。我建议不要将maxConcurrentOperation 计数为 64,因为如果这样做,您很容易耗尽有限数量的工作线程。您通常应该保持在 64 岁以下。

标签: swift blockoperation operationqueue


【解决方案1】:

问题是CGFloat(current / totalCount)。这首先进行整数数学运算,然后将其转换为浮点数。你应该把它翻转到CGFloat(current) / CGFloat(totalCount)

【讨论】:

    【解决方案2】:

    您可以直接在 op.completionBlock 中移动通知发送函数(无需在主线程中调度它)。

    编辑(cmets):

    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 (cmets) : 您应该在除以之前通过浮动转换 current 和 totalCount 来计算百分比。

    CGFloat(current) / CGFloat(totalCount)
    '''
    

    【讨论】:

    • 不会改变结果。
    • 如果:您的数组大于 1 个条目?
    • 它有大约 6000 个元素
    • 在通知发送电话的同一位置带有print(current/totalCount):只调用一次?
    • 没有为每个元素调用,只是声明0.0 done0.0 done - 然后最后一个条目是1.0 done
    猜你喜欢
    • 1970-01-01
    • 2011-08-29
    • 2019-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-25
    • 1970-01-01
    相关资源
    最近更新 更多