В чем разница между URLSession и GCD с точки зрения загрузки изображения из URL изображения? - PullRequest
0 голосов
/ 25 марта 2019

В чем разница между URLSession vs DispatchQueue.global().async + Data(contentsOf: ) с точки зрения загрузки изображений из URL-адресов изображений?

func loadImageWithUrlSession() {
    guard let url = URL(string: IMAGE_URL) else { return }
    URLSession.shared.dataTask(with: url) { (data, response, error) in
        if let error = error {
            print(error.localizedDescription)
            return
        }
        guard let data = data else { return }
        let image = UIImage(data: data)
        DispatchQueue.main.async { [weak self] in
            guard let self = self else { return }
            self.urlSessionImageView.image = image
        }
    }.resume()
}

func loadImageWithGCD() {
    DispatchQueue.global(qos: .background).async {
        guard
            let url = URL(string: self.IMAGE_URL),
            let data = try? Data(contentsOf: url) else {
                return
        }
        let image = UIImage(data: data)

        DispatchQueue.main.async { [weak self] in
            guard let self = self else { return }
            self.gcdImageView.image = image
        }
    }
}

Я знаю, что URLSession может отменить или приостановить задачу.
Но если я вместо этого использую Rx, я могу сделать то же самое, что и выше.

У меня был эксперимент, и он зависел от того, какое QoS я использую.
Кстати, .userInitiated QoS был намного быстрее, чем URLSession.
Какую из них вы, ребята, используете для задачи загрузки с фоновым потоком и почему?

Есть ли добрый учитель, который может мне помочь конкретно?

1 Ответ

2 голосов
/ 25 марта 2019

URLSession предлагает гораздо больший контроль конфигурации, диагностику сбоев, отмену, фоновые сеансы, возможность загрузки непосредственно в постоянное хранилище для минимизации пикового использования памяти и т. Д. URLSession и Data(contentsOf:) просто не сравнимы по набору функций.

Синхронный Data(contentsOf:) излишне блокирует рабочие потоки GCD и также подвержен неправильному использованию.Это также весьма ограничивает, и вы легко пожалеете о своем решении в будущем (например, позже вы добавите какой-нибудь процесс аутентификации; вы хотите настроить поведение кэша, вы захотите проанализировать коды действий в ответах и ​​действовать на них, вам нужно отменитьвозможности, потому что вы извлекаете изображения для коллекций или табличных представлений и т. д.).

Очень интересно посмотреть на документацию для одного из init с методами URL для Data, где он предупреждает нас:

Важно

Не используйте этот синхронный инициализатор для запроса сетевых URL-адресов.Для сетевых URL-адресов этот метод может блокировать текущий поток на десятки секунд в медленной сети, что приведет к ухудшению работы пользователя, а в iOS может привести к прекращению работы вашего приложения.

Вместо этого длянефайловые URL, рассмотрите возможность использования метода dataTask(with:completionHandler:) класса URLSession.См. Выборка данных веб-сайта в память для примера.

Да, отправка этого в фоновый поток решает многие из вышеуказанных проблем, но Apple не просто предложила «просто отправитьэто к некоторой фоновой очереди », но вместо этого явно рекомендуется использовать URLSession.Хотя использование глобальной очереди GCD позволяет избежать некоторых проблем, о которых Apple предупреждает нас выше, оно также накладывает много ненужных ограничений.Если вы используете Data(contentsOf:), это решение, о котором вы, скорее всего, пожалеете / изменится в будущем.Вы также можете использовать URLSession сейчас.


Что касается Data(contentsOf:), заметно более быстрого при использовании подхода .userInitiated, против .default или URLSession, обычно это карлики задержки в сети и времени передачилюбые факторы, связанные с приоритетом очереди, поэтому я считаю, что в это утверждение трудно поверить.На самом деле, я только что протестировал загрузку 50 изображений через GCD (используя .default и .userInitiated), и скорость не заметно отличалась от подхода URLSession.

...