低分辨率图像加载时间过长

Low res image taking too long to load

使用 Facebook Graph API,我检索到 200x200 个人资料图片的字符串 URL,我想在 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()
}

您应该将所有 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 的强引用。这允许视图控制器在用户关闭它时解除分配,然后完成例程 return 提前而不做任何不必要的工作。

此代码是非法的:

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

住手!您正在后台线程 上设置 UIImageView 的图像 。不不不。 UIKit 不是线程安全的。您必须进入主线程才能执行此操作。 (您最终确实进入了代码中的主线程,但为时已晚。)