低分辨率图像需要太长时间才能加载

时间:2016-08-12 15:10:58

标签: swift nsurlsession dispatch-async

使用Facebook Graph API,我检索了一个200x200个人资料图片的字符串网址,我想在UIImageView中显示。我已经成功地做到了这一点,但我注意到图像在屏幕上显示可能需要长达10秒的时间。关于如何优化它,任何人都可以给我一些指示(没有双关语)吗?

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)

    NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: self.profilePictureUrl)!, completionHandler: { (data, response, error) ->
        Void in
        self.profilePictureImageView.image = UIImage(data: data!)
        self.profilePictureImageView.layer.cornerRadius = self.profilePictureImageView.frame.size.width / 2;
        self.profilePictureImageView.clipsToBounds      = true

        dispatch_async(dispatch_get_main_queue(), { () -> Void in
            self.view.addSubview(self.profilePictureImageView)
        })

    }).resume()
}

2 个答案:

答案 0 :(得分:3)

您应该将所有UIView次调用(以及您在UIImageView上设置的任何内容)移动到主线程上,因为UIKit大部分都不是线程安全的。您可以在后台线程上实例化UIImage以进行性能优化,请尝试以下操作:

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)

    let url = NSURL(string: self.profilePictureUrl)!

    NSURLSession.sharedSession().dataTaskWithURL(
        url,
        completionHandler: { [weak self] (data, response, error) -> Void in
            guard let strongSelf = self else { return }

            // create the UIImage on the background thread
            let image = UIImage(data: data!)

            // then jump to the main thread to modify your UIImageView
            dispatch_async(dispatch_get_main_queue(), { [weak self] () -> Void in
                guard let strongSelf = self else { return }

                let profilePictureImageView = strongSelf.profilePictureImageView

                profilePictureImageView.image = image
                profilePictureImageView.layer.cornerRadius = profilePictureImageView.frame.size.width / 2;
                profilePictureImageView.clipsToBounds = true

                strongSelf.view.addSubview(profilePictureImageView)
            })
        }
    ).resume()
}

另请注意,我weak - 您对self的引用。在完成例程调用之前,无法保证用户没有解除启动此代码的视图控制器,因此您需要确保没有保留对self的强引用。这允许视图控制器在用户解除它时解除分配,然后完成例程然后提前返回而不做任何不必要的工作。

答案 1 :(得分:0)

此代码非法:

NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: self.profilePictureUrl)!, completionHandler: { (data, response, error) ->
    Void in
    self.profilePictureImageView.image = UIImage(data: data!)

停止!您正在后台线程上设置UIImageView的图像。不不不。 UIKit不是线程安全的。你必须进入主线程才能做到这一点。 (你最终会进入代码中的主线程,但是你做得太晚了。)