Preloading data from network in UITableView - ios

I have a page that support pagination when loading data from network.
I'm using a UITableview to display list.
I want to preload next page when user scroll near the end of current page.
For example, each page has 10 items. When item 8 is visible in the screen, I shall start loading of next page immediately.
Which delegate method of UITableView is the best choice for this task?

Try the following method, It will get to know the display cell
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell
forRowAtIndexPath:(NSIndexPath *)indexPath
{
// Webservice Call for next 10 display data
}
Discussion
A table view sends this message to its delegate just before it uses cell to draw a row, thereby permitting the delegate to customize the cell object before it is displayed. This method gives the delegate a chance to override state-based properties set earlier by the table view

UITableView is a subclass of UIScrollView, so you can use it delegate methods. I suggest you to use this two:
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
if (!decelerate) {
NSSet *visibleRows = [NSSet setWithArray:[self.view.tableView indexPathsForVisibleRows]];
}
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
NSSet *visibleRows = [NSSet setWithArray:[self.view.tableView indexPathsForVisibleRows]];
}
Check your clause after you get visibleRows and preload your data if, for example, last indexPath.row in NSSet is equal to your datasource array count (or is equal to [array count] - some_number_you_want )
To archive, when tableView start scrolling, you can implement your preload logic here:
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
NSSet *visibleRows = [NSSet setWithArray:[self.view.tableView indexPathsForVisibleRows]];
// your update code here
}
Hope this helps.

add this method in the UITableViewDelegate:
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGFloat height = scrollView.frame.size.height;
CGFloat yOffset = scrollView.contentOffset.y;
CGFloat distanceFromBottom = scrollView.contentSize.height - yOffset;
if(distanceFromBottom < height)
{
NSLog(#"end of the table and call web service or load more data");
}
}

Use UITableViewDataSourcePrefetching or UICollectionViewDataSourcePrefetching to preload data from network and have your cells ready when displayed to the user

Related

iOS Objective C : How to increase number of rows after given condition

I am very new to iOS, Living in a very small village with no help on iOS, I need help in my code where I can increase number of rows once I reach to row number 20.
I actually have more than 6000 lines, when try to show all of them in tableview, it takes lot of time, so I want to load all rows in efficient way, like increasing it like +20, +50 etc
here is my code:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return a;
}
and I am trying to increase rows like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if(indexPath.row == 20)
{
[_myTable reloadData];
[self.myTable beginUpdates];
a= a +50;
[self.myTable endUpdates];
}
if (indexPath.row > 60)
{
[self.myTable beginUpdates];
a= a +100;
[self.myTable endUpdates];
}
}
I declared myTable as property
I am sorry if my post is looking foolish I am at very basic position and sorry for my bad English.
The numbers of rows to be displayed in a tableView depends on data available i.e., the data to be displayed in the UITableView.
Let an array "Countries" containing list of 3 countries:
NSArray *countries;
countries = #[#"India",#"USA",#"Germany",nil];
so, now the UITableView has 3 rows, so use this:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return countries.count;
}
so if the countries list increased later, then it will work.
No need to increase number of rows in table manually.
If the response is from server, then use this:
NSArray *dataArray = [responseObject objectForKey:#"countriesJson"];
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return dataArray.count;
}
Sample Project:
Please check my GitHub link below:
https://github.com/k-sathireddy/TableRowCountDynamic
Note: More images are loaded if we reach a certain limit.
You have to follow below algorithm or logic,
1)First just initialize your array with the 20 objects and that array will use for the display in a UITableView as a datasource.
2)Then you need to implement the UIScrollView delegate method, - (void)scrollViewDidScroll:(UIScrollView *)aScrollView in which you can write a some code like this:
- (Void) scrollViewDidScroll: (UIScrollView *) aScrollView
{
self.tbleSerachResult.frame=self.tbleSerachResult.frame;
if (aScrollView==self.tblOutlet) {
[currentTextfield resignFirstResponder];
CGPoint offset = aScrollView.contentOffset;
CGRect bounds = aScrollView.bounds;
CGSize size = aScrollView.contentSize;
UIEdgeInsets inset = aScrollView.contentInset;
float y = offset.y + bounds.size.height - inset.bottom;
float h = size.height;
float reload_distance = 10;
if(y > h + reload_distance)
{
//add more 20 records to your existing array which used for the UITableView data source and reload the UITableView.
//Put your load more data method here...
}
}
}
3) after this, you doesn't require any other thing to maintain this. Just implement the UITableView delegate and datasource methods as normally. It will work.
Try this way, if still facing any issue let me know I will give you example code.
Hope it works for you!! Happy coding :)

