0

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?

magellan
  • 63
  • 7

2 Answers2

0

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) }
}
ethanrj
  • 56
  • 4
  • I am trying to understand your function. I have an arrayA that holds 10 elements. I run my batch fetch and add 10 more elements. arrayA has 20 elements. I then take arrayA.count - the new items.count to get the start index. Then you want me to take the startIndex + newItems.count but I think I could just take arrayA.count - 1 for the end Index. Then you want me to map thru to return a result. I dont really understand the result. How do I implement this result into the reloadRowsAtIndexPath function? – magellan Nov 22 '19 at 00:58
  • Also what if I get zero new elements. If I get zero new elements, startIndex would be 10 but I dont have a 10th indexed element in my array so my app would crash. – magellan Nov 22 '19 at 01:03
  • What im trying to say is that you dont need to reload the entire table view with that method, just the rows that are new, and only if there are any new rows that need to be reloaded. Your old rows should be fine. – ethanrj Nov 22 '19 at 23:28
0

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()
    }

}
magellan
  • 63
  • 7