Changing the height of UITableViewCell on selection and deselection - iphone

I have a UITableView with cells , which on selected shows a popup with "Yes" or "No" confirmation ,When "Yes" is selected , the height of cell should be increased to 100 and its background image should change and if "No" is selected , nothing should happen and it should remain as a normal cell...
Similarly , if already selected cell is selected , again it shows up popup of "Yes" or "No" confirmation . If "Yes" is selected , the selected cell should convert into a normal cell with height 44 and background image is removed . If "No" is selected , then nothing happens and cell remains as a selected cell...
how to deal with height changes and background image changes in such condition ????
#import "TableViewController.h"
#interface TableViewController ()
#end
#implementation TableViewController
- (id)initWithStyleUITableViewStyle)style
{
self = [super initWithStyle:style];
if (self)
{
objects = [NSArray arrayWithObjects:#"One",#"Two",#"Three",#"Four",#"Five",#"Six",#"Seven",#"Eight",#"Nine",#" Ten",#"Eleven",#"Twelve",#"Thirteen", nil];
selectedIndexPath = [[NSIndexPath alloc] init];
}
return self;
}
- (NSInteger)numberOfSectionsInTableViewUITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableViewUITableView *)tableView numberOfRowsInSectionNSInteger)section
{
// Return the number of rows in the section.
return [objects count];
}
- (UITableViewCell *)tableViewUITableView *)tableView cellForRowAtIndexPathNSIndexPath *)indexPath
{
NSString *CellIdentifier = [NSString stringWithFormat:#"Cell %d",indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseI dentifier:CellIdentifier];
cell.textLabel.text = [objects objectAtIndex:indexPath.row];
NSLog(#"cell description:- %#",[cell description]);
}
return cell;
}
- (CGFloat)tableViewUITableView *)tableView heightForRowAtIndexPathNSIndexPath *)indexPath
{
// if (indexPath == selectedIndexPath)
// {
// return 100 ;
// }
// if (indexPath == selectedIndexPath)
// {
// UITableViewCell *c = [self.tableView cellForRowAtIndexPath:indexPath];
// CGRect rect = c.frame ;
// rect.size.height = 100 ;
// c.frame = rect ;
// return 100;
// }
return 44;
}
-(void)tableViewUITableView *)tableView didSelectRowAtIndexPathNSIndexPath *)indexPath
{
if (selectedIndexPath == [self.tableView indexPathForSelectedRow])
{
UIAlertView *a = [[UIAlertView alloc] initWithTitle:#"DeSelect" message:#"DeSelect ??" delegate:self cancelButtonTitle:#"NO" otherButtonTitles:#"Yes", nil ];
[a show];
}
else
{
UIAlertView *a = [[UIAlertView alloc] initWithTitle:#"Select" message:#"Select ??" delegate:self cancelButtonTitle:#"NO" otherButtonTitles:#"Yes", nil ];
[a show];
}
}
-(void)alertViewUIAlertView *)alertView clickedButtonAtIndexNSInteger)buttonIndex
{
if (selectedIndexPath == [self.tableView indexPathForSelectedRow])
{
if (buttonIndex==1)
{
selectedIndexPath = [NSIndexPath indexPathForRow:-1 inSection:-1];
// [self tableView:self.tableView heightForRowAtIndexPath:selectedIndexPath];
//[self.tableView reloadData];
//[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:selectedIndexPath] withRowAnimation:UITableViewRowAnimationFade];
//[self.tableView beginUpdates];
//[self.tableView endUpdates];
[self showForIndexPath:selectedIndexPath];
[self.tableView beginUpdates];
[self.tableView endUpdates];
}
}
else
{
if (buttonIndex==1)
{
selectedIndexPath = [self.tableView indexPathForSelectedRow];
//[self tableView:self.tableView heightForRowAtIndexPath:selectedIndexPath];
//[self.tableView reloadData];
//[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:selectedIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
// [self.tableView beginUpdates];
// [self.tableView endUpdates];
[self showForIndexPath:selectedIndexPath];
[self.tableView beginUpdates];
[self.tableView endUpdates];
}
}
}
-(void)showForIndexPathNSIndexPath *)indexpath
{
UITableViewCell *c = [self.tableView cellForRowAtIndexPath:indexpath];
CGRect rect = c.frame ;
rect.size.height = 100 ;
c.frame = rect ;
//code to move the cells downward when a cell is selected
for(int i = indexpath.row ; i < [objects count];i++)
{
NSindexpath *row = [NSIndexPath indexPAthforRow:i+1 in Section:0];
UITableViewCell *tmp = [self.tableView cellforindexpath:row];
CGRect frame = tmp.frame;
CGpoint origin = frame.origin;
CGFloat y = origin.y ;
y = y+56; //(100-44)
origin.y = y ;
frame.origin = origin ;
tmp.frame = frame ;
}
NSLog(#"Cell %d :- %# indexpath:- %#",indexpath.row,[c description],indexpath);
}
P.S. -- You can see the attempts I have made to achieve the task by looking at the code that is commented

Keep a flag for yes or no and a index for selected row number.
-(CGFloat)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if ( flag == 1 && indexpath.row == index )
return 50;
else
return 30;
}
apply your logic of image also similarly when you create cell

