Building Netflix App in Swift 5 and UIKit - (Xcode 13, 2021) - Episode 8 - Upcoming Controller
import Foundation
import Combine
class NewAndHotViewModel {
let upcomingMovieModels: CurrentValueSubject<[ContentModel], Never> = .init([])
private var cancellables = Set<AnyCancellable>()
init() {
addSubscription()
}
private func addSubscription() {
APICaller
.shared
.getUpcomingContents(with: .movie)
.sink { completion in
switch completion {
case .failure(let error): print(error.localizedDescription)
case .finished: break
}
} receiveValue: { [weak self] movieModels in
self?.upcomingMovieModels.send(movieModels)
}
.store(in: &cancellables)
}
}
upcomingMovieModels
를 패치 및 뷰 컨트롤러가 구독 가능한 데이터 퍼블리셔를 발행 func configure(with model: ContentModel) {
if let title = model.title {
nameLabel.text = title
} else if let anotherTitle = model.original_title {
nameLabel.text = anotherTitle
} else {
nameLabel.text = "Default Title"
}
overviewLabel.text = model.overview
guard
let imageURLString = model.poster_path,
let imageURL = URL(string: "\(TMDBConstants.imagePath.rawValue)\(imageURLString)") else { return }
let publisher: AnyPublisher<UIImage?, Never> = URLSession
.shared
.dataTaskPublisher(for: imageURL)
.compactMap({$0.data})
.compactMap({UIImage(data: $0)})
.replaceError(with: UIImage(systemName: "video"))
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
var cancellables: AnyCancellable?
cancellables = publisher
.sink(receiveCompletion: { _ in
cancellables?.cancel()
}, receiveValue: { [weak self] image in
self?.contentImageView.image = image
})
}
configure
함수 구현one-shot
퍼블리셔 사용 private func bind() {
viewModel
.upcomingMovieModels
.receive(on: DispatchQueue.main)
.sink { [weak self] movieModels in
self?.tableView.reloadData()
}
.store(in: &cancellabels)
}
viewDidLoaded()
메소드 내부에서 해당 바인드 함수 선언extension NewAndHotViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: NewAndHotTableViewCell.identifier, for: indexPath) as? NewAndHotTableViewCell else {
return UITableViewCell()
}
let model = viewModel.upcomingMovieModels.value[indexPath.row]
cell.configure(with: model)
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return viewModel.upcomingMovieModels.value.count
}
}
guard let
바인딩