如何修改我的swift代码,使其在后台运行而不会阻止UI?

时间:2016-09-19 21:38:08

标签: ios swift

我有一个UITableViewController,每个单元格上都有一个UIImageView。此图像视图中填充了存储在服务器上的视频的快照。至于现在我的代码如下:

func tableView(detailsPanel: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = detailsPanel.dequeueReusableCellWithIdentifier("cell") as! DetailsCell

    let test:SingleTest =  self.items[indexPath.row] as! SingleTest

//this code hangs up the UI for each cell:
    do {
        let asset = AVURLAsset(URL: NSURL(string: test.video)!, options: nil)
        let imgGenerator = AVAssetImageGenerator(asset: asset)
        imgGenerator.appliesPreferredTrackTransform = true
        let cgImage = try imgGenerator.copyCGImageAtTime(CMTimeMake(0, 1), actualTime: nil)
        let uiImage = UIImage(CGImage: cgImage)
        let imageView = UIImageView(image: uiImage)
        cell.testPhoto.image = uiImage
    } catch  {
        print("Error generating thumbnail: \(error)")
    }

}

如何修改我的代码,以便do catch块中的所有内容都不会阻止用户界面并在后台运行?

=== EDIT

按照您的建议后,我修改了我的代码,以便现在do-catch语句被调度包围:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)) {
    var uiImage = UIImage()
    do {
        let asset = AVURLAsset(URL: NSURL(string: test.video)!, options: nil)
        let imgGenerator = AVAssetImageGenerator(asset: asset)
        imgGenerator.appliesPreferredTrackTransform = true
        let cgImage = try imgGenerator.copyCGImageAtTime(CMTimeMake(0, 1), actualTime: nil)
        uiImage = UIImage(CGImage: cgImage)
        //let imageView = UIImageView(image: uiImage)
    } catch  {
        print("Error generating thumbnail: \(error)")
    }

    dispatch_async(dispatch_get_main_queue()) {
        cell.testPhoto.image = uiImage
    }
}

现在它似乎正在工作,但它不会缓存图像,每次我滚动表格时,它再次取出照片......避免它的最佳方法是什么?

1 个答案:

答案 0 :(得分:1)

以下是关于如何完成的粗略概念,代码可能不起作用,但它为您提供了一个开始。

在类中初始化队列:

        let processQueue = DispatchQueue(label: "myQueue", attributes: [])

将处理发送到此队列并在完成后发送回main:

func tableView(detailsPanel: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = detailsPanel.dequeueReusableCellWithIdentifier("cell") as! DetailsCell

    let test:SingleTest =  self.items[indexPath.row] as! SingleTest

    processQueue.async {

        let image: CGImage?

        do {
            let asset = AVURLAsset(URL: NSURL(string: test.video)!, options: nil)
            let imgGenerator = AVAssetImageGenerator(asset: asset)
            imgGenerator.appliesPreferredTrackTransform = true
            image = try imgGenerator.copyCGImageAtTime(CMTimeMake(0, 1), actualTime: nil)

        } catch  {
            print("Error generating thumbnail: \(error)")
        }

        guard let cgImage = image else { return }

        DispatchQueue.main.async { [weak self] in

            guard let `self` = self else { return }

            //TODO: perform some checking that current cell is still the intended cell

            let uiImage = UIImage(cgImage: cgImage)
            cell.testPhoto.image = uiImage

        }

    }
}