在Swift中快速更新UIView背景颜色?

时间:2017-03-09 13:43:37

标签: ios iphone swift

当UIView的背景颜色应该改变颜色时,我有一些时间。该数组保存0-10000ms的值,其中每个索引是第一次更改和当前更改之间的持续时间。我已经实现了一个循环来在预定的时间执行任务,并且使用print语句,它似乎正在工作。但是,背景颜色仅更改为最后一种颜色,而不是连续更改。

我相信这是因为在循环完成之前,背景颜色不会更新。这是否正确,如果是,我该如何解决这个问题?

    sendingView.backgroundColor = UIColor.black
    let startingTime = getCurrentMillis()
    var found = false
    for time in receivingMsgData {
        while(!found) {
            let curDuration = getCurrentMillis() - startingTime
            if curDuration > time {
                if(sendingView.backgroundColor == UIColor.black) {
                    sendingView.backgroundColor = UIColor.white
                    print("playing at \(getCurrentMillis()-startingTime) turning white")
                } else {
                    sendingView.backgroundColor = UIColor.black
                    print("playing at \(getCurrentMillis()-startingTime) turning black")
                }
                found = true
            }
        }
        found = false
    }

3 个答案:

答案 0 :(得分:2)

尝试这样的事情

DispatchQueue.global(qos: .userInitiated).async {
    let delay:TimeInterval = 0.01 // Seconds
    for index in 0..<100 {
        if index % 2 == 0 {
            Thread.sleep(forTimeInterval: delay)
            DispatchQueue.main.async {
                self.view.backgroundColor = UIColor.white
                print("white")
            }
        }else{
            Thread.sleep(forTimeInterval: delay)
            DispatchQueue.main.async {
                self.view.backgroundColor = UIColor.black
                print("black")
            }
        }
    }
}

在异步线程中执行操作并更改主线程上的颜色 你在主线程中做了很多事情导致它挂起,同时放一些延迟,以便用户可以查看动画

在你的案例中尝试这样的事情

let delay:TimeInterval = 0.01 // Seconds
sendingView.backgroundColor = UIColor.black
let startingTime = getCurrentMillis()
var found = false
DispatchQueue.global(qos: .userInitiated).async {
    for time in receivingMsgData {
        while(!found) {
            let curDuration = getCurrentMillis() - startingTime
            if curDuration > time {
                if(sendingView.backgroundColor == UIColor.black) {
                    Thread.sleep(forTimeInterval: delay)
                    DispatchQueue.main.async {
                        sendingView.backgroundColor = UIColor.white
                        print("playing at \(getCurrentMillis()-startingTime) turning white")
                    }
                } else {
                    Thread.sleep(forTimeInterval: delay)
                    DispatchQueue.main.async {
                        sendingView.backgroundColor = UIColor.black
                        print("playing at \(getCurrentMillis()-startingTime) turning black")
                    }
                }
                found = true
            }
        }
        found = false
    }
}

答案 1 :(得分:1)

您设置颜色时,您发布的代码会阻止主线程或操作不在主线程上。在完成整个循环的执行或经过一段时间之后,这两种情况很可能不会导致任何变化。

当您处理某些时间安排的数据时,可能与屏幕更新的速度无关,您需要在屏幕刷新时按需提供颜色。

在您的情况下,我建议使用显示链接CADisplayLink,该链接用于在屏幕刷新时触发。您甚至可以从显示链接本身开始获取当前时间值。经过的时间可以与您在代码中使用curDuration的方式相同。假设代码的其余部分正常工作。

答案 2 :(得分:0)

  

我相信这是因为在循环完成之前,背景颜色不会更新。这是正确的

是的,确实如此。直到主线程上的所有代码完成并且提交了CATransaction之后才会进行绘图。你需要做两件事之一:

  • 在后台线程上运行耗时的代码,进入主线程只与界面通信并设置颜色。

  • 使用某种形式的延迟来延长主线程的时间,以便在继续“循环”之前进行绘图。