I got this to work after reading some of the comments here and doing more research/experimentation. Here’s what I changed:
In the URL extension, I left it pretty much the same as I find it more readable this way. I did push the timeoutInterval
to a parameter:
// Extensions/URL.swift
import Foundation
extension URL {
func isReachable(timeoutInterval: Double, completion: @escaping (Bool) -> Void) {
var request = URLRequest(url: self)
request.httpMethod = "HEAD"
request.timeoutInterval = timeoutInterval
URLSession.shared.dataTask(with: request) { data, response, error in
if error != nil {
DispatchQueue.main.async {
completion(false)
}
return
}
if let httpResp: HTTPURLResponse = response as? HTTPURLResponse {
DispatchQueue.main.async {
completion(httpResp.statusCode == 200)
}
return
} else {
DispatchQueue.main.async {
completion(false)
}
return
}
}.resume()
}
}
I modified my BookViewModel
to make two of the properties to @Published
and used the URL extension there:
// View Models/BookViewModel.swift
import Foundation
class BookViewModel: ObservableObject {
@Published var book: Book
@Published var imageURLIsReachable: Bool
@Published var imageURL: URL?
init(book: Book) {
self.book = book
self.imageURL = nil
self.imageURLIsReachable = false
if let url = book.image_url {
self.imageURL = URL(string: url)
self.imageURL!.isReachable(timeoutInterval: 1.0) { result in
self.imageURLIsReachable = result
}
}
}
// Rest of properties...
}
Now my BookThumbnailView
can properly display the conditional views:
// Views/BookThumbnailView.swift
import SwiftUI
import Foundation
import KingfisherSwiftUI
struct BookThumbnailView: View {
@ObservedObject var viewModel: BookViewModel
private var book: Book {
viewModel.book
}
@ViewBuilder
var body: some View {
if let imageURL = self.viewModel.imageURL {
if self.viewModel.imageURLIsReachable {
KFImage(imageURL)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(maxWidth: 70)
.cornerRadius(8)
} else {
ErrorBookThumbnailView()
}
} else {
DefaultBookThumbnailView()
}
}
}
Whew, that was quite the learning experience. Thanks to everyone who commented with suggestions and provided hints on where to look!
CLICK HERE to find out more related problems solutions.