UITableView Pagination - Bottom Refresh to Load New Data in Swift
Nope, you can't go with that approach because cellForRowAtIndexPath
is called many times and also it will take much time to check your conditions!
Here, I have found a better option for UITableView
pagination.
func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) {
//Bottom Refresh
if scrollView == tableView{
if ((scrollView.contentOffset.y + scrollView.frame.size.height) >= scrollView.contentSize.height)
{
if !isNewDataLoading{
if helperInstance.isConnectedToNetwork(){
isNewDataLoading = true
getNewData()
}
}
}
}
}
isNewDataLoading
is Bool
to check that UITableView
is loading new data or not!
Hope this helps!
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
Swift tableView Pagination
For that you need to have server side change also.
Server will accept
fromIndex
andbatchSize
in theAPI
url as query param.let listUrlString = "http://bla.com/json2.php?listType=" + listType + "&t=" + NSUUID().UUIDString + "&batchSize=" + batchSize + "&fromIndex=" + fromIndex
In the server response, there will be an extra key
totalItems
. This will be used to identify all items are received or not. An array or itemsfromIndex
tobatchSize
number of items.
In the app side
First
loadItem()
will be called withfromIndex = 0
andbatchSize = 20
(for example inviewDidLoad()
orviewWillAppear
). removeAll items fromprivateList
array before callingloadItem()
for the first timeServer returns an array of first 20 items and
totalItems
total number of items in the server.Append the 20 items in
privateList
array and reloadtableView
In
tableView:cellForRowAtIndexPath
method check if the cell is the last cell. And check iftotalItems
(form server) is greater thanprivateList.count
. That means there are more items in the server to loadif indexPath.row == privateList.count - 1 { // last cell
if totalItems > privateList.count { // more items to fetch
loadItem() // increment `fromIndex` by 20 before server call
}
}
Question: where is refresh ? will be scrolling ?
Refresh after appending new items in the array when server response received. (step 3)
Scrolling will trigger tableView:cellForRowAtIndexPath
for every cell when user scrolls. Code is checking if it is the last cell and fetch remaining items. (step 4)
Sample project added:
https://github.com/rishi420/TableViewPaging
Weird behaviour of UITableViewCell after table reload when paging enabled for UITableView
Link it to tableView's height, your table view has all sizes you need.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) {
// ...
cell.viewHeight.constant = tableView.frame.size.heigh
// ...
}
or remove viewHeight
constraint and use delegate method to set row height
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return tableView.frame.size.height
}
UPD:
TableView using estimatedRowHeight
to calculate its scroll offsets. This does create an issue during reload if we have enabled paging and do not configure estimatedRowHeight
.
Solution 1:
Implement estimatedHeightForRowAt
delegate
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return tableView.frame.size.height
}
Solution 2:
Set tableView.estimatedRowHeight = 0
and use heightForRowAt
delegate instead of viewHeight
constraint
Related Topics
Using the C API for Imagemagick (On Iphone) to Convert to Monochrome
Google Maps Url Scheme Not Working on iOS 9
Hide Red Recording Status Bar in iOS App When Not Recording
Change Button Title Color in Uialertview
Open iOS 11 Files App via Url Scheme or Some Other Way
<Googlemaps/Googlemaps.H> File Not Found Google Maps Sdk for iOS
403 Error: Disallowed_Useragent
Afnetworking 2.2.0 Upload Image on Server Issues
Expandable Uitableview Cell Using Autolayout Results in Uiviewalertforunsatisfiableconstraints
Avassetwriter Avvideoexpectedsourceframeratekey (Frame Rate) Ignored
API Facebook iPhone , Possible to Post to a Friend's Wall
Non-Nominal Type X Does Not Support Explicit Initialization
Protocol Extension, Mutating Function
Swift Regular Expression Format
How to Mute/Unmute Audio When Playing Video Using Mpmovieplayercontroller