使用Alamofire调用TMDB API无法获取数据的求助
问题排查与解决方案
核心问题总结
你的代码存在三个关键问题导致无法获取并解析TMDB数据:
- 网络请求URL拼接时变量拼写错误
MovieResult结构体未定义CodingKeys,无法正确映射TMDB的蛇形命名JSON字段- 回调设置顺序错误,可能导致网络请求完成后无法触发UI更新
具体修复步骤
1. 修复NetworkHelper的变量拼写错误
在NetworkHelper的requestUrl方法中,你错误地使用了api_key(下划线),但类内定义的API Key变量是apiKey(驼峰),这会导致URL拼接错误,API请求返回权限错误。
修改后的NetworkHelper:
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)" // 修复变量名拼写 } }
2. 给MovieResult添加CodingKeys映射
TMDB返回的JSON字段是蛇形命名(如genre_ids、backdrop_path),而你的MovieResult属性是驼峰命名,必须通过CodingKeys来映射,否则JSONDecoder无法正确解析字段,导致results数组为空。
修改后的Movie结构体:
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? // 添加CodingKeys映射蛇形字段 enum CodingKeys: String, CodingKey { case adult case backdropPath = "backdrop_path" case genreIDS = "genre_ids" case id case originalLanguage = "original_language" case originalTitle = "original_title" case overview, popularity case posterPath = "poster_path" case releaseDate = "release_date" case title, video case voteAverage = "vote_average" case voteCount = "vote_count" case character case creditID = "credit_id" case order, department, job } }
3. 调整回调设置顺序
在HomeViewController的viewModelConfiguration方法中,你先调用了viewModel.getCatagoryItems(),再设置回调。如果网络请求完成速度快于回调设置,会导致successCallBack和errorCallBack无法触发,无法更新UI或打印错误信息。
修改后的viewModelConfiguration:
fileprivate func viewModelConfiguration(){ // 先设置回调,再发起请求 viewModel.errorCallBack = { [weak self] errorMesage in print("error: \(errorMesage)") } viewModel.successCallBack = { [weak self] in self?.collectionView.reloadData() } viewModel.getCatagoryItems() }
额外优化建议
- 在
NetworkManager的handleResponse方法中打印解码错误,便于排查: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{ print("解码错误: \(error)") // 添加错误打印 completion(.failure(.invalidData)) } } - 优化
HomeEndpoint的path实现,避免重复调用HomeEndpoint.popular.rawValue:enum HomeEndpoint: String { case popular = "movie/popular" var path: String { return NetworkHelper.shared.requestUrl(url: self.rawValue) } }
完成以上修改后,你应该能正常获取TMDB的热门电影数据,cellForItemAt中的print语句也会输出影片的originalTitle。
内容的提问来源于stack exchange,提问作者Mert
相关产品推荐
相关产品推荐

