在后台或主线程中执行更新时,设置GIF图像会阻止UI

时间:2016-03-28 01:35:52

标签: swift multithreading gif

我使用UIImageViewFLAnimatedImageobjective-c内设置了GIF图像。我目前正面临着在加载GIF图像时阻止用户界面的问题( 触摸未在图像前面显示的叠加UIView上注册,叠加视图被隐藏/显示在点按 )。我尝试在后台线程和主线程上更新图像,结果保持不变。我有什么问题吗?还是其他选择? (PS。我也有UITextView检测链接,怀疑这很重要)

的UITableViewCell

        //Main Thread blocks UI
    dispatch_async(dispatch_get_main_queue(), { () -> Void in
       cell.shotImg.setShotImage(self.shots[self.currentIndex])
         })
    //Background thread also blocks ui. See code below for background thread function
  backgroundThread(0.1, completion: {
      cell.shotImg.setShotImage(self.shots[self.currentIndex])
         })

FLAnimatedImage Extension

extension FLAnimatedImageView{

    func setRegularImage(url: String){
        self.af_setImageWithURL(NSURL(string: url)!)
    }

    func setGIFImage(url: String){
        let animatedImage = FLAnimatedImage(animatedGIFData: NSData(contentsOfURL: NSURL(string: url)!)!)
        self.animatedImage = animatedImage
    }

    func setShotImage(shot: Shots){
        var url: String!
        if(shot.images.hidpi != nil){
            url = shot.images.hidpi
        }else{
            url = shot.images.normal
        }

        if(shot.animated!){
            self.setGIFImage(url)
        }else{
            self.setRegularImage(shot.images.normal)
        }
    }
}

后台主题

func backgroundThread(delay: Double = 0.0, background: (() -> Void)? = nil, completion: (() -> Void)? = nil) {
    dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_USER_INITIATED.rawValue), 0)) {
        if(background != nil){ background!(); }

        let popTime = dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC)))
        dispatch_after(popTime, dispatch_get_main_queue()) {
            if(completion != nil){ completion!(); }
        }
    }
}

2 个答案:

答案 0 :(得分:2)

我的猜测是问题是:

 NSData(contentsOfURL: NSURL(string: url))

这不是你下载的东西(如果你正在做的那样)。使用NSURLSession。

答案 1 :(得分:1)

除非您有静态单元格,否则无法直接在后台线程中更新单元格。滚动时,表格视图将在屏幕上重复使用新显示的单元格。当后台任务完成时,单元格可能属于另一行。

相反,您应该在任务完成时将图像存储在数组中,然后调用reloadData(在主线程上)。然后,cellForRowAtIndexPath应该显示数组中的图像,或者如果尚未获取它,则在后台获取它(这将触发reloadData在完成时显示它)。