我创建的视图控制器包含UITableView,而每个UITableViewCell包含UICollectionView。我的问题是我不能对每个CollectionView都有不同的结果。我用JSON解析数据。我有一个静态数组,但它看起来是空的。
在cellForItemAt中,我得到一个错误:索引超出范围。
这是我的可视控制器

import UIKit

class HomeScreenCategoriesViewController: UIViewController,     UITableViewDelegate, UITableViewDataSource {

@IBOutlet weak var tableView: UITableView!
var moviesCategories = ["Popular", "Now Playing", "Latest", "Top Rated", "Upcoming"]
var popularMovies = MovieModel()
var nowPlayingMovies = MovieModel()
static var movies: [MovieModel] = []



override func viewDidLoad() {
    super.viewDidLoad()

    tableView.rowHeight = 130
    tableView.tableFooterView = UIView()
    parsePopularMovies()
    parseNowPlayingMovies()

    DispatchQueue.main.async {
        self.tableView.reloadData()
    }

}

func numberOfSections(in tableView: UITableView) -> Int {
    return 2
}

func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    return "\(moviesCategories[section])"
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 1
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if let cell = tableView.dequeueReusableCell(withIdentifier: "HomeScreenMovieTableViewCell", for: indexPath) as? HomeScreenCategoriesTableViewCell
    {
        return cell
    }
    return UITableViewCell()
}


func parsePopularMovies() {

    let jsonUrlString = "URLwithMyAPIkey"
    guard let url = URL(string: jsonUrlString) else { return }

    URLSession.shared.dataTask(with: url) { (data, response, err) in

        guard let data = data else { return }

        do {
            let tempMovies = try
                JSONDecoder().decode(MovieModel.self, from: data)

            self.popularMovies.page = tempMovies.page
            self.popularMovies.total_results = tempMovies.total_results
            self.popularMovies.total_pages = tempMovies.total_pages
            self.popularMovies.results = tempMovies.results

            for i in 0..<(self.popularMovies.results?.count ?? 0) {
                let tempPosterPath = "https://image.tmdb.org/t/p/w500" + (self.popularMovies.results?[i].poster_path)!!
                let tempBackDropPath = "https://image.tmdb.org/t/p/w500" + (self.popularMovies.results?[i].backdrop_path)!!
                self.popularMovies.results?[i].poster_path = tempPosterPath
                self.popularMovies.results?[i].backdrop_path = tempBackDropPath
                HomeScreenCategoriesViewController.movies.append(self.popularMovies)
            }

        } catch let jsonErr {
            print("Error serializing json:", jsonErr)
        }
        }.resume()

}


func parseNowPlayingMovies() {

    let jsonUrlString = "URLwithMyAPIkey"
    guard let url = URL(string: jsonUrlString) else { return }

    URLSession.shared.dataTask(with: url) { (data, response, err) in

        guard let data = data else { return }

        do {
            let tempMovies = try
                JSONDecoder().decode(MovieModel.self, from: data)

            self.nowPlayingMovies.page = tempMovies.page
            self.nowPlayingMovies.total_results = tempMovies.total_results
            self.nowPlayingMovies.total_pages = tempMovies.total_pages
            self.nowPlayingMovies.results = tempMovies.results

            for i in 0..<(self.nowPlayingMovies.results?.count ?? 0) {
                let tempPosterPath = "https://image.tmdb.org/t/p/w500" + (self.nowPlayingMovies.results?[i].poster_path)!!
                //let tempBackDropPath = "https://image.tmdb.org/t/p/w500" + (self.nowPlayingMovies.results?[i].backdrop_path)!!
                self.nowPlayingMovies.results?[i].poster_path = tempPosterPath
                HomeScreenCategoriesViewController.movies.append(self.nowPlayingMovies)
            }

        } catch let jsonErr {
            print("Error serializing json:", jsonErr)
        }
        }.resume()

}

}

这是我的TableViewCell
import UIKit