iOS - How to create a never ending scrolling news feed

I have to create a social app, which currently displays only 20 items in a user's news feed. Once they hit the bottom there is a "Load More button this will then extend the stable to the next 20 items.
Its very manual and not very fluid, is there a way to automate this?
The feature is something very similar to the likes of Facebook and Twitter, so I know it is possible but my Googling is only taking me so far as I don't know the right terminology to use for this feature.
Any help would be great!
You can start fetching the next items once the user is near the end of the list.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSInteger maximumNumberOfRows = [tableView numberOfRowsInSection:indexPath.section];
if (indexPath.row >= maximumNumberOfRows - kReloadOffset) {
[self fetchNextItemsFromWebserviceWithOffset:maximumNumberOfRows];
}
In fetchNextItemsFromWebserviceWithOffset you can fetch more news items and update your table view with [self.tableView reloadData].
You can get data when you are near to end using this method or you can also use Mark Gibson's Code.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGFloat offsetY = scrollView.contentOffset.y;
CGFloat contentHeight = scrollView.contentSize.height;
if (offsetY > contentHeight - scrollView.frame.size.height - screensizehere*2)
{
if (!isCalling)
{
isCalling = YES;// when you response data change this bool to NO.
[self getdatainbg];//call your service.
}
}
}
Maybe this will help you.
Use Table view. Load only 20 or whatever amount you require. When you get to the end of the scroll load another 2O. Its very basic and simple. Your cells will get reused again and again and its a never ending, till data is available.
Make your UIViewController class to listen for UIScrollViewDelegate
#interface Yourclass : UIViewController<UIScrollViewDelegate>
/*Your getters & setters, method declarations*/
#end
#pragma mark UIScrollViewDelegate & refresh for auto scroll
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
/*Auto scroll Code.. Raja implemented..*/
if (([scrollView contentOffset].y + scrollView.frame.size.height) == [scrollView contentSize].height) {
[self performSelector:#selector(refreshPage) withObject:nil afterDelay:0.0];
return;
}
}

Hide section for UITableView on first load

I have a UITableView with 2 sections (the 1st for the filters and the 2nd for the data).
I want to hide the 1st section when the view is loaded.
The section appears only when I scroll on top.
I tested with scrollToRowAtIndexPath: but the result is not as expected.
Please help. Thanks.
Take a BOOL variable for checking whether to load one section or
two section.
Make is YES in ViewDidLoad then,for the first time UITableView will load one section.
Then when UITableView will be scrolled to top,make that BOOL variable to NO
- (void)viewDidLoad
{
[super viewDidLoad];
isFirstTime = YES;
}
In datasource method of TableView
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
if (isFirstTime) {
return 1;
}
return 2;
}
For checking the UITableView to scroll TOP.We will use delegate methods of UIScrollview.UITableView is the subclass of UIScrollView.
-(void)scrollViewDidScroll:(UITableView *)tableView{
CGFloat content_Offset = tableView.contentOffset.y;
if (content_Offset >= 0 && isFirstTime){
//UITableview is scrolled to top
isFirstTime = NO;
[self.myTbaleView reloadData];
}else if (content_Offset<0) {
//UITableview is draged down
}
}
You can add a BOOL variable to find out whether it is loading first time or not. Set it true in the viewDidLoad like:
- (void)viewDidLoad
{
[super viewDidLoad];
isFirstTimeLoading = YES;
}
Then in your numberOfSectionsInTableView: delegate method,
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
if (isFirstTimeLoading) {
return 1;
} else {
return 2;
}
}
TableView scrolling to top can be find out using
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
In this method, check whether the row is top row. if yes then make isFirstTimeLoading to NO and reload data. Dont forget to change the data also if necessary.

