My swift package UnsplashSwiftUI has a view called UnsplashRandom that uses a StateObject to asynchronously fetch data from the UnsplashApi. However, if you implement the view twice on the same page they load the same image even though they should be different.
I also tried an ObservedObject as follows, UnsplashApi is my ObservableObject.
@StateObject var api = UnsplashApi() // Original
@ObservedObject var api = UnsplashApi() // This didn't work either
Edit: Marking the StateObject private also didn't work
Edit: This is the implementation of UnsplashApi
:
@MainActor
class UnsplashApi: ObservableObject {
enum LoadingState {
case idle
case loading
case loaded(UnsplashData)
case failed(Error)
}
@Published var state: LoadingState = .idle
func fetchImage(clientId: String, query: String, orientation: String) async {
let baseUrl = URL(string: "https://api.unsplash.com/")
guard var components = URLComponents(url: baseUrl!.appendingPathComponent("photos/random"), resolvingAgainstBaseURL: true)
else { state = .failed(URLError(.badURL)); return }
components.queryItems = [URLQueryItem(name: "client_id", value: clientId)]
if query != "" {components.queryItems?.append(URLQueryItem(name: "query", value: query))}
if orientation != "" {components.queryItems?.append(URLQueryItem(name: "orientation", value: orientation))}
guard let url = components.url else { state = .failed(URLError(.badURL)); return }
self.state = .loading
do {
let (data, _) = try await URLSession.shared.data(from: url)
let response = try JSONDecoder().decode(UnsplashData.self, from: data)
self.state = .loaded(response)
} catch {
state = .failed(error)
}
}
}
Your fetchImage
method uses URLSession.shared
. The shared URLSession
uses a URLCache
. So it's likely that the response to your first request for https://api.unsplash.com/photos/random
is being stored in the cache and subsequent requests return the cached response.
Try using URLSession(configuration: .ephemeral)
instead of URLSession.shared
.