Hızlı zincirleme yayıncıları birleştirir ve her sonucu alır
Aşağıdaki örnekte, farklı film türlerini yüklemek için bir ağ isteğinde bulunuyorum, ardından bunu tüm filmleri yüklemek için kullanıyorum. Lavabo yalnızca film sonuçlarını döndürür. Hem türleri hem de filmleri nasıl alabilirim?
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)
}
}
Yanıtlar
Türleri ve filmleri nasıl toplamak istediğinize bağlıdır.
Örneğin, bir tür ve bu türdeki filmlerin bir listesini ister misiniz? Sonuç bir dizi olabilir (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()
Veya, bir dizi (Genre, Movie)
tuple istiyorsanız , bu benzer bir yaklaşımdır, ancak .flatMap
ayrı ayrı filmler elde etmek için ek bir seviye vardır.
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()
Yorum sorunuzu cevaplamak için, güncellenmiş Genre
olanı iade etmek istersiniz , bir demet döndürmek yerine onu iade edebilirsiniz. Çünkü akılda Ayı Genre
olan bir yapıdır, nesnenin bir değişken kopyasını oluşturmak gerekir ( genre
mevcut flatMap
, kopyalama güncellemek ve dönüş o kapanması bir sabittir):
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()