Reputation: 611
I implement pull to refresh in collection View and the problem I'm facing is my app will crash with out of index message. Below is my cellForItem method
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! CauNguyenCell
cell.postArray = postData[indexPath.item]
return cell
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return postData.count
}
I know the problem is because I use removeAll method to clear all data from my postData but I have to that so my data array will have completely new data.
Below is my refresh function:
func handleRefresh(_ refreshControl: UIRefreshControl) {
refreshControl.beginRefreshing()
postData.removeAll()
fetchDataAgain()
self.collectionView.reloadData()
refreshControl.endRefreshing()
}
error message: Thread 1: Fatal error: Index out of range
I just want to ask if anyone has any suggestions to solve the problem. Thanks!
Upvotes: 1
Views: 730
Reputation: 172
Edit you code like this:
func fetchDataAgain(completion: ((Bool) -> ())) {
// your code
if postData != nil, postData.count != 0 {
completion(true)
}
}
func handleRefresh(_ refreshControl: UIRefreshControl) {
refreshControl.beginRefreshing()
postData.removeAll()
fetchDataAgain { (complete) in
if complete {
self.collectionView.reloadData()
refreshControl.endRefreshing()
}
}
}
Method fetchDataAgain will check array, and if it != nil and count != 0 in handler complete reloadData.
Code do all step by step, and when you are reload data in collection, your array can be empty, or nil. As a rule better to use handlers
Upvotes: 0
Reputation: 5823
I have implemented same thing in my project. First I have created refreshControl instance globally, then setup in initSetup()
method call from viewDidLoad()
in my view controller.
var refreshControl : UIRefreshControl?
var arrWeddingInvitations = [MyModelClass]()
func initialSetup() {
self.refreshControl = UIRefreshControl()
self.refreshControl?.tintColor = .yellow
self.refreshControl?.addTarget(self, action: #selector(getWeddingInvitations), for: .valueChanged)
self.cvWeddingInvitation.addSubview(refreshControl!)
}
This is call getWeddingInvitations()
method which is fetching data from server.
// This code will hide refresh controller
DispatchQueue.main.async {
self.refreshControl?.endRefreshing()
}
// This code in my API request completion block and will check responded array data, If it is not nil then assigned to my global array in view controller which are used to display data and reload collection view.
if arrInvitations != nil, arrInvitations.count > 0 {
self.lblEmptyData.isHidden = true
self.cvWeddingInvitation.isHidden = false
self.arrWeddingInvitations = arrInvitations
self.cvWeddingInvitation.reloadData()
} else {
self.lblEmptyData.isHidden = false
self.cvWeddingInvitation.isHidden = true
}
This is working code in my current project. I hope this will help you.
See following video:
Upvotes: 2
Reputation: 1096
Please check your UICollectionViewDataSource
implementation for these methods:
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
func numberOfSections(in: UICollectionView)
In the first one you should return the current number of items postData.count
, the second one in your case should return 1
.
Upvotes: 0