please post the code what you have tried.
This link may help you.
Can you animate a height change on a UITableViewCell when selected?.
Use popup button index to change variable value and use that variable in
-(CGFloat)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
//change tablecell height based on variable value
}
-(void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if (buttonIndex == 0) {
}
}

Create two tableViewCell for the both casses. Then in your buttonTouch method, remove your previous cell using
- (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;
And then add newCell using:
- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;

Related

UITableViewCell Expandable Crash

I am facing a problem about expandable tableviewcell. It crashes when i try to expand tableviewcell.
I don't understand where app crashes. Please suggest me some solution.
Please Help Me.
My Code:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
if (appDelegate.array_proj == (id)[NSNull null])
return 0;
else
return [appDelegate.array_proj count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if ([expandedSections containsIndex:section])
{
if ([appDelegate.array_task count]==0)
{
return 0;
}
else
{
NSLog(#"array task count: %d",[appDelegate.array_task count]);
return [appDelegate.array_task count];
}
}
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell ==nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.backgroundColor = [UIColor clearColor];
cell.textLabel.textColor = [UIColor colorWithRed:53.0/255 green:53.0/255 blue:53.0/255 alpha:1.0];
UIImageView *backgroundView = [[UIImageView alloc] initWithFrame:CGRectZero];
cell.backgroundView = backgroundView;
backgroundView.image = [UIImage imageNamed:#"prjctcell_bg.png"];
if (!indexPath.row)
{
objePro = [appDelegate.array_proj objectAtIndex:indexPath.section];
cell.textLabel.text = objePro.projctname;
appDelegate.intForPid=objePro.pojctid;
if ([expandedSections containsIndex:indexPath.section])
{
cell.accessoryView = [DTCustomColoredAccessory accessoryWithColor:[UIColor blackColor] type:DTCustomColoredAccessoryTypeUp];
}
else
{
cell.accessoryView = [DTCustomColoredAccessory accessoryWithColor:[UIColor blackColor] type:DTCustomColoredAccessoryTypeDown];
}
}
else
{
if (appDelegate.array_task != (id)[NSNull null])
{
objePro = [appDelegate.array_proj objectAtIndex:appDelegate.storeAppDelegateIndex];
objeTask = [appDelegate.array_task objectAtIndex:indexPath.section];
cell.textLabel.text = objeTask.taskname;
cell.backgroundView = nil;
cell.accessoryView = nil;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
}
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canCollapseSection:(NSInteger)section
{
return YES;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
objePro = [appDelegate.array_proj objectAtIndex:indexPath.section];
appDelegate.intForPid=objePro.pojctid;
[appDelegate selectTask:appDelegate.intForPid];
if (!indexPath.row)
{
[tblView beginUpdates];
//only first row toggles expand/collapse
[tblView deselectRowAtIndexPath:indexPath animated:YES];
NSInteger sections = indexPath.section;
BOOL currentlyExpanded = [expandedSections containsIndex:sections];
NSInteger rows;
NSMutableArray *tmpArray = [NSMutableArray array];
if (currentlyExpanded)
{
rows = [self tableView:tblView numberOfRowsInSection:sections];
[expandedSections removeIndex:sections];
}
else
{
[expandedSections addIndex:sections];
rows = [self tableView:tblView numberOfRowsInSection:sections];
}
for (int i=1; i<rows; i++)
{
NSIndexPath *tmpIndexPath = [NSIndexPath indexPathForRow:i inSection:sections];
[tmpArray addObject:tmpIndexPath];
}
UITableViewCell *cell = [tblView cellForRowAtIndexPath:indexPath];
if (currentlyExpanded)
{
[tblView deleteRowsAtIndexPaths:tmpArray withRowAnimation:UITableViewRowAnimationTop];
cell.accessoryView = [DTCustomColoredAccessory accessoryWithColor:[UIColor blackColor] type:DTCustomColoredAccessoryTypeDown];
}
else
{
[tblView insertRowsAtIndexPaths:tmpArray withRowAnimation:UITableViewRowAnimationTop];
cell.accessoryView = [DTCustomColoredAccessory accessoryWithColor:[UIColor blackColor] type:DTCustomColoredAccessoryTypeUp];
}
[tblView endUpdates];
}
}
It gives error:
Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-2380.17/UITableView.m:1070
2013-03-20 19:14:00.102 Daily Achiever[2886:c07] * Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 1. The number of rows contained in an existing section after the update (3) must be equal to the number of rows contained in that section before the update (1), plus or minus the number of rows inserted or deleted from that section (0 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'
Your problem is in these lines of code:
[tblView deleteRowsAtIndexPaths:tmpArray withRowAnimation:UITableViewRowAnimationTop];
and
[tblView insertRowsAtIndexPaths:tmpArray withRowAnimation:UITableViewRowAnimationTop];
The crash that you posted was due to the first one. In these lines, you are trying to insert/delete rows from the table, but your - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section method does not change correspondingly.
It looks like you want to add/remove items from your appDelegate.array_task array whenever you are adding/removing cells from the table (as this is the array from which you are determining the row count).
As a side note, the line:
if ([appDelegate.array_task count]==0) {
return 0;
}
is not doing anything, because you have else return [appDelegate.array_task count] which means that 0 will be returned if [appDelegate.array_task count]==0 anyway.
while adding sections use this code
NSArray *insertIndexPaths = [NSArray arrayWithObjects:
[NSIndexPath indexPathForRow:2 inSection:0],
[NSIndexPath indexPathForRow:3 inSection:0],
nil];
for inserting rows
[tableView insertRowsAtIndexPaths:insertIndexPaths withRowAnimation:UITableViewRowAnimationRight];
if u are adding two sections
[tableView insertSections:[NSIndexSet indexSetWithIndex:indexPath.section + 1] withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView insertSections:[NSIndexSet indexSetWithIndex:indexPath.section + 2] withRowAnimation:UITableViewRowAnimationAutomatic];
same way delete sections
[tableView deleteSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:YES];
[tableView deleteSections:[NSIndexSet indexSetWithIndex:indexPath.section - 1] withRowAnimation:YES];
rows delete
[tableView deleteRowsAtIndexPaths:insertIndexPaths withRowAnimation:UITableViewRowAnimationRight];

Load Data On Uitableview scroll [duplicate]

This question already has answers here:
making a "load more" button in uitableviewcell?
(4 answers)
Closed 9 years ago.
I have 2000 records and i have to display only 15 records in UITableView, When User Scroll UITableView , More 15 records shold be load in table. How should I do it?
I think the Answer is : - (void)scrollViewDidScroll:(UIScrollView *)scrollView
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGPoint offset = scrollView.contentOffset;
CGRect bounds = scrollView.bounds;
CGSize size = scrollView.contentSize;
UIEdgeInsets inset = scrollView.contentInset;
float y = offset.y + bounds.size.height - inset.bottom;
float h = size.height;
float reload_distance = 15;
if(y > h + reload_distance)
{
//Call the Method to load More Data...
}
}
Hope it will be helpful...!!!
You have to check the UIScrollView contentOffset for that (UITableView is built on UIScrollView). So, add this, to your UITableViewDelegate class:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
// when reaching bottom, load more
float offs = (scrollView.contentOffset.y+scrollView.bounds.size.height);
float val = (scrollView.contentSize.height);
if (offs==val)
{
//add more data on your data array
}
}
in order to add more cells to your table when user reaches bottom of your table view.
You can use two delegate methods of UIScrollView. As UITableView comes in hierachy of UIScrollView you'll get control in this delegate methods of UIScrollView.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
NSLog(#"TableView scrolling");
}
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
NSLog(#"TableView Started scrolling");
}
Try above two methods. And choose the one appropriate for you. First see how NSLog are coming when you start scrolling your UITableVIew. And then write your code inside them.
By Default numberOfItemsToDisplay = 15;
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
if (numberOfItemsToDisplay >= [self.yourArray count])
{
numberOfItemsToDisplay = [self.yourArray count];
return 1;
}
return 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (section == 0)
{
return numberOfItemsToDisplay;
}
else
{
return 1;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 0)
{
static NSString *CellIdentifier = #"YourCustomCell";
YourCustomCell *objYourCustomCell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (objYourCustomCell == nil)
{
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"YourCustomCell" owner:self options:nil];
for(id currentObject in topLevelObjects)
{
if ([currentObject isKindOfClass:[YourCustomCell class]])
{
objYourCustomCell = (AlertsCustomCell *) currentObject;
break;
}
}
}
objYourCustomCell.lbl.text = [[self.yourArray objectAtIndex:indexPath.row]valueForKey:#"vName"];
return objYourCustomCell;
}
else
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell=[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
[cell.contentView addSubview:[self loadMoreViewForTable:self.view]];
}
return cell;
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.tblAlertsList deselectRowAtIndexPath:indexPath animated:YES];
if (indexPath.section == 1)
{
numberOfItemsToDisplay = [self loadMore:numberOfItemsToDisplay arrayTemp:self.yourArray tblView:self.tblAlertsList];
[self.tblAlertsList endUpdates];
}else
{
// action if it is not LoadMore
}
}
+ (NSInteger)loadMore : (NSInteger)numberOfItemsToDisplay arrayTemp:(NSMutableArray*)aryItems tblView:(UITableView*)tblList
{
int count =0;
NSUInteger i, totalNumberOfItems = [aryItems count];
NSUInteger newNumberOfItemsToDisplay = MIN(totalNumberOfItems, numberOfItemsToDisplay + kNumberOfItemsToAdd);
NSMutableArray *indexPaths = [[NSMutableArray alloc] init];
for (i=numberOfItemsToDisplay; i<newNumberOfItemsToDisplay; i++)
{
count++;
[indexPaths addObject:[NSIndexPath indexPathForRow:i inSection:0]];
}
numberOfItemsToDisplay = newNumberOfItemsToDisplay;
[tblList beginUpdates];
[tblList insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationLeft];
if (numberOfItemsToDisplay == totalNumberOfItems) {
[tblList deleteSections:[NSIndexSet indexSetWithIndex:1] withRowAnimation:UITableViewRowAnimationLeft];
}
NSIndexPath *scrollPointIndexPath;
if (newNumberOfItemsToDisplay < totalNumberOfItems)
{
scrollPointIndexPath = [NSIndexPath indexPathForRow:numberOfItemsToDisplay-kNumberOfItemsToAdd inSection:0];
}
else
{
scrollPointIndexPath = [NSIndexPath indexPathForRow:i-count inSection:0];
}
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 100000000), dispatch_get_main_queue(), ^(void){
[tblList scrollToRowAtIndexPath:scrollPointIndexPath atScrollPosition:UITableViewScrollPositionNone animated:YES];
});
return numberOfItemsToDisplay;
}
I have to take custom cell to use this method? I have only taken UItableview
Try this:
http://www.cocoacontrols.com/controls/stableviewcontroller
use this two methods
//for refresh
- (void) addItemsOnTop {
//[self getLoginFollowingUserVideosCall];
[self refreshCompleted];
}
//for load more
- (void) addItemsOnBottom {
//[self getLoginFollowingUserVideosCall];
[self loadMoreCompleted];
}
What you have to do is load the tableview data lazily. Like load data for the tableview cell that are current visible & not all of the data at a time.

