Hello, I'm working on an app that is fetching data from Firebase and the data is loaded in a UITableView. I'm using pagination (loading 3 posts at a time). Users are allowed to delete their own post. The issue I'm having is when the user deletes the post (first from Firebase and then from the array), the tableView removes the user's post, but it also removes (from the view only) the next 2 posts. Then all I see are the next 3 posts and if I scroll up to see the previous ones, the app crashes because the indexPath.row is out of range. Below is my code. Any help is greatly appreciated:
override func viewDidLoad() {
super.viewDidLoad()
configureUI()
fetchGlimpseData()
configureRefreshControl()
}
func configureRefreshControl() {
let refreshControl = UIRefreshControl()
refreshControl.addTarget(self, action: #selector(handleRefresh), for: .valueChanged)
glimpseTableView?.refreshControl = refreshControl
}
private func createSpinnerFooter() -> UIView {
let footerView = UIView(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: 100))
let spinner = UIActivityIndicatorView()
spinner.center = footerView.center
spinner.color = .brick
footerView.addSubview(spinner)
spinner.startAnimating()
return footerView
}
@objc func handleRefresh() {
glimpse.removeAll(keepingCapacity: false)
self.currentKey = nil
fetchGlimpseData()
}
func fetchGlimpseData() {
if lastDocument == nil {
GLIMPSE_ALL_USERS_DATA.order(by: TIMESTAMP, descending: true).limit(to: 3)
.getDocuments { [self] (snapshot, error) in.... //this block of code works properly
else {
glimpseTableView.tableFooterView = createSpinnerFooter()
GLIMPSE_ALL_USERS_DATA.order(by: TIMESTAMP, descending: true).start(afterDocument: lastDocument!).limit(to: 3)
.getDocuments { [self] (snapshot, error ) in.......//this block of code works properly
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
let position = scrollView.contentOffset.y
let maxOffset = scrollView.contentSize.height - scrollView.frame.size.height
if maxOffset - position <= 50 {
fetchGlimpseData()
}}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return glimpse.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let gCell = glimpseTableView.dequeueReusableCell(withIdentifier: "GlimpseCell", for: indexPath) as! GlimpseCell
gCell.delegateProfilePic = self
gCell.delegateGlimpseZoom = self
gCell.delegateGlimpseOption = self
gCell.configureGlimpseCell(glimpse: glimpse[indexPath.row])
gCell.separatorInset = .init(top: 5, left: 0, bottom: 5, right: 0)
gCell.backgroundColor = .beige
gCell.layer.borderWidth = 1
gCell.layer.borderColor = UIColor.gray.cgColor
gCell.selectionStyle = .none
return gCell
}
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
return .delete
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return false
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
guard editingStyle == .delete else { return }
glimpseTableView.beginUpdates()
glimpse.remove(at: indexPath.row)
glimpseTableView.deleteRows(at: [indexPath], with: .automatic)
glimpseTableView.reloadData()
glimpseTableView.endUpdates()
}
Thanks for showing your code. There are many things I do not see, but as far as I check the currently shown parts of your code, you need to keep two properties glimpse
and lastDocument
consistent.
When you remove all the elements from glimpse
, you need to set lastDocument
to nil
.
glimpse.removeAll(keepingCapacity: false)
lastDocument = nil //<-
There may be other parts you need to fix, frankly I do not understand why the app crashes because the indexPath.row is out of range. But please try adding one line shown above and tell us what happens.