3

Context

  • Building a type of newsfeed

Problem

  • I need to load more posts when the user scrolls to the last table view cell
  • I have no idea where to start, how to implement, where in code
  • So basically I need to call to server to download posts when user scrolls to last table view, append those posts to the bottom of the current table view

Here are the relevant code pieces (I think!)

class GeneralPostAreaController: UIViewController {
        ...
        extension GeneralPostAreaController: UITableViewDataSource {

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        return PostsCollection.postsFromParse.posts.count

    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("PostCell") as! PostTableViewCell
        cell.postImage.image = PostsCollection.postsFromParse.posts[indexPath.row].image
        cell.postName.text = PostsCollection.postsFromParse.posts[indexPath.row].name
        cell.postText.text = PostsCollection.postsFromParse.posts[indexPath.row].text

        cell.loadAudio = PostsCollection.postsFromParse.posts[indexPath.row].audioObject.parseAudioData
        return cell
    }

}

And here is the code I use to get data from server (Parse). Excuse the horrible data structure, this is my first app!

    class ParseQueryer: NSObject{

//HAVE TO RESTRUCTURE

var posts: [Post] = []

//this is not a very elegant way to reload table Data
func getPosts(selectedTableView: UITableView){

var query = PFQuery(className: "Post")
query.addDescendingOrder("createdAt")
query.limit = 10
query.findObjectsInBackgroundWithBlock {(result: [AnyObject]?, error: NSError?) -> Void in
    self.posts = result as? [Post] ?? []

    selectedTableView.reloadData()

    for post in self.posts{
        post.name = post["Name"] as? String
        post.text = post["Text"] as? String
        //println(post.text)
        if let audioData = post["Audio"] as? PFFile {
            audioData.getDataInBackgroundWithBlock({
                (audioData: NSData?, error: NSError?) -> Void in
                if (error == nil){
                    post.audioObject.parseAudioData = audioData
                }
            })
        }
        if let imgData = post["Photo"] as? PFFile {
            imgData.getDataInBackgroundWithBlock({
                (imageData: NSData?, error: NSError?) -> Void in
                if (error == nil){
                    let image = UIImage(data: imageData!)
                    post.image = image
                }
            })
        }

    }
}
    selectedTableView.reloadData()

I looked at the answer here but it doesn't make sense to me.

Community
  • 1
  • 1
Michael Ninh
  • 772
  • 2
  • 10
  • 23

3 Answers3

1

so UITableView inherits from UIScrollView so you can use the scrollview delegate methods to know when you have scrolled to the bottom.

    override func scrollViewDidScroll(scrollView: UIScrollView) {

       //1. decide on the distance from the bottom that if the user scrolls to that point you will load more results
        let minimumTrigger = scrollView.bounds.size.height + self.triggerDistanceFromBottom

        // 2. Now you are checking to see that the height of all the content in the scrollview/tableView.( i.e. all the cells hights stacked ontop of eachother) is greater than the minimum height for triggering a load
       // This step is so that if you have only a few results, the loadMoreResults method won't constantly be called. 
        if scrollView.contentSize.height > minimumTrigger {

           //3. This calculated the distance from the bottom of the scrollview. 
            let distanceFromBottom = scrollView.contentSize.height - (scrollView.bounds.size.height - scrollView.contentInset.bottom) - scrollView.contentOffset.y

            //4. then this is the crucial check.
            if distanceFromBottom < self.scrollTriggerDistanceFromBottom {
                // Do your stuff
            }
        }

    }
villy393
  • 2,985
  • 20
  • 28
0

You can do your load more operation by this approach,as a table view delegate is a scroll view delegate:

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    float bottomEdge = scrollView.contentOffset.y + scrollView.frame.size.height;
    if (bottomEdge >= scrollView.contentSize.height)
    {
        // we are at the end

       if(currentCount<pageCount)
       {
           if(isLoading)
           {
               return;
           }
           UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
           [spinner startAnimating];
           spinner.frame = CGRectMake(0, 22, 50, 44);
           self.tblCentreEvents.tableFooterView = spinner;

            isLoading=TRUE;
           dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
               [self populateDataInList];

           });


       }

    }
}
Vizllx
  • 9,135
  • 1
  • 41
  • 79
0

The best way is to test a point at the bottom of the screen and use this method call when ever the user scrolls (scrollViewDidScroll):

- (NSIndexPath *)indexPathForRowAtPoint:(CGPoint)point

Test a point near the bottom of the screen, and then using the indexPath it returns check if that indexPath is the last row then if it is, add rows.

Vikram Parimi
  • 777
  • 6
  • 29