Fetching an Image with URLSession
Fetching an image from the internet is a common task in iOS development. This snippet shows how to do it cleanly using URLSession
in Swift, with best practices like error handling and separation of concerns.
Details
URL: 🔗 https://developer.apple.com/documentation/foundation/urlsession
Source: 🔗 Book: Swift Programming
Author: [Author Name]
Tags:
Networking
, URLSession
, Swift
, iOS
, Clean Code
Platforms Supported: iOS, macOS
Swift Version: 5.x
Code​
import Foundation
import UIKit
class ImageDownloader {
static func downloadImage(from urlString: String, completion: @escaping (Result<UIImage, Error>) -> Void) {
guard let url = URL(string: urlString) else {
completion(.failure(NetworkError.invalidURL))
return
}
let session = URLSession(configuration: .default)
let request = URLRequest(url: url)
let task = session.dataTask(with: request) { data, response, error in
if let error = error {
completion(.failure(error))
return
}
guard let data = data, let image = UIImage(data: data) else {
completion(.failure(NetworkError.noData))
return
}
completion(.success(image))
}
task.resume()
}
enum NetworkError: Error {
case invalidURL
case noData
}
}
Usage​
class ImageViewController: UIViewController {
let imageView = UIImageView()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(imageView)
imageView.frame = view.bounds
ImageDownloader.downloadImage(from: "https://imgs.xkcd.com/comics/api.png") { [weak self] result in
DispatchQueue.main.async {
switch result {
case .success(let image):
self?.imageView.image = image
case .failure(let error):
print("Failed to download image: \(error)")
// Handle error (e.g., show an alert to the user)
}
}
}
}
}
Discussion​
This refactored snippet demonstrates how to fetch an image using URLSession
while adhering to clean code principles. By separating concerns, the ImageDownloader
class handles the networking logic, and the ImageViewController
focuses on UI updates. This approach improves code reusability, maintainability, and testability.
Key Points​
- Error Handling: Uses the
Result
type for clear success and failure cases. - Code Reusability: Networking logic is encapsulated in a separate class.
- Avoiding Force Unwrapping: Optional values are safely unwrapped using
guard
. - Separation of Concerns: The view controller is responsible only for UI logic.
Notes​
- Flexibility: This pattern can be extended to fetch other types of data by adjusting the parsing logic in the
ImageDownloader
class. - Compatibility: Suitable for iOS and macOS with Swift 5.x.