Table row animation slides the row on top of the other row - ios

I am removing tableview rows using [tableView beginUpdates] and [tableView endUpdates]
The mechanism works just fine.
My only problem is that visually when the cell is disappearing from the view, it is sliding on top of the cell above it, instead of behind it.
How can I make the cell go under the cell above it, instead of visually above it?
Here is my code:
-(void)reloadTableRowsWithAnimation {
NSMutableArray<NSIndexPath *> *selectedIndexPaths = [[NSMutableArray<NSIndexPath *> alloc]init];
[self.appsDataSource.selectedRows enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL * _Nonnull stop) {
[selectedIndexPaths addObject:[NSIndexPath indexPathForRow:idx inSection:0]];
}];
[self.tableView beginUpdates];
[self.tableView deleteRowsAtIndexPaths:selectedIndexPaths
withRowAnimation: UITableViewRowAnimationTop];
[self reloadAppsBeforeReloadTableView];
[self.tableView endUpdates];
}

Related

Objective-C Remove all selected rows from UITableView

I know about this call that would remove selected row:
[tableView deselectRowAtIndexPath:indexPath animated:YES];
My question is, how do I remove all selected rows? as I have multiple selected.
Thanks,
If you are asking about rows deselecting you may do it like this:
NSArray *selectedIndexPaths = [tableView indexPathsForSelectedRows];
[tableView beginUpdates];
[selectedIndexPaths enumerateObjectsUsingBlock:^(NSIndexPath *selectedIndexPath, NSUInteger idx, BOOL * _Nonnull stop) {
[tableView deselectRowAtIndexPath:selectedIndexPath animated:NO];
}];
[tableView endUpdates];
You can use deleteRowsAtIndexPaths(_:withRowAnimation:) with selected indexPaths.
Also you have to delete your objects from your datasource.
Use this:
[self.tableView reloadData];

iOS - UITableView Delete All Rows Within A Section