class HomeScreenCategoriesTableViewCell: UITableViewCell, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {

@IBOutlet var collectionView: UICollectionView!
var sectionIndex:Int?
static var movies: [MovieModel] = []

override func awakeFromNib() {

    super.awakeFromNib()
    self.collectionView.delegate = self
    self.collectionView.dataSource = self

    DispatchQueue.main.async {
        self.collectionView.reloadData()
    }

}


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCell(withIdentifier: "HomeScreenMovieTableViewCell", for: indexPath) as! HomeScreenCategoriesTableViewCell
    cell.sectionIndex = indexPath.section

    return cell
}


func numberOfSections(in collectionView: UICollectionView) -> Int {
    return 1
}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return 5
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "HomeScreenMovieCell", for: indexPath) as! HomeScreenCategoriesCollectionViewCell

    cell.test.text = HomeScreenCategoriesTableViewCell.movies[collectionView.tag].results?[indexPath.row].title!

    return cell
}

}

我的模型是:
struct MovieResults: Codable, Equatable {

let id: Int?
let title: String?
let overview: String?
let adult: Bool?
let original_language: String?
var poster_path: String?
var backdrop_path: String?
let vote_average: Float?
let release_date: String?
}

struct MovieModel: Codable {

var page: Int?
var total_results: Double?
var total_pages: Int?
var results: [MovieResults]?
}

我试着按照这个指示(How to get section of UITableView from inside a child UICollectionview)做,但找不到解决方法
我做错什么了?

最佳答案

这里很少有问题:
模型命名
您使用的数据模型对象令人困惑。MovieModel听起来应该代表一部电影。但是看看解析函数,

        self.nowPlayingMovies.page = tempMovies.page
        self.nowPlayingMovies.total_results = tempMovies.total_results
        self.nowPlayingMovies.total_pages = tempMovies.total_pages
        self.nowPlayingMovies.results = tempMovies.results

该对象中似乎有多个条目。它可能应该被称为MovieCategoryModel
HomeScreenCategoriesTableViewCell应该有一个这样的模型:
var movieCategory: MovieCategoryModel!
因为你会有不同的电影
不同的部分,movieCategory属性不应为static
cellfortemat indexPath在这个方法中,您试图用关于电影的数据配置单元UI。但从未填充HomeScreenCategoriesTableViewCell的属性。
项目编号部分
这将返回该部分中的电影数量。您的代码返回5-这是一个任意数字。这就是错误的原因。您应该返回movieCategory.total_results
cellForRowAt索引
HomeScreenCategoriesViewController中,当您出列HomeScreenMovieTableViewCell时,您需要将电影传递到该单元格,这样它将有数据显示。你需要做如下事情:
if section == 0 { cell.movieCategory = popularMovies} else if section == 1 { cell.movieCategory = nowPlayingMovies}
通常,在解析代码中,需要为每个类别分别保存电影。这样,在tableView委托方法中,您可以轻松地获取该节所需的数据。
解析代码也需要一些工作,因为我可以看到您正在循环处理对象中包含的项
for i in 0..<(self.nowPlayingMovies.results?.count ?? 0)
但是在同一个循环中将整个对象添加到数组中
`HomeScreenCategoriesViewController.movies.append(self.nowPlayingMovies)`

根据提供的额外信息进行编辑:
MovieResults对于表示单个电影的对象来说是一个非常混乱的名称。我建议把它改成Movie
然后MovieModel-包含多个电影的对象将是MovieCategory。也许将该类别的标题存储在对象本身中也是一个好主意?
模型
struct Movie: Codable, Equatable {

  let id: Int?
  let title: String?
  let overview: String?
  let adult: Bool?
  let original_language: String?
  var poster_path: String?
  var backdrop_path: String?
  let vote_average: Float?
  let release_date: String?
}

struct MovieCategory: Codable {
  var title: String?
  var page: Int?
  var total_results: Double?
  var total_pages: Int?
  var results: [Movie]?
}


视图控制器
import UIKit

