如何在通过完成处理程序接收到解析后的数据后在 table 视图中正确显示它们

How to properly display parsed data in table view after receiving them through completion handler

我需要在 tableView 中显示有关电影的信息(取自 https://developers.themoviedb.org/)。我正在使用单例进行网络请求,然后通过完成处理程序将解析后的数据传递给 tableViewController。我可以打印接收到的数据,但无法在 tableView 单元格中正确设置它们。你能帮我解决这个问题吗?

网络管理员

func getMovies(completion: @escaping ([Movies]?) -> Void) {
    
guard let url = URL(string: "https://api.themoviedb.org/3/movie/now_playing?api_key=\(apiKey)&language=en")
else { fatalError("Wrong URL") }
    
URLSession.shared.dataTask(with: url) { (data, response, error) in
    
     if let jsonData = data {
        let decoder = JSONDecoder()
     do {
        let moviesResult = try decoder.decode(MoviesResult.self, from: jsonData)
        let movies = moviesResult.results
        completion(movies)
        }
     catch {
            print(error)
          }
    }
}.resume()

}

电影视图控制器

var movies = [Movies]()
    
  override func viewDidLoad() {
        super.viewDidLoad()
   
        network.getMovies { result in
            if let result = result {
                self.movies = result
                print(self.movies)
            }
        }

extension MoviesViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return movies.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let movie = movies[indexPath.row]
        print(movie)
        
        if let cell = tableView.dequeueReusableCell(withIdentifier: "moviesMainInfo", for: indexPath) as? MovieTableViewCell {
            
            cell.filmTitle.text = movie.title
            cell.filmRating.text = String(movie.popularity!)
            return cell
          }
        return UITableViewCell()
    }
}

解析结果: [MovieApp.Movies(genreIDs: Optional([14, 28, 12]), overview: Optional("Wonder Woman comes conflict with the 1980 年代寒冷时期的苏联 War,并发现了一个名为猎豹的强大敌人。”),受欢迎程度:可选(1927.057),标题:可选(“神奇女侠 1984”),发布日期:可选( "2020-12-16"), posterPath: Optional("/8UlWHLMpgZm9bx6QYh0NFoq67TZ.jpg")),

您做的一切都正确,您只需要在数据到达时重新加载 UITableView。请注意,您需要在主线程上重新加载 UITableView,因为 UIKit 不是线程安全的:

否则您的应用程序很可能会崩溃:

private func reloadTableView() {
    DispatchQueue.main.async {
        self.tableView.reloadData()
    }
}

另外,我鼓励您从 viewDidLoad 中提取您的网络功能。另一个改进是在闭包中使用 [weak self] 以避免内存泄漏:

private func loadData() {
    network.getMovies { [weak self] result in
        if let result = result {
            self?.movies = result
            print(self?.movies)
            self?.reloadTableView()
        } else {
            // Maybe show some info that the data could not be fetched
        }
    }
}

然后在你的 viewDidLoad 中调用它:

override func viewDidLoad() {
    super.viewDidLoad()
    loadData()
}