Swift开发:无法解码API链接并从数组获取电影标题的问题
问题分析与解决方案
核心问题
- 解码逻辑错误:你试图直接将API返回的完整JSON解码成单个字符串(
title1本质是字符串"title"),但API返回的是包含page、results数组等字段的完整Movies结构,这种解码方式必然失败,导致输出"FAIL"。 - 类型认知偏差:
[Result]是Result对象的数组,数组本身没有title属性,必须遍历数组中的每个Result实例才能获取对应的电影标题。
修正步骤与代码
1. 定义目标结构体(按需存储电影标题)
如果你只需要存储电影标题,可以定义一个极简结构体:
struct MovieTitle: Codable { let title: String }
2. 修正API管理器的解码逻辑
重写APIManager的方法,先解码完整的Movies结构,再从results数组中提取标题并转换为目标结构体:
class APIManager { static let shared = APIManager() let urlString = "https://api.themoviedb.org/3/movie/popular?api_key=d35da28c5f884f89607c3388f07c2f5e" func getMovieTitles(completion: @escaping ([MovieTitle]) -> Void) { // 避免强制解包URL,防止崩溃 guard let url = URL(string: urlString) else { print("无效的API地址") completion([]) return } let task = URLSession.shared.dataTask(with: url) { data, response, error in // 处理请求错误 if let error = error { print("请求失败: \(error.localizedDescription)") completion([]) return } guard let data = data else { print("未获取到返回数据") completion([]) return } do { // 先解码完整的Movies结构 let movies = try JSONDecoder().decode(Movies.self, from: data) // 遍历results数组,提取每个电影的title并转换为目标结构体 let movieTitles = movies.results.map { MovieTitle(title: $0.title) } // 切回主线程回调结果 DispatchQueue.main.async { completion(movieTitles) } } catch { // 打印解码错误详情,方便排查 print("解码失败: \(error.localizedDescription)") completion([]) } } task.resume() } }
3. 优化结构体命名(避免冲突)
Result是Swift标准库的内置类型,建议将原Result结构体重命名为Movie,避免命名冲突:
struct Movies: Codable { let page: Int var results: [Movie] let totalPages, totalResults: Int enum CodingKeys: String, CodingKey { case page, results case totalPages = "total_pages" case totalResults = "total_results" } } struct Movie: Codable { let adult: Bool let backdropPath: String let genreIDS: [Int] let id: Int let originalLanguage: OriginalLanguage let originalTitle, overview: String let popularity: Double let posterPath, releaseDate, title: String let video: Bool let voteAverage: Double let voteCount: Int 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" } } enum OriginalLanguage: String, Codable { case en = "en" case es = "es" case it = "it" }
4. 使用示例
调用修正后的方法获取电影标题数组:
APIManager.shared.getMovieTitles { movieTitles in // 遍历打印所有标题 for movieTitle in movieTitles { print(movieTitle.title) } // 此处可将movieTitles存入你需要的存储位置 }
内容的提问来源于stack exchange,提问作者DanTheMan
相关产品推荐
相关产品推荐

