swift - iOS中为什么更新UI没有反应?
PHP中文网
PHP中文网 2017-04-17 17:29:21
[iOS讨论组]

我写了一个测试使用与不使用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都是成功的。
模拟器和真机都已经试过了,调试也没发现任何问题。这样的情况是为什么?怎么解决问题?

PHP中文网
PHP中文网

认证0级讲师

全部回复(1)
伊谢尔伦

参考链接: 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)")
        })
        
        // 继续循环
    }
})
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号