UITableView add row below selected row

I had a working tableview where I could double-tap a cell and it would add an 'action' cell below which had four buttons programmed on it.
Today I added alphabetic sections to the tableview and a section index and I can no longer get this functionality to work.
I've added a whole range of NSLogs to the code to try and find the problem and I can't, it seems to be trying to add a row in the same section and one row further down than the cell tapped, so I'm not sure what the problem is. Would anyone have any idea what I'm doing wrong?
If anyone can shed any light on this I would be hugely appreciative. (And apologies if my code is cumbersome or hard to follow, I'm new to this so feel free to suggest what I can improve!)
- (void)viewDidLoad
{
//I start with an array of objects, so I created two arrays; one containing the first letters of each Name, and a list of the number of objects that start with each of those names.
nameIndex = [[NSMutableArray alloc] init];
nameIndexCount = [[NSMutableDictionary alloc]init];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [nameIndex count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (self.actionRowIndexPath) {
//Returns first letter of the section
NSString *alphabet = [nameIndex objectAtIndex:section];
//Returns the number of entries starting with that letter
NSString *numberofRows = [nameIndexCount objectForKey:alphabet];
int intNumberOfRows = ([numberofRows integerValue] + 1);
return intNumberOfRows;
} else {
NSString *alphabet = [nameIndex objectAtIndex:section];
NSString *numberofRows = [nameIndexCount objectForKey:alphabet];
int intNumberOfRows = [numberofRows integerValue];
return intNumberOfRows;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"newTableViewCell"];
if (!cell) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"newTableViewCell"];
}
//Configure the cell
UIImageView *imageView = [[UIImageView alloc]initWithFrame:cell.frame];
UIImage *image = [UIImage imageNamed:#"LightGrey.png"];
imageView.image = image;
if ([indexPath isEqual:self.actionRowIndexPath]) {
// Four UIButtons coded programmatically
} else {
Contact *p = [[[ContactStore sharedStore]allContacts]objectAtIndex:totalNumberOfRows];
NSString *firstAndLastName = [NSString stringWithFormat:#"%# %#", [p firstName], [p lastName]];
indexPath = [self modelIndexPath:indexPath];
cell.backgroundView = imageView;
// [cell.imageView setImage:smallThumbnailImage];
[cell.imageView setImage:[p thumbnail]];
[[cell textLabel]setBackgroundColor:[UIColor clearColor]];
[[cell textLabel]setText:firstAndLastName];
[[cell detailTextLabel]setBackgroundColor:[UIColor clearColor]];
[[cell detailTextLabel]setText:[p phoneNumber]];
totalNumberOfRows = totalNumberOfRows + 1;
}
return cell;
}
#pragma mark - Action Row Support
-(NSIndexPath *)modelIndexPath: (NSIndexPath *)indexPath
{
if (self.actionRowIndexPath == nil) {
return indexPath;
}
if ([indexPath row] > [self.actionRowIndexPath row]) {
return [NSIndexPath indexPathForRow:([indexPath row] - 1) inSection:indexPath.section];
}
return indexPath;
}
- (void)handleDoubleTap:(UITapGestureRecognizer *)recognizer {
NSLog(#"Double tap");
CGPoint p = [recognizer locationInView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:p];
NSIndexPath *pathToDelete = self.actionRowIndexPath;
_selectedIndexPath = [self modelIndexPath:_selectedIndexPath];
//Is the user deselecting current row?
if (_actionRowIndexPath) {
[self.tableView deselectRowAtIndexPath:_selectedIndexPath animated:NO];
self.selectedIndexPath = nil;
self.actionRowIndexPath = nil;
} else {
//Selecting a new row
self.selectedIndexPath = indexPath;
self.actionRowIndexPath= [NSIndexPath indexPathForRow:([indexPath row] + 1) inSection:[indexPath section]];
}
[self.tableView beginUpdates];
if (pathToDelete) {
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:pathToDelete] withRowAnimation:UITableViewRowAnimationAutomatic];
}
if (self.actionRowIndexPath) {
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:self.actionRowIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
[self.tableView endUpdates];
}
After you get the IndexPath you need to get the IndexPath.row and IndexPath.section and accordingly you need to add the object into your array at the desired index. For example: if you double tap the 2nd row in the 1st section then you need to add the object at index 4 of the array corresponding to the 1st section and then reload table. The cell would be added to the 3rd index of the 1st section.

Automatically load more articles in TableView

I have TableView and in this TableView I'm printing articles. Now user must click in navigation bar item to update(download more articles from web over json). I want and I think that is better that when user scroll to bottom that automaticaly shows loading cell and start to loading or getting more articles from web.
My questions are next:
How to put that extra cell in which would appear loading indicator
and loading text How to automatically get more articles?
This functionality is in iphone app "App Store" but with click load more items.
Maybe is better to put button load more articles?
All examples and suggestions are welcome.
Thank's for help
This one is easy it's add an UITablecell at the end to load more items.
//
// TableViewController.m
// PartialTable
//
// Created by Abizer Nasir on 07/07/2011.
//
#import "TableViewController.h"
#define kNumberOfItemsToAdd 8
#implementation TableViewController
#synthesize items;
// Mark: -
// Mark: Set up and tear down
- (id)init {
// New designated initialiser
if (!(self = [super initWithStyle:UITableViewStyleGrouped])) {
return nil; // Bail!
}
numberOfItemsToDisplay = kNumberOfItemsToAdd; // Show 10 items at startup
return self;
}
- (id)initWithStyle:(UITableViewStyle)style {
// Call out to the new designated initialiser
return [self init];
}
- (void)dealloc {
[items release];
[super dealloc];
}
#pragma mark - View lifecycle
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
if (numberOfItemsToDisplay == [items count]) {
return 1;
}
return 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (section == 0) {
return numberOfItemsToDisplay;
} else {
return 1;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"ItemCell";
// If the indexPath is less than the numberOfItemsToDisplay, configure and return a normal cell,
// otherwise, replace it with a button cell.
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
if (indexPath.section == 0) {
cell.textLabel.text = [items objectAtIndex:indexPath.row];
cell.textLabel.textAlignment = UITextAlignmentLeft;
cell.textLabel.textColor = [UIColor blackColor];
cell.textLabel.font = [UIFont boldSystemFontOfSize:17.f];
} else {
cell.textLabel.text = [NSString stringWithFormat:NSLocalizedString(#"Next %d items", #"The text to display to load more content"), kNumberOfItemsToAdd];
cell.textLabel.textAlignment = UITextAlignmentCenter;
cell.textLabel.textColor = [UIColor colorWithRed:0.196f green:0.3098f blue:0.52f alpha:1.f];
cell.textLabel.font = [UIFont boldSystemFontOfSize:14.f];
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 1) {
NSUInteger i, totalNumberOfItems = [items count];
NSUInteger newNumberOfItemsToDisplay = MIN(totalNumberOfItems, numberOfItemsToDisplay + kNumberOfItemsToAdd);
NSMutableArray *indexPaths = [[NSMutableArray alloc] init];
for (i=numberOfItemsToDisplay; i<newNumberOfItemsToDisplay; i++) {
[indexPaths addObject:[NSIndexPath indexPathForRow:i inSection:0]];
}
numberOfItemsToDisplay = newNumberOfItemsToDisplay;
[tableView beginUpdates];
[tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationTop];
[indexPaths release];
if (numberOfItemsToDisplay == totalNumberOfItems) {
[tableView deleteSections:[NSIndexSet indexSetWithIndex:1] withRowAnimation:UITableViewRowAnimationTop];
}
[tableView endUpdates];
// Scroll the cell to the top of the table
if (newNumberOfItemsToDisplay < totalNumberOfItems) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 200000000), dispatch_get_main_queue(), ^(void){
[tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
});
[tableView deselectRowAtIndexPath:indexPath animated:YES];
} else {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 200000000), dispatch_get_main_queue(), ^(void){
[tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:totalNumberOfItems-1 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];
});
}
}
}
#end
Q1: add 1 more cell for load more status:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return cellsCount <= 0 ? 0 : cellsCount + 1;
}
and create load more cell:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == cellsCount) {
if (loadMoreCell == nil) {
self.loadMoreCell = [[LoadMoreTableCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:#"LoadMoreCellIdentifier"];
}
return loadMoreCell;
}
...
}
You can custom LoadMoreTableCell as you want.
Q2:
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
float offset = (scrollView.contentOffset.y - (scrollView.contentSize.height - scrollView.frame.size.height));
if (offset >= 0 && offset <= 5) {
[self loadMoreData];
}
}
I also do like this thing in my app,
Here you can use AsyncImage class which is useful to download image with url in background so your tableview scroll smooth..
here two link hope this help you for download image in background...
1.https://github.com/Koolistov/Image-Cache
2.https://github.com/rs/SDWebImage
2nd thing you want to download at bottom to another data and cell then here if you use 1 condition then its work which you like...
in cellForRowAtIndexPath tableview Delegate Method
if(indexPath.row==[yourArray count]-1){
.....do somthing which you like.....(Reload table with your json or another data)
}
here only simple logic other wise better idea is put button at your last row...
Hope this help you..
:)

