UITableView animation issue on insert and delete of cells - ios

I have gone through of various solutions on this but they didn't seem to work. I get consistency exception after insert and delete operations.
For the time being I have used reloadSection method as temporary solution which gives awful animation experience.
How to use insertRowsWithAnimation and deleteRowsWithAnimation which will result in correct animation in the following code :
- (void) imageTapped:(id)sender {
#try {
UIButton *button = sender;
NSInteger tag = button.tag;
GroupNode *group = [[dictGroups objectForKey:#"0"] objectAtIndex:tag];
NSMutableArray *arr = [[CommonModel shared]GetAllGroupNodesByTreeId:group.TreeId];
BOOL isVisited = NO;
GroupNode *nextNode;
for(GroupNode *gp in arr)
{
if(!isVisited)
{
if([gp.Id isEqual:group.Id])
{
isVisited = YES;
}
}
else
{
nextNode = gp;
break;
}
}
if(![group.Indent isEqual:#"0"] && [nextNode.Indent intValue] == [group.Indent intValue] + 1)
{
if ([arrExpandedGroups containsObject:group.Id]) {
[arrExpandedGroups removeObject:group.Id];
NSMutableArray *insertIndexPaths = [[NSMutableArray alloc] init];
NSMutableArray *deleteIndexPaths = [[NSMutableArray alloc] init];
NSMutableArray *arr1 = [dictGroups objectForKey:#"0"];
NSMutableArray *arrDelete = [[NSMutableArray alloc]init];
BOOL isChild = YES;
for(int i = 0; i< arr1.count;i++)
{
GroupNode *gp = [arr1 objectAtIndex:i];
if(![group.Id isEqual:gp.Id])
{
if([arr1 indexOfObject:gp] < [arr1 indexOfObject:group])
{
[arrDelete addObject:gp];
}
else
{
if(([gp.Indent intValue] > [group.Indent intValue]) && !isChild)
{
[arrDelete addObject:gp];
}
else if(([gp.Indent intValue] <= [group.Indent intValue]))
{
[arrDelete addObject:gp];
isChild = NO;
}
else
{
[deleteIndexPaths addObject:[NSIndexPath indexPathForRow:i inSection:0]];
}
}
}
else
{
[arrDelete addObject:gp];
[dictExpand removeObjectForKey:[NSString stringWithFormat:#"%i", (int)button.tag]];
button.tag = [arrDelete indexOfObject:gp];
[dictExpand setObject:#"no" forKey:[NSString stringWithFormat:#"%i", (int)button.tag]];
for(NSString *key in dictExpand.allKeys)
{
if(![key isEqual:[NSString stringWithFormat:#"%i", (int)button.tag]])
{
if([group.Indent intValue] == 1)
[dictExpand setObject:#"no" forKey:key];
}
}
}
}
[tableGroup beginUpdates];
[dictGroups setObject:arrDelete forKey:#"0"];
NSRange range = NSMakeRange(0, 1);
NSIndexSet *sectionToReload = [NSIndexSet indexSetWithIndexesInRange:range];
[tableGroup reloadSections:sectionToReload withRowAnimation:UITableViewRowAnimationNone];
[tableGroup endUpdates];
} else {
if([group.Indent intValue] == 1)
[arrExpandedGroups removeAllObjects];
[arrExpandedGroups addObject:group.Id];
NSMutableArray *arrAdd = [NSMutableArray new];
NSMutableArray *insertIndexPaths = [[NSMutableArray alloc] init];
NSMutableArray *deleteIndexPaths = [[NSMutableArray alloc] init];
NSMutableArray *arr1 = [dictGroups objectForKey:#"0"];
BOOL isVisited = NO;
BOOL isMainVisited = NO;
int icount = 0;
for(GroupNode *gp in arr)
{
BOOL isPresentInArr1 = NO;
for(GroupNode *g in arr1)
{
if([g.Id isEqual:gp.Id] && ![group.Indent isEqual:#"1"])
{
isPresentInArr1 = YES;
break;
}
}
if(!isVisited && (([gp.Indent intValue] == 0 || [gp.Indent intValue] == 1) || isPresentInArr1))
{
[arrAdd addObject:gp];
[insertIndexPaths addObject:[NSIndexPath indexPathForRow:icount inSection:0]];
if([gp.Id isEqual:group.Id])
{
isVisited = YES;
[dictExpand removeObjectForKey:[NSString stringWithFormat:#"%i", (int)button.tag]];
button.tag = [arrAdd indexOfObject:gp];
[dictExpand setObject:#"yes" forKey:[NSString stringWithFormat:#"%i", (int)button.tag]];
for(NSString *key in dictExpand.allKeys)
{
if(![key isEqual:[NSString stringWithFormat:#"%i", (int)button.tag]])
{
if([group.Indent intValue] == 1)
[dictExpand setObject:#"no" forKey:key];
}
}
}
}
else if(isVisited)
{
if([gp.Indent intValue] > [group.Indent intValue] && ([gp.Indent intValue] == [group.Indent intValue] + 1) && !isMainVisited)
{
[arrAdd addObject:gp];
[insertIndexPaths addObject:[NSIndexPath indexPathForRow:icount inSection:0]];
}
else if([group.Indent intValue] > 1 && [gp.Indent intValue] == [group.Indent intValue] && !isMainVisited)
{
[arrAdd addObject:gp];
[insertIndexPaths addObject:[NSIndexPath indexPathForRow:icount inSection:0]];
}
else if([gp.Indent intValue] <= 1 && !isMainVisited)
{
[arrAdd addObject:gp];
[insertIndexPaths addObject:[NSIndexPath indexPathForRow:icount inSection:0]];
isMainVisited = YES;
}
else if([gp.Indent intValue] <= 1 && isMainVisited)
{
[arrAdd addObject:gp];
[insertIndexPaths addObject:[NSIndexPath indexPathForRow:icount inSection:0]];
}
else
{
for(GroupNode *gn in arr1)
{
if([gn.Id isEqual:gp.Id])
[deleteIndexPaths addObject:[NSIndexPath indexPathForRow:icount inSection:0]];
}
}
}
icount ++;
}
[dictGroups setObject:arrAdd forKey:#"0"];
[tableGroup beginUpdates];
NSRange range = NSMakeRange(0, 1);
NSIndexSet *sectionToReload = [NSIndexSet indexSetWithIndexesInRange:range];
[tableGroup reloadSections:sectionToReload withRowAnimation:UITableViewRowAnimationNone];
[tableGroup endUpdates];
}
}
}
#catch (NSException *exception) {
}
}
I am aware this is a complex logic but this is how it will work.
arr - All database records array
arr1 - All displayed records
numberOfRowsInSection :
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
int count = (int)[[dictGroups objectForKey:#"0"] count];
return count;
}
This number is always same as the number of records in array in imageTapped function.

Insert row in table view as well when you are adding it in array. you are at once reloading the whole section... may be that might be a problem!(m not sure!!!)
Add this when you are updating index path while adding row:
[tableView insertRowsAtIndexPaths:[NSMutableArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
and this when deleting the index:
[tableView deleteRowsAtIndexPaths:[NSMutableArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
may be this can help and if not then try changing following line from your code:
[tableGroup reloadSections:sectionToReload withRowAnimation:UITableViewRowAnimationNone];
to:
[tableGroup reloadSections:sectionToReload withRowAnimation:UITableViewRowAnimationFade];

At first delete that object from tableview array, then use
[table deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationBottom];
[table reloadData];

Related

Unable to figure out the value change of the integer in the code

I have this code and I am trying to understand it. This has an int value 'currentExpandIndex' ,I couldnt figure out why it is changing because I dont find proper initiation of it. The int is first given the value -1,but later in code the int value changes according to the indexpath. I coldnt find the relation between the int and the indexpath declared in the code.Kindly tell me,why
the code is:
#interface AccordionTableViewController : UITableViewController {
NSArray *topItems;
NSMutableArray *subItems; // array of arrays
int currentExpandedIndex;
}
#end
//.m file
- (id)init {
self = [super init];
if (self) {
topItems = [[NSArray alloc] initWithArray:[self topLevelItems]];
subItems = [NSMutableArray new];
currentExpandedIndex = -1;
NSLog(#"currenyt index -init is %d",currentExpandedIndex);
for (int i = 0; i < [topItems count]; i++) {
[subItems addObject:[self subItems]];
}
}
return self;
}
#pragma mark - Data generators
- (NSArray *)topLevelItems {
NSMutableArray *items = [NSMutableArray array];
for (int i = 0; i < NUM_TOP_ITEMS; i++) {
[items addObject:[NSString stringWithFormat:#"Item %d", i + 1]];
}
return items;
}
- (NSArray *)subItems {
NSMutableArray *items = [NSMutableArray array];
int numItems = arc4random() % NUM_SUBITEMS + 2;
for (int i = 0; i < numItems; i++) {
[items addObject:[NSString stringWithFormat:#"SubItem %d", i + 1]];
}
return items;
}
#pragma mark - View management
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"currenyt index -view did load is %d",currentExpandedIndex);
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSLog(#"currenyt index -no of rows in section is %d",currentExpandedIndex);
return [topItems count] + ((currentExpandedIndex > -1) ? [[subItems objectAtIndex:currentExpandedIndex] count] : 0);
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *ParentCellIdentifier = #"ParentCell";
static NSString *ChildCellIdentifier = #"ChildCell";
NSLog(#"currenyt index-cell for row at index is %d",currentExpandedIndex);
BOOL isChild =
currentExpandedIndex > -1
&& indexPath.row > currentExpandedIndex
&& indexPath.row <= currentExpandedIndex + [[subItems objectAtIndex:currentExpandedIndex] count];
UITableViewCell *cell;
if (isChild) {
cell = [tableView dequeueReusableCellWithIdentifier:ChildCellIdentifier];
}
else {
cell = [tableView dequeueReusableCellWithIdentifier:ParentCellIdentifier];
}
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ParentCellIdentifier] autorelease];
}
if (isChild) {
cell.detailTextLabel.text = [[subItems objectAtIndex:currentExpandedIndex] objectAtIndex:indexPath.row - currentExpandedIndex - 1];
}
else {
int topIndex = (currentExpandedIndex > -1 && indexPath.row > currentExpandedIndex)
? indexPath.row - [[subItems objectAtIndex:currentExpandedIndex] count]
: indexPath.row;
cell.textLabel.text = [topItems objectAtIndex:topIndex];
cell.detailTextLabel.text = #"";
}
return cell;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
BOOL isChild =
currentExpandedIndex > -1
&& indexPath.row > currentExpandedIndex
&& indexPath.row <= currentExpandedIndex + [[subItems objectAtIndex:currentExpandedIndex] count];
if (isChild) {
NSLog(#"A child was tapped, do what you will with it");
NSLog(#"currenyt index -did select is %d",currentExpandedIndex);
return;
}
NSLog(#"currenyt index -did select out is %d",currentExpandedIndex);
[self.tableView beginUpdates];
if (currentExpandedIndex == indexPath.row) {
[self collapseSubItemsAtIndex:currentExpandedIndex];
currentExpandedIndex = -1;
}
else {
BOOL shouldCollapse = currentExpandedIndex > -1;
if (shouldCollapse) {
[self collapseSubItemsAtIndex:currentExpandedIndex];
}
currentExpandedIndex = (shouldCollapse && indexPath.row > currentExpandedIndex) ? indexPath.row - [[subItems objectAtIndex:currentExpandedIndex] count] : indexPath.row;
[self expandItemAtIndex:currentExpandedIndex];
}
[self.tableView endUpdates];
}
- (void)expandItemAtIndex:(int)index {
NSMutableArray *indexPaths = [NSMutableArray new];
NSArray *currentSubItems = [subItems objectAtIndex:index];
int insertPos = index + 1;
for (int i = 0; i < [currentSubItems count]; i++) {
[indexPaths addObject:[NSIndexPath indexPathForRow:insertPos++ inSection:0]];
}
[self.tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade];
//[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];
[indexPaths release];
}
- (void)collapseSubItemsAtIndex:(int)index {
NSMutableArray *indexPaths = [NSMutableArray new];
for (int i = index + 1; i <= index + [[subItems objectAtIndex:index] count]; i++) {
[indexPaths addObject:[NSIndexPath indexPathForRow:i inSection:0]];
}
[self.tableView deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade];
[indexPaths release];
}
In didSelectRowAtIndexPath: you have this line:
currentExpandedIndex =
(shouldCollapse && indexPath.row > currentExpandedIndex) ?
indexPath.row - [[subItems objectAtIndex:currentExpandedIndex] count] :
indexPath.row;
This line assign indexPath.row or indexPath.row - [[subItems objectAtIndex:currentExpandedIndex] count] to currentExpandedIndex.
currentExpandedIndex = (shouldCollapse && indexPath.row > currentExpandedIndex) ? indexPath.row - [[subItems objectAtIndex:currentExpandedIndex] count] : indexPath.row;
On each didSelectRow it will change.
First, set a breakpoint in -init. Depending on how you create this controller, it might not be called, in which case it will be 0. Try -initWithCoder: instead if this is the case. Otherwise, I only see this set in one place: -tableView:didSelectRowAtIndexPath:, where it can be set to the row or indexPath.row - [[subItems objectAtIndex:currentExpandedIndex] count]. Depending on what else you are doing with the table, this might be a good job for sections or expandable individual rows to simplify.

update UITableView sectionHeaderHeight at time of UIButton click in iOS

Good day! My default tableview sectionHeaderHeight is 56. I want to update it when sectionOpened method gets called.This is the following code:
- (void) sectionOpened : (NSInteger) section
{
sectionHeight = #"YES";
getsection = section;
NSLog(#"Section Clicked: %ld",(long)getsection);
SectionInfo *array = [self.sectionInfoArray objectAtIndex:section];
array.open = YES;
NSInteger count = [array.category.menulist count];
NSMutableArray *indexPathToInsert = [[NSMutableArray alloc] init];
for (NSInteger i = 0; i<count;i++)
{
[indexPathToInsert addObject:[NSIndexPath indexPathForRow:i inSection:section]];
}
NSMutableArray *indexPathsToDelete = [[NSMutableArray alloc] init];
NSInteger previousOpenIndex = self.openSectionIndex;
if (previousOpenIndex != NSNotFound)
{
SectionInfo *sectionArray = [self.sectionInfoArray objectAtIndex:previousOpenIndex];
sectionArray.open = NO;
NSInteger counts = [sectionArray.category.menulist count];
[sectionArray.sectionView toggleButtonPressed:FALSE];
for (NSInteger i = 0; i<counts; i++)
{
[indexPathsToDelete addObject:[NSIndexPath indexPathForRow:i inSection:previousOpenIndex]];
}
}
UITableViewRowAnimation insertAnimation;
UITableViewRowAnimation deleteAnimation;
if (previousOpenIndex == NSNotFound || section < previousOpenIndex)
{
insertAnimation = UITableViewRowAnimationTop;
deleteAnimation = UITableViewRowAnimationBottom;
}
else
{
insertAnimation = UITableViewRowAnimationBottom;
deleteAnimation = UITableViewRowAnimationTop;
}
[menulistTable beginUpdates];
if(section==3 || section==4 || section==5) // this section has cells like submenu of a menu
{
menulistTable.sectionHeaderHeight = 20.0;
[menulistTable reloadSections:[NSIndexSet indexSetWithIndex:section] withRowAnimation:UITableViewRowAnimationNone];
//[menulistTable reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationNone];
}
[menulistTable insertRowsAtIndexPaths:indexPathToInsert withRowAnimation:insertAnimation];
[menulistTable deleteRowsAtIndexPaths:indexPathsToDelete withRowAnimation:deleteAnimation];
[menulistTable endUpdates];
self.openSectionIndex = section;
}
But nothing happening. I also used indexSetWithIndex:0. Whats wrong in the code?
Try like this to change Height:
[menulistTable beginUpdates];
menulistTable.sectionHeaderHeight = 20.0;
[menulistTable endUpdates];
Edited:
Take variable to set SectionHeaderHeight. Then place this code:
[menulistTable beginUpdates];
secHeaderHeight = 20.0;
[menulistTable endUpdates];
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return secHeaderHeight;
}
Hope it will work for you.

Different behavior on UITableView control

There Is this control that I really appreciate: github link the problem is that now I have a situation where when I need to open one row and all the previous ones should close, I can only have one open row at the time.
Since I'm not very experienced with xcode, I need some info on where should I start and the necessary steps to make the code work the way I need right now.
I managed to make some tests but not a viable solution, here is what I have right now:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSInteger row = indexPath.row;
if (indexPath.section == 0) {
NSLog(#"indexPath1 = %i", selectedRow);
NSDictionary *d = [self.firstForTable objectAtIndex:indexPath.row];
if([d valueForKey:#"Objects"]) {
NSArray *ar = [d valueForKey:#"Objects"];
NSUInteger count = indexPath.row +1;
NSMutableArray *arCells = [NSMutableArray array];
for(NSDictionary *dInner in ar ) {
[arCells addObject:[NSIndexPath indexPathForRow:count inSection:0]];
[self.firstForTable insertObject:dInner atIndex:count++];
}
[tableView insertRowsAtIndexPaths:arCells withRowAnimation:UITableViewRowAnimationLeft];
}
else {
NSLog(#"Leave Element:::%# %#|",[d valueForKey:#"name"],[d valueForKey:#"book"]);
}
if (selectedRow == row) {
NSLog(#"selectedRow2 = %i",selectedRow);
NSDictionary *d=[self.firstForTable objectAtIndex:selectedRow];
if([d valueForKey:#"Objects"]) {
NSArray *ar = [d valueForKey:#"Objects"];
[self miniMizeFirstsRows:ar];
}
selectedRow = -1;
return;
}
if (selectedRow >= 0) {
NSLog(#"selectedRow3 = %i",selectedRow);
NSDictionary *d=[self.firstForTable objectAtIndex:selectedRow];
if([d valueForKey:#"Objects"]) {
NSArray *ar = [d valueForKey:#"Objects"];
[self miniMizeFirstsRows:ar];
}
selectedRow = row;
}
selectedRow = row;
[tableView beginUpdates]; [tableView endUpdates];
}
if (indexPath.section == 1) {
NSDictionary *d = [self.secondForTable objectAtIndex:indexPath.row];
if([d valueForKey:#"Objects"]) {
NSArray *ar = [d valueForKey:#"Objects"];
BOOL isAlreadyInserted=NO;
for (NSDictionary *dInner in ar) {
NSInteger index = [self.secondForTable indexOfObjectIdenticalTo:dInner];
isAlreadyInserted = (index > 0 && index != NSIntegerMax);
if (isAlreadyInserted) break;
}
if (isAlreadyInserted) {
[self miniMizeSecondsRows:ar];
}
else {
NSUInteger count = indexPath.row+1;
NSMutableArray *arCells = [NSMutableArray array];
for (NSDictionary *dInner in ar ) {
[arCells addObject:[NSIndexPath indexPathForRow:count inSection:1]];
[self.secondForTable insertObject:dInner atIndex:count++];
}
[tableView insertRowsAtIndexPaths:arCells withRowAnimation:UITableViewRowAnimationLeft];
}
}
else {
NSLog(#"Leave Element:::%# %#|",[d valueForKey:#"name"],[d valueForKey:#"book"]);
}
}
}
Thanks in Advance.
UPDATED: Expandable Rows JSON is your project, with auto-collapse working for all rows.
Also check Expandable Rows, i forked this project to help Novara and improve it. Now working for all sections, except nested rows.
FIRST STEP
Track opened row for each section. Of course this can be done using NSArray of tabOpened for multiple sections.
#interface RootViewController : UITableViewController {
NSInteger tabOpened_1;
NSInteger tabOpened_2;
}
SECOND STEP
Next initialize those with "-1" value, for none opened tab.
- (void)viewDidLoad
{
........
[self.firstForTable addObjectsFromArray:self.firstArray];
tabOpened_1 = -1;
[self.secondForTable addObjectsFromArray:self.secondArray];
tabOpened_2 = -1;
}
THIRD STEP
Change the didSelectRowAtIndexPath
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
if (indexPath.section==0) {
NSDictionary *d=[self.firstForTable objectAtIndex:indexPath.row];
if([d valueForKey:#"produtos"]) {
if (tabOpened_1 == -1) {
NSLog(#"No tab opened in first section");
tabOpened_1 = indexPath.row;
} else if(tabOpened_1 != indexPath.row && tabOpened_1 > indexPath.row){
NSDictionary *d_ = [self.firstForTable objectAtIndex:tabOpened_1];
NSArray *ar_ = [d_ valueForKey:#"produtos"];
[self miniMizeFirstsRows:ar_];
tabOpened_1 = indexPath.row;
}
NSArray *ar=[d valueForKey:#"produtos"];
BOOL isAlreadyInserted=NO;
for(NSDictionary *dInner in ar ){
NSInteger index=[self.firstForTable indexOfObjectIdenticalTo:dInner];
isAlreadyInserted=(index>0 && index!=NSIntegerMax);
if(isAlreadyInserted) break;
}
if(isAlreadyInserted) {
[self miniMizeFirstsRows:ar];
} else {
NSUInteger count=indexPath.row+1;
NSMutableArray *arCells=[NSMutableArray array];
for(NSDictionary *dInner in ar ) {
[arCells addObject:[NSIndexPath indexPathForRow:count inSection:0]];
[self.firstForTable insertObject:dInner atIndex:count++];
}
[tableView insertRowsAtIndexPaths:arCells withRowAnimation:UITableViewRowAnimationLeft];
}
if (tabOpened_1 == -1) {
NSLog(#"No tab opened in first section");
tabOpened_1 = indexPath.row;
} else if(tabOpened_1 != indexPath.row && tabOpened_1 < indexPath.row){
NSDictionary *d_ = [self.firstForTable objectAtIndex:tabOpened_1];
NSArray *ar_ = [d_ valueForKey:#"produtos"];
[self miniMizeFirstsRows:ar_];
tabOpened_1 = indexPath.row - [ar_ count];
tabOpened_1 = (tabOpened_1 < 0) ? indexPath.row : tabOpened_1;
}
} else {
NSLog(#"Leave Element:::%# %#|",[d valueForKey:#"nome"],[d valueForKey:#"numeroConta"]);
}
for (int i=0; i < [[self.rowsPerSection objectAtIndex:indexPath.section] integerValue]; i++) {
NSDictionary *d_ = [self.secondForTable objectAtIndex:i];
NSArray *ar_ = [d_ valueForKey:#"produtos"];
[self miniMizeSecondsRows:ar_];
}
}
if (indexPath.section==1) {
if (tabOpened_2 == -1) {
NSLog(#"No tab opened in second section");
tabOpened_2 = indexPath.row;
} else if(tabOpened_2 != indexPath.row && tabOpened_2 > indexPath.row){
NSDictionary *d_ = [self.secondForTable objectAtIndex:tabOpened_2];
NSArray *ar_ = [d_ valueForKey:#"produtos"];
[self miniMizeSecondsRows:ar_];
tabOpened_2 = indexPath.row;
}
NSDictionary *d=[self.secondForTable objectAtIndex:indexPath.row];
if([d valueForKey:#"produtos"]) {
NSArray *ar=[d valueForKey:#"produtos"];
BOOL isAlreadyInserted=NO;
for(NSDictionary *dInner in ar ){
NSInteger index=[self.secondForTable indexOfObjectIdenticalTo:dInner];
isAlreadyInserted=(index>0 && index!=NSIntegerMax);
if(isAlreadyInserted) break;
}
if(isAlreadyInserted) {
[self miniMizeSecondsRows:ar];
} else {
NSUInteger count=indexPath.row+1;
NSMutableArray *arCells=[NSMutableArray array];
for(NSDictionary *dInner in ar ) {
[arCells addObject:[NSIndexPath indexPathForRow:count inSection:1]];
[self.secondForTable insertObject:dInner atIndex:count++];
}
[tableView insertRowsAtIndexPaths:arCells withRowAnimation:UITableViewRowAnimationLeft];
}
if (tabOpened_2 == -1) {
NSLog(#"No tab opened in second section");
tabOpened_2 = indexPath.row;
} else if(tabOpened_2 != indexPath.row && tabOpened_2 < indexPath.row){
NSDictionary *d_ = [self.secondForTable objectAtIndex:tabOpened_2];
NSArray *ar_ = [d_ valueForKey:#"produtos"];
[self miniMizeSecondsRows:ar_];
tabOpened_2 = indexPath.row - [ar_ count];
tabOpened_2 = (tabOpened_2 < 0) ? indexPath.row : tabOpened_2;
}
} else {
//NSLog(#"Leave Element:::%# %#|",[d valueForKey:#"nome"],[d valueForKey:#"book"]);
}
for (int i=0; i < [[self.rowsPerSection objectAtIndex:indexPath.section] integerValue]; i++) {
NSDictionary *d_ = [self.firstForTable objectAtIndex:i];
NSArray *ar_ = [d_ valueForKey:#"produtos"];
[self miniMizeFirstsRows:ar_];
}
}
}
Is this really necessary for you to use mentioned by you control? If not I can propose you another control.
It is open source and available on github https://github.com/Augustyniak/RATreeView.
RATreeView was written by me and (from what you wrote) it has functionality you need. Its public API is based on UITableView's one so it is really simple to use. It has pretty expanded documentation which will allow you to get all needed information. Linked github's repository contains sample project which shows exactly how to start using it in your own project.
In case you start to use it and have some questions just ask.

Error 'Attempt to create two animations for cell' when reordering

I have a UITableView with sections that "collapse" when you tap the section header. When the section collapses, it really just removes the rows from the section. When I try to reorder a cell from another section below the collapsed section into the collapsed section, the app crashes. I get this error:
*** Assertion failure in -[_UITableViewUpdateSupport _setupAnimationForReorderingRow], /SourceCache/UIKit/UIKit-2380.17/UITableViewSupport.m:847
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Attempt to create two animations for cell'
What's strange is that it works fine if I'm moving the cell into a collapsed section from above the collapsed section. It only crashes if I move it from below the collapsed section.
Here's my code:
-(NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath
{
if ([proposedDestinationIndexPath section] == 0 && [[JRBTaskStore sharedStore] isTodayCollapsed])
[self hideShowToday];
else if ([proposedDestinationIndexPath section] == 1 && [[JRBTaskStore sharedStore] isTomorrowCollapsed])
[self hideShowTomorrow];
else if ([proposedDestinationIndexPath section] == 2 && [[JRBTaskStore sharedStore] isUpcomingCollapsed])
[self hideShowUpcoming];
else if ([proposedDestinationIndexPath section] == 3 && [[JRBTaskStore sharedStore] isSomedayCollapsed])
[self hideShowSomeday];
return proposedDestinationIndexPath;
}
-(void)hideShowToday
{
[self setDayType: TaskDayTypeToday];
[self hideShowSection: 0 rows: numberOfRowsInToday array: [[JRBTaskStore sharedStore] todayTasks]];
}
-(void)hideShowTomorrow
{
[self setDayType: TaskDayTypeTomorrow];
[self hideShowSection: 1 rows: numberOfRowsInTomorrow array: [[JRBTaskStore sharedStore] tomorrowTasks]];
}
-(void)hideShowUpcoming
{
[self setDayType: TaskDayTypeUpcoming];
[self hideShowSection: 2 rows: numberOfRowsInUpcoming array: [[JRBTaskStore sharedStore] upcomingTasks]];
}
-(void)hideShowSomeday
{
[self setDayType: TaskDayTypeSomeday];
[self hideShowSection: 3 rows: numberOfRowsInSomeday array: [[JRBTaskStore sharedStore] somedayTasks]];
}
-(void)hideShowSection:(int)section rows:(int)numRows array:(NSArray *)array
{
if ([array count] > 0 && [[self tableView] numberOfRowsInSection: section] == 0) {
// Uncollapse the section
// Create an array of index paths
NSMutableArray *indexPaths = [[NSMutableArray alloc] init];
int i = [array count];
for (int x = 0; x < i; x++) {
NSIndexPath *ip = [NSIndexPath indexPathForRow: x inSection: section];
[indexPaths addObject: ip];
}
if (dayType == TaskDayTypeToday) {
numberOfRowsInToday = [array count];
[[JRBTaskStore sharedStore] setIsTodayCollapsed: NO];
}
if (dayType == TaskDayTypeTomorrow) {
numberOfRowsInTomorrow = [array count];
[[JRBTaskStore sharedStore] setIsTomorrowCollapsed: NO];
}
if (dayType == TaskDayTypeUpcoming) {
numberOfRowsInUpcoming = [array count];
[[JRBTaskStore sharedStore] setIsUpcomingCollapsed: NO];
}
if (dayType == TaskDayTypeSomeday) {
numberOfRowsInSomeday = [array count];
[[JRBTaskStore sharedStore] setIsSomedayCollapsed: NO];
}
// Getting the error here
[[self tableView] insertRowsAtIndexPaths: indexPaths withRowAnimation: UITableViewRowAnimationAutomatic];
}
else if ([array count] > 0 && [[self tableView] numberOfRowsInSection: section] > 0) {
// Collapse the section
// Find the index paths of the rows and delete them
NSMutableArray *indexPaths = [[NSMutableArray alloc] init];
int i = [[self tableView] numberOfRowsInSection: section];
for (int x = 0; x < i; x++) {
NSIndexPath *ip = [NSIndexPath indexPathForRow: x inSection: section];
[indexPaths addObject: ip];
}
if (dayType == TaskDayTypeToday) {
numberOfRowsInToday = 0;
[[JRBTaskStore sharedStore] setIsTodayCollapsed: YES];
}
if (dayType == TaskDayTypeTomorrow) {
numberOfRowsInTomorrow = 0;
[[JRBTaskStore sharedStore] setIsTomorrowCollapsed: YES];
}
if (dayType == TaskDayTypeUpcoming) {
numberOfRowsInUpcoming = 0;
[[JRBTaskStore sharedStore] setIsUpcomingCollapsed: YES];
}
if (dayType == TaskDayTypeSomeday) {
numberOfRowsInSomeday = 0;
[[JRBTaskStore sharedStore] setIsSomedayCollapsed: YES];
}
[[self tableView] deleteRowsAtIndexPaths: indexPaths withRowAnimation: UITableViewRowAnimationTop];
}
else if ([array count] == 0) {
// There's nothing in the section
}
}

UITableView Expanding Section generated errors

I have a snippet of code of expanding the rows of cells of section. The error occurs at the xtable updates [UIViewAnimation initWithView:indexPath:endRect:endAlpha:startFraction:endFraction:curve:animateFromCurrentPosition:shouldDeleteAfterAnimation:editing:]
Snippet of code
-(void)sectionHeaderView:(SectionHeaderView*)sectionHeaderView sectionOpened:(NSInteger)sectionOpened {
SectionInfo *sectionInfo = [self.sectionInfoArray objectAtIndex:sectionOpened];
sectionInfo.open = YES;
NSInteger countOfRowsToInsert = 5;
NSMutableArray *indexPathsToInsert = [[NSMutableArray alloc] init];
for (NSInteger i = 0; i < countOfRowsToInsert; i++) {
[indexPathsToInsert addObject:[NSIndexPath indexPathForRow:i inSection:sectionOpened]];
}
NSMutableArray *indexPathsToDelete = [[NSMutableArray alloc] init];
NSInteger previousOpenSectionIndex = self.openSectionIndex;
if (previousOpenSectionIndex != NSNotFound) {
SectionInfo *previousOpenSection = [self.sectionInfoArray objectAtIndex:previousOpenSectionIndex];
previousOpenSection.open = NO;
[previousOpenSection.headerView toggleOpenWithUserAction:NO];
NSInteger countOfRowsToDelete = 5;
for (NSInteger i = 0; i < countOfRowsToDelete; i++) {
[indexPathsToDelete addObject:[NSIndexPath indexPathForRow:i inSection:previousOpenSectionIndex]];
}
}
// Style the animation so that there's a smooth flow in either direction.
UITableViewRowAnimation insertAnimation;
UITableViewRowAnimation deleteAnimation;
if (previousOpenSectionIndex == NSNotFound || sectionOpened < previousOpenSectionIndex) {
insertAnimation = UITableViewRowAnimationTop;
deleteAnimation =UITableViewRowAnimationBottom;
}
else {
insertAnimation = UITableViewRowAnimationBottom;
deleteAnimation = UITableViewRowAnimationTop;
}
// Apply the updates.
[xtable beginUpdates];
[xtable insertRowsAtIndexPaths:indexPathsToInsert withRowAnimation:insertAnimation];
[xtable deleteRowsAtIndexPaths:indexPathsToDelete withRowAnimation:deleteAnimation];
[xtable endUpdates];
self.openSectionIndex = sectionOpened;
}
what could possible be wrong? any ideas?
in my case helped
-(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
return 0;
}

Resources