Created
January 22, 2023 22:21
-
-
Save soapyigu/311797657f59a795570b6806c4dc5c40 to your computer and use it in GitHub Desktop.
Get an image from a url
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Convention: using GCD and URLSession | |
import Foundation | |
import UIKit | |
enum NetworkError: Error { | |
case invalidURL | |
case noData | |
case failedRequest | |
case returnedError | |
} | |
protocol NetworkManagable { | |
func get(_ url: String?, _ completion: @escaping (Result<Data, NetworkError>) -> Void) | |
} | |
class NetworkManager: NetworkManagable { | |
private let session = URLSession.shared | |
func get(_ url: String?, _ completion: @escaping (Result<Data, NetworkError>) -> Void) { | |
guard let urlStr = url, let realURL = URL(string: urlStr) else { | |
completion(.failure(.invalidURL)) | |
return | |
} | |
let dataTask = session.dataTask(with: realURL) { data, response, error in | |
guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else { | |
completion(.failure(.failedRequest)) | |
return | |
} | |
guard error == nil else { | |
completion(.failure(.returnedError)) | |
return | |
} | |
guard let data = data else { | |
completion(.failure(.noData)) | |
return | |
} | |
completion(.success(data)) | |
} | |
dataTask.resume() | |
} | |
} | |
enum ServiceError: Error { | |
case networkError(NetworkError) | |
case decodeError | |
} | |
class ImageService { | |
private var networkManager: NetworkManagable | |
init(networkManager: NetworkManagable = NetworkManager()) { | |
self.networkManager = networkManager | |
} | |
func getImage(_ url: String?, _ completion: @escaping (Result<UIImage, ServiceError>) -> Void) { | |
networkManager.get(url) { result in | |
switch result { | |
case .success(let data): | |
if let uiImage = UIImage(data: data) { | |
completion(.success(uiImage)) | |
} else { | |
completion(.failure(.decodeError)) | |
} | |
case .failure(let networkError): | |
completion(.failure(.networkError(networkError))) | |
} | |
} | |
} | |
} | |
// SwiftUI | |
// init(url:scale:) | |
AsyncImage(url: URL(string: urlStr)) | |
.frame(width: 200, height: 200) | |
// init(url:scale:content:placeholder:) | |
AsyncImage(url: URL(string: "https://example.com/icon.png")) { image in | |
image.resizable() | |
} placeholder: { | |
ProgressView() | |
} | |
.frame(width: 50, height: 50) | |
// init(url:scale:transaction:content:) | |
AsyncImage(url: URL(string: "https://example.com/icon.png")) { phase in | |
if let image = phase.image { | |
image // Displays the loaded image. | |
} else if phase.error != nil { | |
Color.red // Indicates an error. | |
} else { | |
Color.blue // Acts as a placeholder. | |
} | |
} | |
// Use the latest structured concurrency | |
import Foundation | |
import UIKit | |
enum NetworkError: Error { | |
case invalidURL | |
case noData | |
case invalidServerResponse | |
} | |
protocol NetworkManagable { | |
func get(_ url: String?) async throws -> Data | |
} | |
class NetworkManager: NetworkManagable { | |
private let session = URLSession.shared | |
func get(_ url: String?) async throws -> Data { | |
guard let urlStr = url, let realURL = URL(string: urlStr) else { | |
throw NetworkError.invalidURL | |
} | |
let (data, response) = try await session.data(for: URLRequest(url: realURL)) | |
guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else { | |
throw NetworkError.invalidServerResponse | |
} | |
guard !data.isEmpty else { | |
throw NetworkError.noData | |
} | |
return data | |
} | |
} | |
enum ImageServiceError: Error { | |
case unsupportedImage | |
} | |
class ImageService { | |
private var networkManager: NetworkManagable | |
init(networkManager: NetworkManagable = NetworkManager()) { | |
self.networkManager = networkManager | |
} | |
func getImage(for url: String?) async throws -> UIImage { | |
let data = try await networkManager.get(url) | |
if let image = UIImage(data: data) { | |
return image | |
} else { | |
throw ImageServiceError.unsupportedImage | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment