iOS开发求助:解析JSON后dataMovie数组为空问题排查
问题分析与解决方案
核心原因1:异步请求完成后未刷新CollectionView
getTrendingMovie是异步网络请求,当你在闭包里给dataMovie赋值时,CollectionView已经完成了初始的数据源加载(此时dataMovie还是空数组)。赋值后没有通知CollectionView更新,所以界面和控制台显示的都是初始的空状态。
核心原因2:未利用闭包返回的results,依赖全局共享变量存在风险
你在闭包里直接取FetchData.shared.data,但没有用到回调返回的results,这说明FetchData的设计可能有问题——如果getTrendingMovie的回调已经返回了结果,就应该直接用这个结果,而不是依赖共享实例的属性,避免多线程下的数据不一致。
核心原因3:未在主线程更新UI
网络请求的回调通常在后台线程执行,直接在后台线程修改UI相关的数据源(dataMovie)并刷新界面,可能导致线程不安全的问题。
修复步骤
修改
getTrendMovie方法,使用回调返回的结果并刷新CollectionView
把闭包里的逻辑改成直接用results,然后切主线程刷新CollectionView:private func getTrendMovie() { FetchData.shared.getTrendingMovie { [weak self] results in guard let self = self else { return } // 优先使用回调返回的results,而不是共享实例的data if let movies = results as? [Movie] { self.dataMovie = movies // 切主线程刷新CollectionView DispatchQueue.main.async { self.TrendingMovieCollectionView.reloadData() } } } }检查
FetchData的getTrendingMovie实现
确保getTrendingMovie内部正确解析JSON,并把结果通过闭包返回,而不是只赋值给shared.data。比如FetchData里的方法应该类似:func getTrendingMovie(completion: @escaping (Any?) -> Void) { let url = URL(string: "你的TMDB接口地址")! URLSession.shared.dataTask(with: url) { data, response, error in guard let data = data, error == nil else { completion(nil) return } do { let movies = try JSONDecoder().decode([Movie].self, from: data) // 如果需要保存到共享实例,这里可以赋值,但回调一定要返回结果 self.data = movies completion(movies) } catch { print("解析错误:\(error)") completion(nil) } }.resume() }额外检查点
- 确认
Movie模型的属性和TMDB返回的JSON字段完全匹配(注意大小写、可选性,比如poster_path是否是可选字符串) - 检查网络请求是否成功,在
FetchData的请求回调里打印error和返回的data,确认接口能正常返回数据 - 确保CollectionView的
delegate和dataSource在请求前设置好(你当前的代码已经设置了,但如果请求完成太快,也可能有问题,不过主要问题还是刷新)
- 确认
内容的提问来源于stack exchange,提问作者Mezzz
相关产品推荐
相关产品推荐