I have a UITableView with expandable sections. When a user goes to another view, I need all the expanded sections to collapse, which I'll need to put in the viewWillDisappear method.
I've found solutions only on how to delete all rows from a table view at once, but is there a way to delete all the rows from a specific section?
EDIT:
I have figured out a solution, but I'm not sure if it's optimal or can lead to inefficiencies in the future. Whenever a cell is expanded, it gets added to an NSMutableIndexSet. So in my viewWillDisappear method, I iterate over the expanded sections like so:
-(void)viewWillDisappear:(BOOL)animated
{
if (expandedSections.count != 0) {
NSLog(#"COLLAPSING CALLED");
[self.tableView beginUpdates];
NSUInteger section = [expandedSections firstIndex];
do
{
NSInteger rows;
NSMutableArray *tmpArray = [NSMutableArray array];
rows = [self tableView:self.tableView numberOfRowsInSection:section];
[expandedSections removeIndex:section];
for (int i=1; i<rows; i++) {
NSIndexPath *tmpIndexPath = [NSIndexPath indexPathForRow:i inSection:section];
[tmpArray addObject:tmpIndexPath];
}
[self.tableView deleteRowsAtIndexPaths:tmpArray withRowAnimation:UITableViewRowAnimationTop];
NSIndexPath *expandableCellIndexPath = [NSIndexPath indexPathForRow:0 inSection:section];
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:expandableCellIndexPath];
cell.accessoryView = [DTCustomColoredAccessory accessoryWithColor:[self.colorHolder objectAtIndex:section] type:DTCustomColoredAccessoryTypeRight];
section = [expandedSections indexGreaterThanIndex:section];
} while (section != NSNotFound);
[self.tableView endUpdates];
}
}
Please let me know if this is a good solution or, if I'm suspecting correctly, if this will lead to slower transitions between views in the future when there are more rows in each expanded section. Any help or advice would be appreciated. Thanks.
If you want to animate changes, you will need to first update your data source (to return 0 for number of rows in the section) then remove section and add section at the same index path in one transaction between [tv beginUpdates] [tv endUpdates]
Otherwise just update the data source and reload the table on your way back to the VC (if you don't want any animations)
I did not read this in detail but surely the for loop should start at zero.
for (int i=0; i<rows; i++) {
NSIndexPath *tmpIndexPath = [NSIndexPath indexPathForRow:i inSection:section];
[tmpArray addObject:tmpIndexPath];
}
otherwise you will only delete all but the first cells in the section.

Attempt to create two animations for cell

I would like to create cell by expand and collapse. To do this i animate the cell by reloading. When i expand it works fine. But when i collapse it crashes and the reason is Attempt to create two animations for cell. I know Ive given same array paths and it wont reload two cell at the time. Is there a way to fix this.
I am new to coding, so i would be happy to get a simple solution.
Code:
The reason am using lastSelIPath is when first cell is expanded and touch the second cell the first cell would collapse and the second cell would expand.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSIndexPath* lastSelIPath = [ NSIndexPath indexPathForRow:selectedIndex_ inSection:0 ];
[ tableView deselectRowAtIndexPath:indexPath animated:YES ];
if (selectedIndex_ == indexPath.row)
{
selectedIndex_ = -1;
}
else
{
selectedIndex_ = indexPath.row;
}
NSIndexPath* ipath = [ NSIndexPath indexPathForRow:indexPath.row inSection:0 ];
NSArray* indexPathArr = [ NSArray arrayWithObjects:lastSelIPath, ipath, nil ];
[ tableView beginUpdates ];
[ tableView reloadRowsAtIndexPaths:indexPathArr withRowAnimation:UITableViewRowAnimationAutomatic ];
[ tableView endUpdates ];
}
So what i did now I set a condition and reload the one i wanted. Is it a correct method to follow please help.
Modified code:
if ( lastSelIPath.row == ipath.row )
{
[tableView reloadRowsAtIndexPaths:#[ipath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
else
{
[tableView reloadRowsAtIndexPaths:#[lastSelIPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView reloadRowsAtIndexPaths:#[ipath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
Crash is right, you are trying to attempt two animation. Your indexPathArr contains two objects. Do not create this array and try this:
[tableView reloadRowsAtIndexPaths:#[lastSelIPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView reloadRowsAtIndexPaths:#[ipath] withRowAnimation:UITableViewRowAnimationAutomatic];
Let me know, if it helps
[tableView reloadRowsAtIndexPaths:#[newIndexPath, oldIndexPath] withRowAnimation:UITableViewRowAnimationNone];
If newIndexPath is same as oldIndexPath, it will crash in iOS8, but this is fixed in iOS9 and later.
You can use third party library for expanding cell.
https://github.com/bennyguitar/CollapseClick
& implement there delegate method as
-(int)numberOfCellsForCollapseClick
{
}
-(NSString *)titleForCollapseClickAtIndex:(int)index {
}
-(UIView *)viewForCollapseClickContentViewAtIndex:(int)index {
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (selectedTag==1) {
selectedIndex=indexPath.row;
[self performSelector:#selector(Write Your Action) withObject:nil];
}
NSMutableArray *modifiedRows = [NSMutableArray array];
if ([indexPath isEqual:self.expandedIndexPath]) {
[modifiedRows addObject:self.expandedIndexPath];
self.expandedIndexPath = nil;
}
else {
if (self.expandedIndexPath)
[modifiedRows addObject:self.expandedIndexPath];
self.expandedIndexPath = indexPath;
[modifiedRows addObject:indexPath];
}
// This will animate updating the row sizes
[tableView reloadRowsAtIndexPaths:modifiedRows withRowAnimation:UITableViewRowAnimationAutomatic];
// Preserve the deselection animation (if desired)
[tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
Using Selected Tag write the condition of your cell expand action. may be it helps.

UITableView insertRowsAtIndexPaths remove cell separator

I need to add a new row under the selected row. I'm using this code in didSelectRowAtIndexPath:
[_dataSource insertObject:newDataObject atIndex:indexPath.row + 1];
NSMutableArray *indexPaths = [NSMutableArray array];
NSInteger currentCount = indexPath.row;
[indexPaths addObject:[NSIndexPath indexPathForRow:currentCount+1 inSection:0]];
[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates];
It adds the new row in the correct position, but it also deletes the upper cell separator of the selected row. What am I doing wrong?
Seems like UITableViewCell has no separator in selected state. UITableViewCellSelectionStyleNone just disables highlighting, but cell is selected anyway. adding
[tableView beginUpdates];
// insert/delete manipulations
[tableView deselectRowAtIndexPath:indexPath animated:NO];
[tableView endUpdates];
fixes the problem

The sectionView has been loaded on the cell

As the picture shows. I make a tableview which can splite by inserting one row (the gray one) when I click on the cell, click again to cancel the splite:
The code is as below:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
int clickCellRow = [indexPath row] + 1;
int clickCellSection = [indexPath section];
[self beginUpdates];
if (isEditFlag == NO) {
isEditFlag = YES;
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:clickCellRow inSection:clickCellSection]] withRowAnimation:UITableViewRowAnimationFade];
}
else {
isEditFlag = NO;
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:clickCellRow inSection:clickCellSection]] withRowAnimation:UITableViewRowAnimationFade];
}
[self endUpdates];
}
It works well on IOS6, but on IOS7 one bug happened. When one cell is clicked and the splited row is inserted, then the sectionView is forced to go outside of the screen:
After cancelling the splite, and scroll the hidden cell up. The table turn to be as below :
It seems that the sectionView has been loaded on the cell! How does this happened and how to fix it?

Resources