我正在尝试使用 tmdb API 制作一个类似 IMDb 的应用程序,我已经完成了应用程序的第一部分,但是我无法从 API 获取数据,我已经尝试了一天多,但我无法解决问题。
print(viewModel.movie?.results?[indexPath.item].originalTitle ?? "")
在 homeViewController 的 cellForItemAt 中
作为此代码的结果,originalTitle 应该被打印出来,但它没有打印出来。
我正在尝试通过观看此视频系列来制作此应用程序:https://www.youtube.com/playlist?list=PLnoj2maz_tTO1u-1BjKs3xrEzKc3Rmj_T
如果你想看github上的所有代码,项目的github链接:https://github.com/mertplt/Filmly
import Foundation
enum HTTPMethods: String{
case get = "GET"
case post = "POST"
}
enum ErrorTypes: String,Error{
case invalidData = "Invalid data"
case invalidURL = "Invalid url"
case generalError = "An error happened"
}
class NetworkHelper{
static let shared = NetworkHelper()
private let baseURL = "https://api.themoviedb.org/3/"
private let apiKey = "509ef93252a59761a3c353f9ea114de0"
func requestUrl(url: String) -> String {
return baseURL + url + "?api_key=\(apiKey)"
}
}
import Alamofire
class NetworkManager {
static let shared = NetworkManager()
func request<T: Codable>(type: T.Type,
url: String,
method: HTTPMethod,
completion: @escaping((Result<T, ErrorTypes>)->())) {
AF.request(url.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? " ", method: method).responseData { response in
switch response.result {
case .success(let data):
self.handleResponse(data: data) { response in
completion(response)
}
case .failure(_):
completion(.failure(.generalError))
}
}
}
fileprivate func handleResponse<T: Codable>(data: Data,completion: @escaping((Result<T, ErrorTypes>)->())){
do{
let result = try JSONDecoder().decode(T.self, from: data)
completion(.success(result))
}
catch{
completion(.failure(.invalidData))
}
}
}
import Foundation
enum HomeEndpoint: String {
case popular = "movie/popular"
var path: String {
switch self{
case.popular:
return NetworkHelper.shared.requestUrl(url: HomeEndpoint.popular.rawValue)
}
}
}
-HomeManager
import Foundation
protocol HomeManagerProtocol {
func getCatagoryMovies(complete:@escaping((Movie?,Error?)->()))
}
class HomeManager{
static let shared = HomeManager()
func getCatagoryMovies(complete:@escaping((Movie?,Error?)->())){
NetworkManager.shared.request(type: Movie.self,
url: HomeEndpoint.popular.path,
method:.get) { response in
switch response{
case .success(let data):
complete(data,nil)
case .failure(let error):
complete(nil,error)
}
}
}
}
-电影
import Foundation
// MARK: - Movie
struct Movie: Codable {
let page: Int?
let results: [MovieResult]?
let totalPages, totalResults: Int?
enum CodingKeys: String, CodingKey {
case page, results
case totalPages = "total_pages"
case totalResults = "total_results"
}
}
// MARK: - MovieResult
struct MovieResult: Codable {
let adult: Bool?
let backdropPath: String?
let genreIDS: [Int]?
let id: Int?
let originalLanguage, originalTitle, overview: String?
let popularity: Double?
let posterPath, releaseDate, title: String?
let video: Bool?
let voteAverage: Double?
let voteCount: Int?
let character, creditID: String?
let order: Int?
let department, job: String?
}
-HomeViewModel
import Foundation
class HomeViewModel{
let manager = HomeManager.shared
var movie: Movie?
var errorCallBack: ((String)->())?
var successCallBack: (()->())?
func getCatagoryItems(){
manager.getCatagoryMovies { [weak self ]Movie, error in
if let error = error{
self?.errorCallBack?(error.localizedDescription)
}else{
self?.movie = Movie
self?.successCallBack?()
}
}
}
func numberOfItems() -> Int{
movie?.results?.count ?? 0
}
}
-HomeViewController
import UIKit
class HomeViewController: UIViewController {
@IBOutlet private weak var collectionView: UICollectionView!
let viewModel = HomeViewModel()
override func viewDidLoad() {
super.viewDidLoad()
collectionSetup()
viewModelConfiguration()
}
fileprivate func collectionSetup(){
collectionView.registerCell(type: VerticalCollectionViewCell.self)
}
fileprivate func viewModelConfiguration(){
viewModel.getCatagoryItems()
viewModel.errorCallBack = { [weak self] errorMesage in
print("error: \(errorMesage)")
}
viewModel.successCallBack = { [weak self] in
self?.collectionView.reloadData()
}
}
}
extension HomeViewController:UICollectionViewDataSource,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout{
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return viewModel.numberOfItems()
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell: VerticalCollectionViewCell = collectionView.dequeueCell(for: indexPath)
print(viewModel.movie?.results?[indexPath.item].originalTitle ?? "")
cell.backgroundColor = .red
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: collectionView.frame.width * 327 / 375, height: 120)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize {
CGSize(width: collectionView.frame.width, height: 365)
}
}