UItableView load data 10 10 records on scroll

I am getting the data from the web-service and I have to display it in UITableView. But the condition here is I have to display only 10 records initially,then once the user scroll down I have to load more records it contains image also.I tried searching it but didn't get any useful answer.
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { }
display the value,but how will I fetch only 10 records initially ce and then other record based on scroll. Please provide some points or sample code
In your backend link keep an ' index' field. When index=0, get the 10 records from backed then increment index to 1, get another 10 records,etc...
keep the code also to call link when scroll the tableView at the end ,
-(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
NSInteger currentOffset = scrollView.contentOffset.y;
NSInteger maximumOffset = scrollView.contentSize.height- scrollView.frame.size.height;
if (maximumOffset - currentOffset <= 0) {
index =index +1;
// Call your link here
}
}
Inside your cellForRowAtIndexPath: method you could always check if the current row equals the count of your data - 1:
if(indexPath.row == tableData.count - 1)
{
[self getMoreData];
}
I assume that in your web service you will get page number and 10
record as per page
when you scroll in tablview it will call willDisplayCell and check
current Array count.
if your scroll reach equal to array count or last record it will request data again with page number.
//Declare variable
NSInteger currentPageNumber;
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{
if (indexPath.row == arrData.count-1) {
currentPageNumber++;
//Call your Webservice
}
}
-(void)webserviceCall{
//pass page number in your web service you will get data with page number
// After getting data from web service you need to add data in your array, so you will have total records.
if([[jsonResponse objectForKey:#"status"] intValue] == 1){
[arrData addObjectsFromArray:arrData];
}
}

How would I access the tableView in a non tableView method?

how would I access this code for determining which tableView is being used in a non tableView method?
I know how to use it in the tableView:numberOfRowsInSection: method but how would I access it in a method I make?
do I use UITableView instead of tableView?
-(void)myMethod {
if ([tableView isEqual:self.tableViewNode])
{
}
if ([tableView isEqual:self.tableViewCities])
{
}
}
I'm looking to see if a tableView is scrollViewDidEndDecelerating: and then perform an action.
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
// NSLog(#"scrollViewDidEndDecelerating");
if ([UITableView isEqual:self.tableViewNode])
{
float endScrolling = scrollView.contentOffset.y + scrollView.frame.size.height;
if (endScrolling >= scrollView.contentSize.height)
{
index ++;
[self getFeed:index];
}
}
if ([UITableView isEqual:self.tableViewCities])
{
}
}
Inside a UIScrollViewDelegate method, you can compare the scrollView argument to the table view properties.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (self.firstTableView == scrollView) {
// respond to firstTableView scrolling
}
else if (self.secondTableView == scrollView) {
// respond to secondTableView scrolling
}
}
If you need to implement methods in your table view's delegate that are called by the delegate methods, but behave differently based on which table view called the calling method, then you should make those methods take a table view parameter and always pass the the table view argument of the delegate methods when you call them. Inside these methods, compare tableView to your properties.
- (void)myMethod:(UITableView *)tableView
{
if (self.firstTableView == tableView) {
// do something for firstTableView
}
else if (self.secondTableView == tableView) {
// etc
}
}
If you needed to call myMethod: from tableView:didSelectRowAtIndexPath: for instance, you'd do something like this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self myMethod:tableView];
}

Resources