Reload TableView only at new added Cells

892 views Asked by At

I have a scrollToBottom function that notifies the app when to beginBatchFetches for content, pics, and checks.

   //1: User Scrolls all the way down calls beginBatchFetch()
   func scrollViewDidScroll(_ scrollView: UIScrollView) {
         let offsetY = scrollView.contentOffset.y
         let contentHeight = scrollView.contentSize.height
         print("offsetY: \(offsetY)")
         if offsetY > contentHeight - scrollView.frame.height {
            if self.viewSelected == "Content" {
                if !contentFetchMore {
                    beginContentBatchFetch()
                }
            } else if self.viewSelected == "Pics" {
                    if !picFetchMore {
                        beginPicBatchFetch()
                    }
            } else if self.viewSelected == "Checks" {
                        if !checksFetchMore {
                            beginChecksBatchFetch()
                        }
                    }
            }

     }

These are the beginBatchFetchMethods. Self.reload currently reloads the whole Tableview:

 func beginContentBatchFetch() {
    contentFetchMore = true
    ProgressHUD.show()
    DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
        self.checkQueryContinous()

        ProgressHUD.dismiss()
    }

}




func beginPicBatchFetch() {
     picFetchMore = true
           ProgressHUD.show()
           DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
            self.PicContinous()
            self.Reload()
            ProgressHUD.dismiss()
           }

}

func beginChecksBatchFetch() {
    checksFetchMore = true
           ProgressHUD.show()
           DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
            self.checkQueryContinous()
            self.Reload()
            ProgressHUD.dismiss()
           }

}

Instead of reloading the whole TableView. I would like to only reload the new added cells. For example, if I had 10 cells before the batchfetch and then 20 cells after the batchfetch, I would like to only reload the tableview for those cells 11-20.

I looked online and StackOverFlow brought me to this: iOS Swift and reloadRowsAtIndexPaths compilation error

      var _currentIndexPath:NSIndexPath?
      if let indexPath = _currentIndexPath {
     self.tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: 
     UITableViewRowAnimation.None)
      }
      else {
 `    //_currentIndexPath` is nil.
      // Error handling if needed.
    }

This from what I understand only reloads the cells that are shown. However, my batchfetches may not return more values. As a result, my tableview will display the same cells as before the batch fetch and this would reload those cells. Since those cells were previously loaded, I do not want to waste data/screw up my tableview.

What do I do, thanks?

2

There are 2 answers

3
ethanrj On

What you need to do is calculate the rows that need to be reloaded and make sure you pass those indexPaths into the reload rows function after you update your data source with the new data.

 private func calculateIndexPathsToReload(from newItems: [Items]) -> [IndexPath] {
    let startIndex = results!.count - newItems.count
    let endIndex = startIndex + newItems.count
    return (startIndex..<endIndex).map { IndexPath(row: $0, section: 0) }
}
0
magellan On

This is what I have added complements to: https://www.youtube.com/watch?v=whbyVPFFh4M

I may have screwed up the for in loop function. I don't really understand mapping yet.

func beginContentBatchFetch() {
    contentFetchMore = true
    ProgressHUD.show()
    let oldcount = contentObjectIdArray.count
    var IndexPathsToReload = [IndexPath]()
    var startIndex = Int()
    var endIndex = Int()
    DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
        self.checkQueryContinous()
        let newElements = self.contentObjectIdArray.count - oldcount
        startIndex = self.contentObjectIdArray.count - newElements
        endIndex = self.contentObjectIdArray.count
        for index  in startIndex..<endIndex {
            let indexPath = IndexPath(row: index, section: 0)
            IndexPathsToReload.append(indexPath)
        }
        if newElements > 0 {
        self.BarSelectedTableView.reloadRows(at: IndexPathsToReload, with: .fade)
    }
        ProgressHUD.dismiss()
    }

}