게시자를 신속하게 결합하고 각 결과를 수신
Aug 18 2020
아래 예에서는 다양한 영화 장르를로드하도록 네트워크 요청을 한 다음이를 사용하여 모든 영화를로드합니다. 싱크는 영화 결과 만 반환합니다. 장르와 영화를 모두받을 수있는 방법은 무엇입니까?
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)
}
}
답변
2 NewDev Aug 18 2020 at 17:03
장르와 영화를 수집하는 방법에 따라 다릅니다.
예를 들어 장르와 해당 장르의 영화 목록을 원하십니까? 결과는의 배열이 될 수 있습니다 (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()