You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Alamofire调用TMDB API无法获取数据的求助

问题排查与解决方案

核心问题总结

你的代码存在三个关键问题导致无法获取并解析TMDB数据:

  1. 网络请求URL拼接时变量拼写错误
  2. MovieResult结构体未定义CodingKeys,无法正确映射TMDB的蛇形命名JSON字段
  3. 回调设置顺序错误,可能导致网络请求完成后无法触发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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 04:27:24