class HomeScreenCategoriesViewController: UIViewController,     UITableViewDelegate, UITableViewDataSource {

  @IBOutlet weak var tableView: UITableView!
  var moviesCategories: [MovieCategory] = []


  override func viewDidLoad() {
    super.viewDidLoad()

    tableView.rowHeight = 130
    tableView.tableFooterView = UIView()
    parsePopularMovies()
    parseNowPlayingMovies()

  }

  func numberOfSections(in tableView: UITableView) -> Int {
    return moviesCategories.count
  }

  func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    let category = moviesCategories[section]
    return category.title
  }

  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 1
  }

  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if let cell = tableView.dequeueReusableCell(withIdentifier: "HomeScreenMovieTableViewCell", for: indexPath) as? HomeScreenCategoriesTableViewCell
    {
      cell.movieCategory = moviesCategories[indexPath.section]
      return cell
    }
    return UITableViewCell()
  }


  func parsePopularMovies() {

    let jsonUrlString = "URLwithMyAPIkey"
    guard let url = URL(string: jsonUrlString) else { return }

    URLSession.shared.dataTask(with: url) { (data, response, err) in

      guard let data = data else { return }

      do {
        var popularMovies = try
          JSONDecoder().decode(MovieCategory.self, from: data)
        popularMovies.title = "Popular Movies"

        for i in 0..<(popularMovies.results?.count ?? 0) {
          let tempPosterPath = "https://image.tmdb.org/t/p/w500" + (popularMovies.results?[i].poster_path)!!
          let tempBackDropPath = "https://image.tmdb.org/t/p/w500" + (popularMovies.results?[i].backdrop_path)!!
          popularMovies.results?[i].poster_path = tempPosterPath
          popularMovies.results?[i].backdrop_path = tempBackDropPath
        }
        self.moviesCategories.append(popularMovies)
        DispatchQueue.main.async {
            self.tableView.reloadData()
        }

      } catch let jsonErr {
        print("Error serializing json:", jsonErr)
      }
      }.resume()

  }


  func parseNowPlayingMovies() {

    let jsonUrlString = "URLwithMyAPIkey"
    guard let url = URL(string: jsonUrlString) else { return }

    URLSession.shared.dataTask(with: url) { (data, response, err) in

      guard let data = data else { return }

      do {
        var nowPlayingMovies = try
          JSONDecoder().decode(MovieCategory.self, from: data)

        for i in 0..<(nowPlayingMovies.results?.count ?? 0) {
          let tempPosterPath = "https://image.tmdb.org/t/p/w500" + (nowPlayingMovies.results?[i].poster_path)!!
          //let tempBackDropPath = "https://image.tmdb.org/t/p/w500" + (self.nowPlayingMovies.results?[i].backdrop_path)!!
          nowPlayingMovies.results?[i].poster_path = tempPosterPath
        }
        self.moviesCategories.append(nowPlayingMovies)
        DispatchQueue.main.async {
            self.tableView.reloadData()
        }
      } catch let jsonErr {
        print("Error serializing json:", jsonErr)
      }
      }.resume()

  }

}


表格视图单元格
class HomeScreenCategoriesTableViewCell: UITableViewCell, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {

  @IBOutlet var collectionView: UICollectionView!
  var sectionIndex:Int?
  var movieCategory: MovieCategory!

  override func awakeFromNib() {

    super.awakeFromNib()
    self.collectionView.delegate = self
    self.collectionView.dataSource = self

    DispatchQueue.main.async {
      self.collectionView.reloadData()
    }

  }

  func numberOfSections(in collectionView: UICollectionView) -> Int {
    return 1
  }

  func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return 5
  }

  func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "HomeScreenMovieCell", for: indexPath) as! HomeScreenCategoriesCollectionViewCell

    if indexPath.row < movieCategory.results?.count ?? 0 {
      let movie = movieCategory.results?[indexPath.row]
      cell.test.text = movie.title
    }

    return cell
  }

}

09-27 17:27