加载嵌套在表视图单元格中的Collection视图时遇到了困难。单元格内的内容只会在滚动表格几次后显示。我的方法是使用DispatchGroup()
来获取后台线程中的数据,但它不起作用。为了在不滚动表格的情况下一次显示所有信息,有什么可做的?
viewDidLoad中
override func viewDidLoad() {
super.viewDidLoad()
_tableView.isHidden = true
_tableView.dataSource = nil
_tableView.delegate = nil
SVProgressHUD.show()
view.backgroundColor = UIColor.flatBlack()
getData()
dispatchGroup.notify(queue: .main) {
SVProgressHUD.dismiss()
self._tableView.isHidden = false
self._tableView.dataSource = self
self._tableView.delegate = self
self._tableView.reloadData()
}
}
UICollectionView和UITableView数据源/ OtherMethods
func getData(){
dispatchGroup.enter()
backend.movieDelegate = self
backend.actorDelegate = self
backend.getMoviePopularList()
backend.getMovieTopRatedList()
backend.getMovieUpcomingList()
backend.getPopularActors()
backend.getMovieNowPlayingList()
dispatchGroup.leave()
}
func transferMovies(data: [String:[MovieModel]]) {
dispatchGroup.enter()
popularMovies = data
dispatchGroup.leave()
}
func transferActors(data: [ActorModel]) {
dispatchGroup.enter()
popularActors = data
dispatchGroup.leave()
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "DiscoverCell") as? DiscoverViewCell else { return UITableViewCell()}
cell.categoryLabel.text = cell.categories[indexPath.item]
//categories[indexPath.item]
cell._collectionView.delegate = self
cell._collectionView.dataSource = self
cell._collectionView.tag = indexPath.row
cell._collectionView.reloadData()
self.setUpCell(cell)
return cell
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MovieCell", for: indexPath) as? MovieCollectionViewCell else { return UICollectionViewCell()}
if collectionView.tag == 0{
if let movieDetails = popularMovies["Popular"]?[indexPath.item] {
cell.updateMovieCollectionCell(movie: movieDetails)
}
} else if collectionView.tag == 1{
if let movieDetails = popularMovies["Top rated"]?[indexPath.item] {
cell.updateMovieCollectionCell(movie: movieDetails)
}
} else if collectionView.tag == 2{
if let movieDetails = popularMovies["Upcoming"]?[indexPath.item] {
cell.updateMovieCollectionCell(movie: movieDetails)
} else if collectionView.tag == 3{
cell.movieTitleLabel.text = popularActors?[indexPath.item].name ?? ""
cell.moviePicture.image = popularActors?[indexPath.item].poster
}
} else if collectionView.tag == 4{
if let movieDetails = popularMovies["Now playing"]?[indexPath.item] {
cell.updateMovieCollectionCell(movie: movieDetails)
}
}
return cell
}
电影CollectionViewCell
class MovieCollectionViewCell: UICollectionViewCell {
@IBOutlet weak var moviePicture: UIImageView!
@IBOutlet weak var movieTitleLabel: UILabel!
func updateMovieCollectionCell(movie: MovieModel){
moviePicture.image = movie.poster
movieTitleLabel.text = movie.name
}
}
DiscoverViewCell
class DiscoverViewCell: UITableViewCell {
@IBOutlet weak var categoryLabel: UILabel!
@IBOutlet weak var _collectionView: UICollectionView!
let categories = ["Popular", "Top Rated", "Upcoming", "Popular People", "Now playing"]
@IBAction func seeMoreAction(_ sender: Any) {
}
}
我的目的是显示一个加载动画,直到获取所有数据,并显示包含带有从web获取的数据的集合视图的表视图单元格。
打开应用程序时,所需的结果应如下所示
据我所知,你正在使用dispatchGroup错误。
总结notify()
:
我看到的问题是,对于写入fetch代码的方式,当您调用notify时,该组认为其队列为空。所以notify()
块立即运行,然后你只看到在滚动期间重新加载时填充的单元格。
有两种方法可以填充dispatchGroup的队列:
DispatchQueue.async()
并传递该组以直接将一个块排队并将其与该组关联enter()
,结束时手动调用leave()
,这会增加/减少组内部计数器第一种方法更安全,因为您不必自己跟踪块,但如果您无法控制块运行的队列,则第二种方法更灵活。
由于您使用的是enter/leave
,因此您需要确保为每个单独的工作项调用enter()
(在您的情况下,对backend
进行异步调用),并且只在每个工作项完成时调用leave()
。我不确定你是如何使用委托方法的,但是每个backend
调用似乎都没有,因为有5个不同的调用,只有2个委托方法。如果后端调用中发生错误,它看起来也不会调用委托方法。
我建议更改backend
调用以改为使用完成块,但如果你想坚持使用委托模式,那么你可以这样做:
func getData(){
backend.movieDelegate = self
backend.actorDelegate = self
dispatchGroup.enter()
backend.getMoviePopularList()
dispatchGroup.enter()
backend.getMovieTopRatedList()
dispatchGroup.enter()
backend.getMovieUpcomingList()
dispatchGroup.enter()
backend.getPopularActors()
dispatchGroup.enter()
backend.getMovieNowPlayingList()
dispatchGroup.notify(queue: .main) {
SVProgressHUD.dismiss()
self._tableView.isHidden = false
self._tableView.dataSource = self
self._tableView.delegate = self
self._tableView.reloadData()
}
}
func transferPopularMovies(data: [MovieModel]) {
popularMovies = data
dispatchGroup.leave()
}
func transferTopRatedMovies(data: [MovieModel]) {
topRatedMovies = data
dispatchGroup.leave()
}
func transferUpcomingMovies(data: [MovieModel]) {
upcomingMovies = data
dispatchGroup.leave()
}
func transferActors(data: [ActorModel]) {
popularActors = data
dispatchGroup.leave()
}
func transferNowPlayingMovies(data: [MovieModel]) {
nowPlayingMovies = data
dispatchGroup.leave()
}
即使出现错误以确保enter/leave
调用是平衡的,也不要忘记调用委托方法。如果你比enter
更频繁地调用leave
,那么notify
块永远不会运行。如果你经常打电话给leave
,你会崩溃。
试试这个......从后端获取数据并分配给moviedetails后,将你的委托和数据源设置为self和reload表。
将此行设置为getData()函数的底部并运行
self._tableView.isHidden = false
self._tableView.dataSource = self
self._tableView.delegate = self
self._tableView.reloadData()
并从viewdidload()中删除