Building Netflix App in Swift 5 and UIKit - (Xcode 13, 2021) - Episode 5 - Networking
Codable
프로토콜 구조체 구현func getTrendingMovies() -> AnyPublisher<[MovieModel], Error> {
guard let url = URL(string: "\(TMDBConstants.baseURL.rawValue)/3/trending/all/day?api_key=\(TMDBConstants.API_KEY.rawValue)") else { return Fail(error: URLError(.badURL)).eraseToAnyPublisher() }
return URLSession.shared.dataTaskPublisher(for: url)
.receive(on: DispatchQueue.global(qos: .background))
.compactMap({$0.data})
.decode(type: TrendingMoviesResponse.self, decoder: JSONDecoder())
.map{$0.results}
.eraseToAnyPublisher()
}
TMDB
API를 통해 트렌드 영화 데이터를 리턴하는 APICaller
함수struct TrendingMoviesResponse: Codable {
let results: [MovieModel]
}
import Foundation
struct MovieModel: Codable {
let adult: Bool
let overview: String
let release_date: String?
let id: Int
let genre_ids: [Int]
let original_title: String?
let original_language: String?
let title: String?
let vote_count: Int
let vote_average: Double
let popularity: Double
let poster_path: String?
}
Codable
프로토콜 양식의 구조체private func addSubcription() {
APICaller
.shared
.getTrendingMovies()
.sink { completion in
switch completion {
case.finished: break
case .failure(let error): print(error.localizedDescription)
}
} receiveValue: { [weak self] movieModels in
self?.movieModels.send(movieModels)
}
.store(in: &cancellabels)
}
func configure(with model: MovieModel) {
if let title = model.title {
nameLabel.text = title
} else if let anotherTitle = model.original_title {
nameLabel.text = anotherTitle
} else {
nameLabel.text = "Default Title"
}
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?.imageView.image = image
})
}
MovieModel
데이터의 타이틀과 이미지를 통해 셀 UI 표현기존의
Asset
에 추가된 이미지를 사용하던 바와 달리 헤더 타이블 뷰에 사용되는 이미지 또한 API를 통해 리턴받은 영화 데이터 중 랜덤으로 택함