Asynchronously fetching book information from ISBN using the Google Books API in SwiftUI

Solution 1:

There are a few issues.

  • Never try! in a method which throws, hand the error over.
  • Never print error.localizedDescription in a decoding context, print always just the error instance.
  • Never force unwrap URLs composed with String Interpolation, throw an error on failure.

The main issue is that you have to encode the URL by adding percent encoding


private func fetchBook(id identifier: String) async throws -> GoogleBook {
    guard let encodedString = "https://www.googleapis.com/books/v1/volumes?q={\(identifier)}"
                              .addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed),
          let url = URL(string: encodedString) else { throw URLError(.badURL)}
    let (data, _) = try await URLSession.shared.data(from: url)
    return try JSONDecoder().decode(GoogleBook.self, from: data)
}

If you'll face any DecodingError, the error message will tell you exactly why and where it occurred

To show a progress view add a view model with a @Published property representing a state, an enum with associated values for example this generic enum

enum LoadingState<Value> {
    case loading(Double)
    case loaded(Value)
}

The associated Double value can pass the progress percentage.