UITableView didSelectRowAtIndexPath add additional checkmark at tap

When i select a player in 'didSelectRowAtIndexPath' and add a checkmark on the selected row it adds an additional checkmark.
If i tap row = 0 it adds a checkmark to row = 0 and row = 11. This means that two row's are marked by one tap. If i tap row = 1 it adds an extra checkmark to row = 10 so it adds checkmark 10 rows forward. It seems like it only add the checkmark as the player does not get into the actual player-list.
Any help would be very much appreciated.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSLog(#"indexPath: %i", indexPath.row);
// To many players selected
if (nrOfSelectedPlayers == 6) { //This is max players allowed
UIAlertView *alertPlayer = [[UIAlertView alloc] initWithTitle:#"VARNING"
message:#"Du kan maximalt spela \n med sex spelare!"
delegate:self
cancelButtonTitle:#"Tillbaka"
otherButtonTitles:nil];
[alertPlayer show];
[alertPlayer release];
nrOfSelectedPlayers--;
checkDeletePlayer = YES;
}
else {
// Handle the number of selected players to be able to delete player +6
if (checkDeletePlayer == YES) {
checkDeletePlayer = NO;
nrOfSelectedPlayers++;
}
if (cell.accessoryType == UITableViewCellAccessoryNone) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[selectedPlayersArray addObject:cell.textLabel.text];
nrOfSelectedPlayers++;
}
else {
cell.accessoryType = UITableViewCellAccessoryNone;
selectedPlayer = cell.textLabel.text;
for (int oo = 0; oo < nrOfSelectedPlayers; oo++) {
if ([selectedPlayersArray objectAtIndex:oo] == cell.textLabel.text) {
[selectedPlayersArray removeObjectAtIndex:oo];
nrOfSelectedPlayers--;
}
}
//nrOfSelectedPlayers--;
}
}
}
I am using storyboards with Dynamic Prototype Cells to display a list of states I used some of the ideas above before I found this solution
Step 1
#interface StateViewController : UITableViewController
{
NSMutableArray *checkedIndexPaths;
}
Step 2
(void)viewDidLoad
{
[super viewDidLoad];
self.states = [[GAIGStateStore sharedInstance]allStates];
//Setup default array to keep track of the checkmarks
checkedIndexPaths = [NSMutableArray arrayWithCapacity:self.states.count];
for (int i = 0; i < self.states.count; i++) {
[checkedIndexPaths addObject:[NSNumber numberWithBool:NO]];
}
}
Step 3
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//This toggles the checkmark
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (cell.accessoryType == UITableViewCellAccessoryNone)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
//This sets the array
[checkedIndexPaths replaceObjectAtIndex:indexPath.row withObject:[NSNumber numberWithBool:YES]];
} else
{
cell.accessoryType = UITableViewCellAccessoryNone;
//This sets the array
[checkedIndexPaths replaceObjectAtIndex:indexPath.row withObject:[NSNumber numberWithBool:NO]];
}
}
Step 4
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:stateCell forIndexPath:indexPath];
UILabel *stateLabel = (UILabel *)[cell viewWithTag:1000];
StateProvince *myState = [self.states objectAtIndex:indexPath.row];
stateLabel.text = myState.label;
//Now set the check marks
// Assume cell not checked;
[cell setAccessoryType:UITableViewCellAccessoryNone];
NSNumber *num = [checkedIndexPaths objectAtIndex:indexPath.row];
if (num == [NSNumber numberWithBool:YES]) {
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
}
return cell;
}
The problem you are facing is caused by cell reusing.
Basically, if your UITableView has, let say 50 cells to display, it creates only 10 and then reuse them as you scroll down / scroll up. So whatever changes you did to the cell at row 0, it will be re-displayed for the row 11 as TableView uses the same cell etc.
What you want to do is to keep track of which players have been selected independently from cell. You can achieve that easily by creating a collection, let say NSMutableArray or NSMutableDictionary, which will store BOOL values in NSNumber objects, eg.
NSMutableArray *players = [NSMutableArray arrayWithCapacity:50];
for (int i = 0; i < 50; i++) {
[players addObject:[NSNumber numberWithBool:NO]];
}
Then in didSelectRowAtIndexPath:(NSIndexPath *)indexPath you do instead of operating on cell, you will simply change the value of a corresponding NSNumber object.
Then in cellForRowAtIndexPath:(NSIndexPath *)indexPath you configure cell accessory by checking the corresponding entry in players collection.
Or if you are really, really stubborn you could replace (THIS IS NOT RECOMENDED) the following line from the cellForRowAtIndexPath:(NSIndexPath *)indexPath:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
with:
UITableViewCell *cell = nil;
For others coming here (like I did) to see why their table selects random cells, you have to add something like the following to your cellForRowAtIndexPath:
// Assume cell not checked;
[cell setAccessoryType:UITableViewCellAccessoryNone];
for (int i = 0; i < checkedIndexPaths.count; i++) {
NSUInteger num = [[checkedIndexPaths objectAtIndex:i] row];
if (num == indexPath.row) {
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
}
}
I keep a NSMutableArray called checkedIndexPaths so that I know which indexPaths are checked. Keeping such an array allows you to easily limit the number of cells a user can check. Here's an example of my didSelectRowAtIndexPath:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
// uncheck if already checked
if (cell.accessoryType == UITableViewCellAccessoryCheckmark) {
cell.accessoryType = UITableViewCellAccessoryNone;
[checkedIndexPaths removeObject:indexPath];
}
else {
// make sure no more than 3 are selected
if ([checkedIndexPaths count] < 3) {
// check row
cell.accessoryType = UITableViewCellAccessoryCheckmark;
// add it to our list of checked indexes
[checkedIndexPaths addObject:indexPath];
} else {
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:#"Note"
message:#"You can only select 3 rows."
delegate:nil
cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
}
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}