Изображение с низким разрешением занимает слишком много времени для загрузки

Используя Facebook Graph API, я получил строковый URL-адрес 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 ответа

Решение

Вы должны переместить все 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, Это позволяет контроллеру представления освободить, если пользователь отклоняет его, и процедуры завершения тогда возвращаются рано, не делая никакой ненужной работы.

Этот код является незаконным:

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

Стоп! Вы устанавливаете изображение UIImageView в фоновом потоке. Нет нет нет. UIKit не является потокобезопасным. Вы должны попасть в основной поток, чтобы сделать это. (В конечном итоге вы попадаете в основной поток в своем коде, но делаете это слишком поздно.)

Другие вопросы по тегам