चेंजिंग स्विफ्ट प्रकाशकों को जोड़ती है और प्रत्येक परिणाम प्राप्त करती है
नीचे दिए गए उदाहरण में, मैं विभिन्न मूवी शैलियों को लोड करने के लिए नेटवर्क अनुरोध कर रहा हूं, फिर सभी फिल्मों को लोड करने के लिए। सिंक केवल फिल्म परिणाम देता है। मैं दोनों शैलियों और फिल्मों को कैसे प्राप्त कर सकता हूं?
struct Genre: Codable, Identifiable{
let id: Int
let name: String
var movies: [Movie]?
}
struct Movie: Codable, Hashable, Identifiable {
let title: String
let id: Int
let posterPath: String?
let backdropPath : String?
var tagline: String?
}
loadGenres() is AnyPublisher<[Genre], Error>
fetchMoviesIn() is AnyPublisher<[Movie], Error>
class GenresViewModel: ObservableObject{
@Published var genres = [Genre]()
@Published var movies = [Movie]()
var requests = Set<AnyCancellable>()
init(){
NetworkManager.shared.loadGenres()
.flatMap{ genres in
genres.publisher.flatMap{ genre in
NetworkManager.shared.fetchMoviesIn(genre)
}
}
.collect()
.retry(1)
.receive(on: DispatchQueue.main)
.sink(receiveCompletion: { completion in
switch completion{
case .finished:
print("Finished loading all movies in every genre")
case .failure(let error):
print("Error: \(error)")
}
}, receiveValue: { [self] values in
let allMovies = values.joined()
self.movies = allMovies.map{$0}
})
.store(in: &self.requests)
}
}
जवाब
निर्भर करता है कि आप शैलियों और फिल्मों को कैसे इकट्ठा करना चाहते हैं।
उदाहरण के लिए, क्या आप उस शैली में एक शैली और फिल्मों की सूची चाहते हैं? परिणाम की एक सरणी हो सकती है (Genre, [Movies])
।
NetworkManager.shared.loadGenres()
.flatMap { genres in
genres.publisher.setFailureType(to: Error.self)
}
.flatMap { genre in
NetworkManager.shared.fetchMoviesIn(genre)
.map { movies in (genre, movies) }
}
.collect()
या, यदि आप (Genre, Movie)
टुपल्स की एक सरणी चाहते हैं , तो यह एक समान दृष्टिकोण है, लेकिन .flatMap
व्यक्तिगत फिल्में प्राप्त करने के लिए एक अतिरिक्त स्तर के साथ
NetworkManager.shared.loadGenres()
.flatMap { genres in
genres.publisher.setFailureType(to: Error.self)
}
.flatMap { genre in
NetworkManager.shared.fetchMoviesIn(genre)
.flatMap { movies in
movies.publisher.setFailureType(to: Error.self)
}
.map { movie in (genre, movie) }
}
.collect()
आपके टिप्पणी के सवाल का जवाब देने के लिए, आप अपडेट लौटना चाहते हैं Genre
, आप एक टपल वापस करने के बजाय वापस लौट सकते हैं। ध्यान रखें कि चूंकि Genre
एक संरचना है, आपको ऑब्जेक्ट की एक वैरिएबल कॉपी बनाने की आवश्यकता होगी ( क्लोजर genre
में उपलब्ध flatMap
एक स्थिर है), कॉपी को अपडेट करें, और उसे वापस करें:
NetworkManager.shared.loadGenres()
.flatMap { genres in
genres.publisher.setFailureType(to: Error.self)
}
.flatMap { genre in
NetworkManager.shared.fetchMoviesIn(genre)
.map { movies -> Genre in
var genreCopy = genre
genreCopy.movies = movies
return genreCopy
}
}
.collect()