在加载嵌套在表视图单元格中的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
}
MovieCollectionViewCell
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获取数据的集合视图的表视图单元格。
打开应用程序时,所需的结果应如下所示
答案 0 :(得分:0)
尝试一下...从后端获取数据并分配给moviedetails之后,将委托和数据源设置为self并重新加载表。
答案 1 :(得分:0)
据我所知,您使用的DispatchGroup不正确。
总结notify()
:
我看到的问题是,通过编写提取代码的方式,当您调用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
,则会崩溃。
答案 2 :(得分:0)
将此行设置在getData()函数的底部并运行
self._tableView.isHidden = false
self._tableView.dataSource = self
self._tableView.delegate = self
self._tableView.reloadData()
并从viewdidload()中删除