首页 > iOS中为什么更新UI没有反应?

iOS中为什么更新UI没有反应?

我写了一个测试使用与不使用Metal框架来进行矩阵计算的程序,其中包含一个UIProgressView来提示已经完成的计算任务的比例。
程序运行的时候其他的东西一切正常,但是UIProgressView的更新没有反应,任务进行中的时候进度条一直是0,完成之后一瞬间变成1.

for i in 0..<100 {
            
    dispatch_apply(100, queue, {
        (n: Int) in
        let imatrix = NKMatrix.matrixOfElementaryDaltonTransform(2, to: 3, amount: 0.4, n: 4)
        let omatrix = NKMatrix.matrixOfElementaryDaltonTransform(2, to: 3, amount: 0.4, n: 4)
        for _ in 0..<300 {
            omatrix.leftMultiply(imatrix)
        }
    })
    progressViewOfCPUOnlyTest.setProgress(Float(i+1) / 100.0, animated: true)
    outputLabelForCPUOnlyTest.text = "\(i)"
    print("\(i) percent \(progressViewOfCPUOnlyTest.progress)")
}
progressViewOfCPUOnlyTest.setProgress(1, animated: true)
let endTimeOfCPUOnlyTest = CACurrentMediaTime()
let CPUTimeConsumption = Int(endTimeOfCPUOnlyTest - startTimeOfCPUOnlyTest)
outputLabelForCPUOnlyTest.text = "\(CPUTimeConsumption)"

有关系的代码在这里,循环里面的更新UIProgressView和更新UILabelView都没有更新UI,尽管print成功地把文本打到了调试器输出上。同时根据调试器上面看到的信息,progressViewOfCPUOnlyTest.progress的值的确已经更新了。循环下面的代码更新UI都是成功的。
模拟器和真机都已经试过了,调试也没发现任何问题。这样的情况是为什么?怎么解决问题?


参考链接: Main event loop


你的所有处理都是在一次事件循环中做的,中间虽然多次更改了 UI 控件的数据 ,但最后只经过一次界面渲染的过程,自然以最后一次更改为准。

而且 dispatch_apply 会阻塞所在进程,如果任务太繁重导致明显界面卡顿会被系统结束。

你的代码大致应该这样写:

// 把阻塞主线程,导致你界面更新不及时的代码片段移出去
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
    for i in 0..<100 {
    
        // dispatch_apply 会阻塞所在进程直到本次矩阵计算完成,然后在它后面更新界面
        dispatch_apply(100, queue, {
            (n: Int) in
            let imatrix = NKMatrix.matrixOfElementaryDaltonTransform(2, to: 3, amount: 0.4, n: 4)
            let omatrix = NKMatrix.matrixOfElementaryDaltonTransform(2, to: 3, amount: 0.4, n: 4)
            for _ in 0..<300 {
                omatrix.leftMultiply(imatrix)
            }
        })
        
        // 一次矩阵计算完成,回主进程更新界面
        dispatch_async(dispatch_get_main_queue(), {
            progressViewOfCPUOnlyTest.setProgress(Float(i+1) / 100.0, animated: true)
            outputLabelForCPUOnlyTest.text = "\(i)"
            print("\(i) percent \(progressViewOfCPUOnlyTest.progress)")
        })
        
        // 继续循环
    }
})
【热门文章】
【热门文章】