Reputation: 509
I have a problem when pull-to-refresh with UICollectionView
. The refreshing control work well but when I click on a cell, push another view controller, and pop back, try refreshing, UICollectionView
is disappeared( I don't use storyboard).
Screen record video: https://www.youtube.com/watch?v=3bsaqqv6x_8
Here is my code:
AccountController
class AccountController: UICollectionViewController, UICollectionViewDelegateFlowLayout{
var menuData: [Any]? {
didSet{
self.collectionView?.reloadData()
}
}
let collectionLayout = UICollectionViewFlowLayout()
let refreshControl = UIRefreshControl()
override func viewDidLoad() {
...
setupCollectionView()
self.collectionView?.isHidden = false
refreshControl.addTarget(self, action: #selector(refresh), for: .valueChanged)
collectionView!.addSubview(refreshControl)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
super.collectionViewLayout.invalidateLayout()
}
func setupCollectionView(){
self.collectionView?.isHidden = true
collectionView?.backgroundColor = UIColor(white: 0.95, alpha: 1)
collectionView?.alwaysBounceVertical = true
collectionView?.register(MenuCell.self, forCellWithReuseIdentifier: cellId)
collectionView?.register(MenuSupplementary.self, forCellWithReuseIdentifier: supplementaryId)
collectionLayout.minimumLineSpacing = 0
collectionView?.collectionViewLayout = collectionLayout
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if let count = menuData?.count {
return count
}
return 0
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if let dt = menuData?[indexPath.item] {
if dt is MenuCellData{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! MenuCell
cell.data = dt as? MenuCellData
return cell
}
if dt is MenuSupplementaryData {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: supplementaryId, for: indexPath) as! MenuSupplementary
cell.data = dt as? MenuSupplementaryData
return cell
}
}
return UICollectionViewCell()
}
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize.init(width: view.frame.width, height: 45)
}
@objc func refresh(sender:UIRefreshControl){
let api = AccountApi(jwt: appDelegate.userDefault.string(forKey: "jwt"))
api.getMenuData { (data) in
var dt: [Any] = []
if data.isEmpty { return }
for d in data as! [MenuData] {
if d.type == "supplementary" {
dt.append(MenuSupplementaryData( d.text ))
}
if d.type == "cell" {
dt.append(MenuCellData(d.icon!, d.text, isTheLastItem: d.isTheLastItem ?? false, url: d.url, httpMethod: d.httpMethod ))
}
}
if !dt.isEmpty {
self.menuData = dt
}
sender.endRefreshing()
}
}
}
TabBarController
class TabBarController: UITabBarController, UITabBarControllerDelegate {
...
private func setUpNavControllerFrom(viewController: UIViewController, title: String, imageName: String)-> UINavigationController{
let navController = UINavigationController(rootViewController: viewController)
navController.tabBarItem.title = title
navController.tabBarItem.image = UIImage(named: imageName)
let imageView = UIImageView.init(frame: CGRect())
imageView.image = UIImage(named: "logo")
imageView.contentMode = .scaleAspectFit
imageView.heightAnchor.constraint(equalToConstant: 20).isActive = true // Set logo height
viewController.navigationItem.titleView = imageView
navController.navigationBar.barTintColor = themeColor
return navController
}
// Set up color, logo, font ...
private func setupViewControllers(){
tabBar.tintColor = UIColor.white
tabBar.barTintColor = themeColor
let accountVC = AccountController(collectionViewLayout: UICollectionViewFlowLayout())
let accNavController = setUpNavControllerFrom(viewController: accountVC, title: "Account", imageName: "account-icon")
...
}
}
Additional info:
numberOfItemsInSection
, cellForItemAt
, sizeForItemAt
of delegate is invoked when call collectionView?.reloadData()
.cellForItemAt
, sizeForItemAt
of delegate is not invoked when call collectionView?.reloadData()
.Thanks for help!
Upvotes: 0
Views: 1137
Reputation: 509
Thanks for trying help me!
I finally find out my mistake.
When handling menu is selected, I create new controller with current collectionViewLayout
, and I think this current layout is changed when pop back, make menu is disappeared.
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if let dt = menuData?[indexPath.item]{
if dt is MenuCellData {
let d = dt as! MenuCellData
// let controller = AccountMenuController(collectionViewLayout: collectionView.collectionViewLayout)
let controller = AccountMenuController(collectionViewLayout: UICollectionViewLayout())
controller.menuData = d
navigationController?.pushViewController(controller, animated: true)
}
}
}
Upvotes: 1