Uitableview Load More When Scrolling to Bottom

UITableView load more when scrolling to bottom like Facebook application

You can do that by adding a check on where you're at in the cellForRowAtIndexPath: method. This method is easy to understand and to implement :

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Classic start method
static NSString *cellIdentifier = @"MyCell";
MyCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell)
{
cell = [[MyCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MainMenuCellIdentifier];
}

MyData *data = [self.dataArray objectAtIndex:indexPath.row];
// Do your cell customisation
// cell.titleLabel.text = data.title;

BOOL lastItemReached = [data isEqual:[[self.dataArray] lastObject]];
if (!lastItemReached && indexPath.row == [self.dataArray count] - 1)
{
[self launchReload];
}
}

EDIT : added a check on last item to prevent recursion calls. You'll have to implement the method defining whether the last item has been reached or not.

EDIT2 : explained lastItemReached

TableView loading more cell when scroll to bottom

Add a boolean parameter to avoid infinite loop.

var isLoading = false

func loadData() {
isLoading = true
self.showLoadingView()
apiCALL(callback: { data
self.isLoading = false
self.jsonDATA.append(contentsOf: data)
self.tableView.reloadData()
})
}


func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
let lastData = self.data!.count - 1
if !isLoading && indexPath.row == lastData {
currentPage += 1
self.loadData()
}
}

UITableView load more data when scrolling to top?

When you are updating your data, you need to get the current offset of the tableView first. Then, you can add the height of the added data to the offset and set the tableView's offset like so:

func updateWithContentOffsset(data: [String]) {
guard let tableView = tableView else {
return
}
let currentOffset = tableView.contentOffset
let yOffset = CGFloat(data.count) * tableView.rowHeight // MAKE SURE YOU SET THE ROW HEIGHT OTHERWISE IT WILL BE ZERO!!!
let newOffset = CGPoint(x: currentOffset.x, y: currentOffset.y + yOffset)
tableView.reloadData()
tableView.setContentOffset(newOffset, animated: false)
}

You can also take a look at the gist that I created. Simply open up a new iOS Playground and copy-paste the gist.

The only thing you have to be aware of is that make sure you know your row height to add to the offset.

Load More After Coming to Bottom of UITableView

Add a UIActivityIndicatorView (i.e. spinner) to your UITableViewController. Connect the outlet to the code:

@IBOutlet weak var spinner: UIActivityIndicatorView!

Add a property to your UITableViewController to keep track that you're currently loading more data so that you don't try to do it twice:

var loadingData = false

Start the spinner animating and then call refreshResults2():

func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
if !loadingData && indexPath.row == refreshPage - 1 {
spinner.startAnimating()
loadingData = true
refreshResults2()
}
}

Have refreshResults2() run on a background thread. This will allow your table to still move freely. The animated spinner will tell the user that more data is coming. Once your query returns, update the table data on the main thread.

func refreshResults2() {
dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0)) {
// this runs on the background queue
// here the query starts to add new 40 rows of data to arrays

dispatch_async(dispatch_get_main_queue()) {
// this runs on the main queue
self.refreshPage += 40
self.tableView.reloadData()
self.spinner.stopAnimating()
self.loadingData = false
}
}
}

Auto scroll to bottom of UITableView

let indexPath = IndexPath(item: noOfRows, section: 0)
yourTableView.scrollToRow(at: indexPath, at: UITableView.ScrollPosition.bottom, animated: true)

load more for UITableView in swift

To answer your question made a small test! One possible solution to this problem is to make another array and add it to the data that you want to display in the table and load the data to the same that you want to load! Loading data will willDisplayCell forRowAtIndexPath

var allObjectArray: NSMutableArray = []
var elements: NSMutableArray = []

var currentPage = 0
var nextpage = 0

override func viewDidLoad() {
super.viewDidLoad()
for var i = 0; i <= 500; i++ {
allObjectArray.addObject(i)
}
elements.addObjectsFromArray(allObjectArray.subarrayWithRange(NSMakeRange(0, 20)))
}
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
println(indexPath.row)
nextpage = elements.count - 5
if indexPath.row == nextpage {
currentPage++
nextpage = elements.count - 5
elements.addObjectsFromArray(allObjectArray.subarrayWithRange(NSMakeRange(currentPage, 20)))
tableView.reloadData()
}
}

test project

https://drive.google.com/file/d/0B-CqajDlBoGHSE1OcjFoZWJxUTg/view?usp=sharing

Load more items scrolling up on uitableview

You need a few methods:

Fetch Method -
This depends on how you are implementing the data retrieval. Say by default you only show the most recent 10 comments. If your array contains only these 10 comments, then you need a mechanism to perform a fetch of either a local or a remote database to pull another 10 additional comments and add them to the array. If though the array always contains all comments related to that post (say 56 comments in this case), the additional fetch is not necessary, though one could argue that retrieving and storing comments that users might never see is inefficient. Some math will need to be carried out in order to display the right amount of comments, but I will get to this in a little bit.

