Chaining swift รวมผู้เผยแพร่และรับผลลัพธ์แต่ละรายการ
ในตัวอย่างด้านล่างฉันกำลังขอเครือข่ายเพื่อโหลดภาพยนตร์ประเภทต่างๆจากนั้นใช้สิ่งนั้นเพื่อโหลดภาพยนตร์ทั้งหมด ซิงก์จะส่งคืนผลลัพธ์ของภาพยนตร์เท่านั้น ฉันจะรับทั้งประเภทและภาพยนตร์ได้อย่างไร
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()