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.
Related
I want to create a generic UITableView expand and collapse so that it can be bind with array of arrays/dictionary to multilevel.
Number of levels will be defined on run time. Please help, I am working in Objective-C.
Try this code. Worked for me as per my requirement.
------ To expand the rows ------
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSDictionary * d = [self.arForTable objectAtIndex:indexPath.row];
if([d valueForKey:#"Objects"]) {
NSArray * ar = [d valueForKey:#"Objects"];
BOOL isAlreadyInserted = NO;
for(NSDictionary * dInner in ar){
NSInteger index = [self.arForTable indexOfObjectIdenticalTo:dInner];
isAlreadyInserted = (index > 0 && index != NSIntegerMax);
if(isAlreadyInserted) break;
}
if(isAlreadyInserted) {
[self miniMizeThisRows:ar];
}
else {
NSUInteger count = indexPath.row+1;
NSMutableArray * arCells = [NSMutableArray array];
for(NSDictionary * dInner in ar) {
[arCells addObject:[NSIndexPath indexPathForRow:count inSection:0]];
[self.arForTable insertObject:dInner atIndex:count++];
}
[tableView insertRowsAtIndexPaths:arCells withRowAnimation:UITableViewRowAnimationFade];
[tableView beginUpdates];
[tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationNone];
[tableView endUpdates];
}
}
}
------ To minimize the rows ------
-(void)miniMizeThisRows:(NSArray *)ar{
for(NSDictionary * dInner in ar ) {
NSUInteger indexToRemove = [self.arForTable indexOfObjectIdenticalTo:dInner];
NSArray * arInner = [dInner valueForKey:#"Objects"];
if(arInner && [arInner count] > 0){
[self miniMizeThisRows:arInner];
}
if([self.arForTable indexOfObjectIdenticalTo:dInner] != NSNotFound) {
[self.arForTable removeObjectIdenticalTo:dInner];
[self.mainTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:indexToRemove inSection:0]] withRowAnimation:UITableViewRowAnimationFade];
[self.mainTableView beginUpdates];
[self.mainTableView reloadRowsAtIndexPaths:#[[NSIndexPath indexPathForRow:indexToRemove-1 inSection:0]] withRowAnimation:UITableViewRowAnimationFade];
[self.mainTableView endUpdates];
}
}
}
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];
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.
I am expanding and collapsing table view using plist value from one git hub tutorial. In that tutorial when i press row it is expanding, when i press the same row it is again collapsing no problem in that. But what i want is when i press a row expect that row other opened rows should be collapsed, so could any one give me some idea.
This is the code for expanding and collapsing
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSDictionary *d=[self.arForTable objectAtIndex:indexPath.row];
NSLog(#"%#",d);
if([d valueForKey:#"Objects"]) {
NSArray *ar=[d valueForKey:#"Objects"];
NSLog(#"%#",ar);
BOOL isAlreadyInserted=NO;
for(NSDictionary *dInner in ar ){
NSInteger index=[self.arForTable indexOfObjectIdenticalTo:dInner];
NSLog(#"%ld",(long)index);
isAlreadyInserted=(index>0 && index!=NSIntegerMax);
if(isAlreadyInserted) break;
}
if(isAlreadyInserted)
{
[self miniMizeThisRows:ar];
}
else
{
NSUInteger count=indexPath.row+1;
NSMutableArray *arCells=[NSMutableArray array];
for(NSDictionary *dInner in ar ) {
[arCells addObject:[NSIndexPath indexPathForRow:count inSection:0]];
[self.arForTable insertObject:dInner atIndex:count++];
}
[tableView insertRowsAtIndexPaths:arCells withRowAnimation:UITableViewRowAnimationLeft];
}
}
}
-(void)miniMizeThisRows:(NSArray*)ar{
for(NSDictionary *dInner in ar ) {
NSUInteger indexToRemove=[self.arForTable indexOfObjectIdenticalTo:dInner];
NSArray *arInner=[dInner valueForKey:#"Objects"];
if(arInner && [arInner count]>0){
[self miniMizeThisRows:arInner];
}
if([self.arForTable indexOfObjectIdenticalTo:dInner]!=NSNotFound)
{
[self.arForTable removeObjectIdenticalTo:dInner];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:
[NSIndexPath indexPathForRow:indexToRemove inSection:1]
]
withRowAnimation:UITableViewRowAnimationRight];
}
}
}
That means you want to expand exactly one cell at a time. So you should save the index path of last expanded row and you should call your method for that index path and at the same time you should insert cell for row which you are expecting to expand.
UPDATED
Make member variable in .h
NSIndexPath *lastIndexPath;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
if(lastIndexPath.row == indexPath.row)
{
NSDictionary *d=[self.arForTable objectAtIndex:indexPath.row];
if([d valueForKey:#"Objects"]) {
NSArray *ar=[d valueForKey:#"Objects"];
}
[self miniMizeThisRows:ar];
}
else
{
if(lastIndexPath.row)
{
NSDictionary *d=[self.arForTable objectAtIndex:lastIndexPath.row];
if([d valueForKey:#"Objects"]) {
NSArray *ar=[d valueForKey:#"Objects"];
[self miniMizeThisRows:ar];
}
}
NSUInteger count=indexPath.row+1;
NSMutableArray *arCells=[NSMutableArray array];
for(NSDictionary *dInner in ar ) {
[arCells addObject:[NSIndexPath indexPathForRow:count inSection:0]];
[self.arForTable insertObject:dInner atIndex:count++];
lastIndexPath = indexPath;
[tableView insertRowsAtIndexPaths:arCells withRowAnimation:UITableViewRowAnimationLeft];
}
}
}
Please excuse if any bracket is missed. Please notify me regarding that.
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
}
}