Im having issue with making page control work for a collection view which is inside table view. There are actually 2 collection views in the view controller, one is outside the tableView and other one is inside. I want page control for inside one. Let me share code below and then explain what is causing trouble:
class HomeViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
override func viewDidLoad() {
super.viewDidLoad()
//setup stories collection view
let nib = UINib(nibName: "StoryCollectionViewCell", bundle: nil)
cvStories.register(nib, forCellWithReuseIdentifier: "StoryCollectionViewCell")
let layout1 = UICollectionViewFlowLayout()
layout1.scrollDirection = .horizontal
layout1.sectionInset = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
collectionViewStories.setCollectionViewLayout(layout1, animated: true)
collectionViewStories.delegate = self
collectionViewStories.dataSource = self
tblHome.dataSource = self
tblHome.delegate = self
}
// MARK: - Table View
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tblHome.dequeueReusableCell(withIdentifier: "HomeTableViewCell", for: indexPath) as! HomeTableViewCell
cell.collectionViewPostImages.dataSource = self
cell.collectionViewPostImages.delegate = self
cell.collectionViewPostImages.tag = indexPath.row
cell.collectionViewPostImages.reloadData()
cell.pageControl.hidesForSinglePage = true
cell.pageControl.numberOfPages = self.posts[cell.collectionViewPostImages.tag].imagesArray?.count ?? 0
return cell
}
//MARK: - Collection View
func numberOfSections(in collectionView: UICollectionView) -> Int {
if collectionView == cvStories {
return 2
}
else {
return 1
}
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if collectionView == collectionViewStories {
return stories.count
}
else {
return posts[collectionView.tag].imagesArray?.count ?? 0
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if collectionView == collectionViewStories {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "StoryCollectionViewCell", for: indexPath) as! StoryCollectionViewCell
//code to show stories
return cell
}
else {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "HomeCollectionViewCell", for: indexPath) as! HomeCollectionViewCell
//code to show images
return cell
}
}
}
//TableViewCell Class
class HomeTableViewCell: UITableViewCell {
@IBOutlet weak var collectionViewPostImages: UICollectionView!
@IBOutlet weak var pageControl: UIPageControl!
var currentPage = 0
override func awakeFromNib() {
let flowLayout = UICollectionViewFlowLayout()
flowLayout.itemSize = CGSize(width: UIScreen.main.bounds.size.width, height: cvPostImages.frame.size.height)
flowLayout.scrollDirection = .horizontal
flowLayout.minimumInteritemSpacing = 0
flowLayout.minimumLineSpacing = 0
collectionViewPostImages?.collectionViewLayout = flowLayout
collectionViewPostImages.showsHorizontalScrollIndicator = false
collectionViewPostImages.isPagingEnabled = true
}
//ScrollView delegate method
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let pageWidth = scrollView.frame.width
self.currentPage = Int((scrollView.contentOffset.x pageWidth / 2) / pageWidth)
self.pageControl.currentPage = self.currentPage
}
}
The whole code is like Instagram app, stories at top and posts with images in tableView. Whole code is in single View controller and everything works fine. Even dots (page number) are correct according to number of pages however when you swipe between them they do not change. I saw many solutions and in those pageControl.numberOfPages was used in cellForItemAt function but its out of scope for me so I just called it as cell.pageControl.numberOfPages in cellForRowAt instead. First time dealing with collectionView inside tableView so getting confused getting it worked.
CodePudding user response:
The main problem is you use cell.collectionViewPostImages.delegate = self
in HomeViewController
but your method scrollViewDidScroll
in cell HomeTableViewCell
.
Collectionview's own scrollview delegate methods triggering in UICollectionViewDelegate
. Thats why scrollViewDidScroll
is not triggered in your cell.
Solution is using scrollViewDidScroll
in where you delegete the collectionview. It is HomeViewController
By the way, I dont recommend to use
cell.collectionViewPostImages.dataSource = self cell.collectionViewPostImages.delegate = self
in reusable cell. You dont want to make...delegate = self
on everytime when cell reused. You can take it inawakeFromNib
in cell class