Updating the Table -
You will want to call [tableView reloadData] when the top cell is viewed because there will be more data to show. Depending on whether the array contains only the comments to be displayed or all comments related to the post, you may need to call the fetch method above as well. For example, if your array contains only 10 comments and you need to pull the additional 10, then you will first need to perform the fetch, and when the fetch completes you will need to call reloadData. If the array contains all 56 comments, then you will need to update the numCommentsToShow property as described below, and then immediately call reloadData

Update Trigger -
The method that reloads the table needs to be called when the top cell is viewed; however, you do not want to call the reload table right away when the view first appears. There are numerous ways of accomplishing this, and it really depends on if you want to additional comments to appear when the top cell is partially visible, fully visible, or even about to be viewed (which actually might be the cleanest for the user). One easy implementation (but not necessarily the most ideal) is to include the call to update the table in the cellForIndexPath method. If indexPath.row is 0 then call update. You will want to first test though that the view was not just loaded before allowing the update. You will also want the cell returned to the contain the comment that would have appeared before the update, because the cellForIndexPath method will be called again after the fetch. If you want the cell to be fully visible before allowing the update, you could do something like this: Best way to check if UITableViewCell is completely visible

The Math -
If the array only contains the comments to be shown, I would actually make the NSMutableArray an NSArray. When you get the results of the fetch, I would just hold those 20 comments in a completely new array, and have the comment array property just reference the new array. Then call reloadData. Otherwise, adding the comments to an NSMutableArray while the user is scrolling sounds a bit dangerous to me, but I could be wrong. Btw, some people might actually only perform the fetch on the 10 next comments (i.e. 11-20), but I would retrieve 1-20 if you are allows the users to edit their comments since the most recent comments are the ones most likely to change. After the fetch, the array will contain the 20 comments, and they should be in order of least to most recent. This makes it easy for the cellForIndexPath method, which should just retrieve the comment at index indexPath.row for each cell. The cell currently being viewed (the same one before the update) would be at the index equal to the number of new items just pulled.

If the array contains all comments related to the post (56 in my example), then you need to have a property that contains the number of comments to be displayed at this given point in time. When the view first appears, this property is set to some default number (10 in my example). The numberOfRowsInSection method needs to return this property which I will call numCommentsToShow. However, the cellForIndexPath needs to retrieve the correct items in the array. If they sorted from least recent to most recent, you actually need to retrieve the comment at the index equal to the number of comments in the array less numCommentsToShow plus indexPath.row. It gets a bit confusing doing it this way. When you call the update, you need to increase numCommentsToShow by some incremental amount (in my example) 10, but you should be careful to not increase it to greater than the number of items in the array. So you should actually increase it by the minimum of the incremental amount and the amount of comments not yet shown.

Issues with Scrolling
You probably will encounter some issues while scrolling since the cell at the top of the table will actually become one of the middle cells of the table. Thus, the table will likely jump to the top after the update. There is some math that you can do to ensure that the scroll position of the table after the update is set so that it appears to the user that the position of the scroll has not changed, when in reality it has. And there is an even more difficult challenge that will occur if the user moves the table down while the table has not yet updated.

Before explaining how to do this, the trend these days seems to be avoiding this situation. If you look at the facebook app, there is never really a infinite scroll to the top. There is a button to load the newer posts that automatically scrolls to the top. And comments on posts start at the top with the least recent comment and you can click a button to "view more comments" to see more recent ones. Not to say that this is good user experience, but programming the fix might be more time confusing than it's worth.

But anyway, to get around the scroll issue, I would use the setContentOffset method since a UITableView inherits from UIScrollView. You should not use the scrollToRowAtIndexPath method of a UITableView since it is possible that the current scroll position might not be completely lined up with any given row. You should make sure that the animated parameter is set to NO. The exact position though that you want to scroll to involves a bit of math and timing. It is possible that the user has scrolled to a new position while the data was being fetched, so you have offset the current position, not whatever the position was before the fetch. When the fetch is complete and you reload the table, you need to immediately call setContentOffset. The new y position needs to be the current scroll y position + to the number of new comments to show * the row height.

There is a bit of a problem though. It is possible that the view will be in the middle of scrolling when the fetch is complete. Calling setContentOffset at this point will probably cause a jump or a stall in the scrolling. There are a few ways of handling this case. If the user has scrolled away from the top of the table, then perhaps he/she might not want to view those records anymore. So perhaps you ignore the data you fetched or save it in another place without including the results in the table. Another is to wait until the table is finished scrolling before using the new data. The third way to continue scrolling with the same velocity and deceleration as you were before the table was reloaded, but I am not sure how you would accomplish this offhand.

To me this is more pain than it's worth.

Hope this helps,



Related Topics



Leave a reply



Submit