¿Cuál es la diferencia entre URLSession vs DispatchQueue.global().async + Data(contentsOf: ) en términos de descarga de imágenes desde direcciones URL de imágenes?
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 } } } Sé que URLSession puede cancelar o suspender la tarea.
Pero si uso Rx en su lugar, también puedo hacer lo mismo que arriba.
Tuve un experimento que dependía de qué QoS estaba usando.
Por cierto, .userInitiated QoS fue mucho más rápido que URLSession.
¿Cuál usan ustedes para algo como una tarea de descarga con un subproceso en segundo plano y por qué?
¿Hay algún tipo de maestro que pueda ayudarme específicamente?
URLSession ofrece un control de configuración mucho mayor, diagnóstico de fallas, cancelación, sesiones en segundo plano, capacidad de descargar directamente al almacenamiento persistente para minimizar el uso máximo de memoria, etc. URLSession y Data(contentsOf:) simplemente no son comparables en el conjunto de funciones.
Los Data(contentsOf:) bloquean innecesariamente los subprocesos de trabajo de GCD y también son susceptibles de uso indebido. También es bastante limitante y fácilmente te arrepentirás de la decisión en el futuro (por ejemplo, luego agregas algún proceso de autenticación; quieres personalizar los comportamientos de la memoria caché, quieres analizar y actuar sobre los códigos de estado en las respuestas, necesitas cancelar capacidades porque está recuperando imágenes para vistas de colección o tabla, etc.).
Es esclarecedor mirar la documentación de uno de los métodos init con una URL para Data , donde nos advierte:
Importante
No utilice este inicializador síncrono para solicitar direcciones URL basadas en la red. Para las URL basadas en la red, este método puede bloquear el hilo actual durante decenas de segundos en una red lenta, lo que resulta en una experiencia de usuario deficiente y, en iOS, puede provocar que su aplicación finalice.
En su lugar, para las URL que no son de archivo, considere usar el
dataTask(with:completionHandler:)de la claseURLSession. Consulte Obtención de datos del sitio web en la memoria para ver un ejemplo.
Sí, enviar esto a un subproceso en segundo plano soluciona muchas de las preocupaciones anteriores, pero Apple no solo sugirió "simplemente enviar esto a alguna cola en segundo plano", sino que recomendó explícitamente usar URLSession en su lugar. Si bien el uso de la cola global de GCD evita algunos de los problemas de los que Apple nos advierte anteriormente, también impone muchas limitaciones innecesarias. Si usa Data(contentsOf:) , esta es una decisión de la que probablemente se arrepentirá/refactorizará en el futuro. También podría usar URLSession ahora.
Con respecto a Data(contentsOf:) es apreciablemente más rápido cuando se usa .userInitiated , vs .default o URLSession , por lo general, la latencia de la red y el tiempo de transmisión empequeñecen cualquier factor relacionado con la prioridad de la cola, por lo que encuentro esa afirmación difícil de creer. De hecho, acabo de probar la descarga de 50 imágenes a través de GCD (usando tanto .default como .userInitiated ) y la velocidad no fue apreciablemente diferente a la del método URLSession .