【问题标题】:How can I make the screen stop freezing during extensive calculations?如何在大量计算期间使屏幕停止冻结?
【发布时间】:2016-04-05 11:23:08
【问题描述】:

好的,我要做的是更改某个图像的像素数据。我想使用每次循环作为进度条时向右移动的 UIView。但是,正在发生的事情是在计算过程中屏幕冻结,并且在计算完成之前没有任何反应。状态栏时钟也不会更新。有没有办法以某种方式将这些计算移到后台并仍然使用屏幕空间?

func lock() {

    let lockView =  UIImageView(image: self.photoBackgroundView.image!)
    var progressBar = UIView(frame: CGRectMake(-self.view.width,0,self.view.width,20)
    let increment = progressBar.width/self.photoBackgroundView.width
    var password = self.textField.text!
    if password == "" {
        password = " "
    }
    var currentIndex = 0



    let imageRect = CGRectMake(0, 0, self.photoBackgroundView.image!.size.width,self.photoBackgroundView.image!.size.height)

    UIGraphicsBeginImageContext(self.photoBackgroundView.image!.size)
    let context = UIGraphicsGetCurrentContext()

    CGContextSaveGState(context)
    CGContextDrawImage(context, imageRect, self.photoBackgroundView.image!.CGImage)
    for x in 0...Int(self.photoBackgroundView.image!.size.width) {
        print(x)

        progressBar.frame.origin.x += (CGFloat(x) * increment)
        self.view.addSubView(progressBar)


        for y in 0...Int(self.photoBackgroundView.image!.size.height) {
            let pointColor = lockView.layer.colorOfPoint(CGPoint(x: x, y: y))

            if currentIndex == Array(password.characters).count {
                currentIndex = 0
            }
            let red = encrypt(pointColor.components.red, passwordChar: Array(password.characters)[currentIndex], currentIndex: currentIndex, x: x, y: y)
            currentIndex++
            if currentIndex == Array(password.characters).count {
                currentIndex = 0
            }
            let green = encrypt(pointColor.components.green, passwordChar: Array(password.characters)[currentIndex], currentIndex: currentIndex, x: x, y: y)
            currentIndex++
            if currentIndex == Array(password.characters).count {
                currentIndex = 0
            }
            let blue = encrypt(pointColor.components.blue, passwordChar: Array(password.characters)[currentIndex], currentIndex: currentIndex, x: x, y: y)
            currentIndex++

            CGContextSetRGBFillColor(context, red, green, blue, pointColor.components.alpha)
            CGContextFillRect(context, CGRectMake(CGFloat(x), CGFloat(y), 1, 1))

        }



    }

    CGContextRestoreGState(context)
    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    self.photoBackgroundView.image = newImage
    self.slideView.addSubview(photoBackgroundView)
    self.view.addSubview(self.slideView)
}

【问题讨论】:

    标签: ios swift


    【解决方案1】:

    您可以在background thread 中进行这些计算。

    斯威夫特 2:

    let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
    dispatch_async(dispatch_get_global_queue(priority, 0)) {
        // Put the calculations here
        dispatch_async(dispatch_get_main_queue()) {
            // any updates of the UI need to be here which will be executed in the main thread after your background task completes. For example adding subviews
        }
    }
    

    斯威夫特 3:

    this answer

    【讨论】:

    • 请在答案中添加更多信息,而不仅仅是链接。
    • 我现在收到了我没有在主线程上收到的内存警告,有什么办法可以避免吗?
    • @SemAllush 仅供参考,您不应该使用来自后台线程的任何基于 UIView 的对象引用。当您回到第二个调度块中的主线程时,您需要将帧计算卸载为 CGRects,然后将它们写入您的progressBar。但是,根据我的经验,在线程之间传递UIImage 应该没问题。
    【解决方案2】:

    当您在主线程中进行大量计算时,您的屏幕或 UI 冻结。主线程负责更新 UI 元素,当你在 mainThread 上执行繁重的工作时,它会阻塞 mainThread 并冻结 UI,这是不推荐的。

    默认情况下,您编写的任何代码都将在主线程上运行。您需要分别在后台线程中编写代码,以便 mainThread 和 BGthread 可以同时运行。

    您可以使用 NSOperationQueue 或 GCD (Grand Central Dispatch) 轻松编写函数以在其他一些后台线程中运行。

    请点击this链接获取更多解释。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-30
      • 2021-05-06
      • 1970-01-01
      • 1970-01-01
      • 2012-12-11
      • 2014-10-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多