Row deletion animation issue with swipe to delete - ios

I am implementing swipe to delete feature on one of my table that uses custom table view cells. The issue I am facing is when I tap on "Delete" button, I see a weird transition while cell is being removed.
Below is my code in "commitEditingStyle" and also see the attached screenshot I captured while row is being removed.
PS: I have tried with all types of row removal animation styles but no luck.
- (void)tableView:(UITableView *)iTableView commitEditingStyle:(UITableViewCellEditingStyle)iEditingStyle forRowAtIndexPath:(NSIndexPath *)iIndexPath {
if (iEditingStyle == UITableViewCellEditingStyleDelete && iTableView == self.temporaryCartTable) {
if (self.temporaryCartTable.frame.size.height == kMyAppCartTableViewExpandedHeight) {
[self.temporaryCartTable beginUpdates];
[self.temporaryCartTable deleteRowsAtIndexPaths:[NSArray arrayWithObjects: iIndexPath, nil] withRowAnimation:UITableViewRowAnimationAutomatic];
MyAppCartInfo *aMyAppCartInfo = [self cart];
if (([[aMyAppCartInfo.tempProducts allKeys] count] > iIndexPath.row) && [aMyAppCartInfo.tempProducts containsObjectForKey:[[aMyAppCartInfo.tempProducts allKeys] objectAtIndex:iIndexPath.row]]) {
[aMyAppCartInfo.tempProducts removeObjectForKey:[[aMyAppCartInfo.tempProducts allKeys] objectAtIndex:iIndexPath.row]];
}
[self.temporaryCartTable endUpdates];
}
}
}
- (BOOL)tableView:(UITableView *)iTableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
return (iTableView == self.temporaryCartTable) ? YES : NO;
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)iTableView editingStyleForRowAtIndexPath:(NSIndexPath *)iIndexPath {
return UITableViewCellEditingStyleDelete;
}
- (CGFloat)tableView:(UITableView *)iTableView heightForRowAtIndexPath:(NSIndexPath *)iIndexPath {
if (iTableView == self.temporaryCartTable) {
if (self.isTempCartCell)
return 92.0;
else
return 58.0;
} else {
return 58.0;
}
}

Add the following method implementation to your UITableViewDelegate
-(UITableViewCellEditingStyle)tableView:(UITableView *)tableView
editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewCellEditingStyleDelete;
}

Use [self.temporaryCartTable setRowHeight:xxx] instead of using the delegate rowHeightAtIndexPath. After the row is deleted and there is no other rows in the table, the delegate will not called and your table view's row height will be retrieved by its property (hence the default height). Plus, using this method from the delegate affects the performance.

If anyone else is having this, the problem in my case was heightForRowAtIndexPath: When cells have dynamic size delete animation behaves strange. In my case the solution was to use a different approach and not spend time investigating. But you can test it and see results. Assign a fixed height for cells:
self.tableView.rowHeight = Constant;
comment out heightForRowAtIndexPath:. And animations should be ok now.
I know this is not the solution but may still help someone.

Related

Custom moving tableview cell: How to always keep first cell at top of UITableView when "moveRowAtIndexPath"

I need to keep my first cell always located at top of tableview when i move others cell.I spent a lot of time and many ways button i haven't figure out that how to solve this problem.
This is my code:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//...do something to custom first cell design from xib file
//...do some thing to custom normal cells(cells at below of first cell)
[firstcell setEditing:NO animated:YES];
firstcell.userInteractionEnabled=NO;
if (indexPath.row==0)
{
return firstcell;
}
else
{
return cell;
}
}
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 0) // Don't move the first row
return NO;
return YES;
}
-(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath {
// i just change datasource for tableview at here
}
And there is my tableview when I move cell (normal cell).
I wanna keep first cell (blue cell) always be at top and not be interact by others cell.
You need to implement one more delegate method:
- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath {
if (proposedDestinationIndexPath.row == 0) {
// Don't allow a row to be moved to the first row position
return [NSIndexPath indexPathForRow:1 inSection:0];
} else {
return proposedDestinationIndexPath;
}
}
This code assume you only have one section in your table view.
The point of this method is to tell the table view that if the proposed destination for the row being moved isn't appropriate, the returned value should be used. As written here, any attempt to move a row to the top will result in it being moved just below the top row.

iOS UITableView Swipe Left Buttons don't appear

I'm trying to implement the swipe left to display the delete button.
The cell moves left, but there are no visible buttons. Why does this happen? What is the solution?
To be clear, I have searched on StackOverflow and tried at least a dozen posted "solutions", but none of them have worked for me.
Thanks in advance.
I tried using the following code, which does seem to make the table cell move, but the log does not show NSLog(#"commitEditingStyle");. Why does this happen?
// Swipe to delete.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"commitEditingStyle");
if (editingStyle == UITableViewCellEditingStyleDelete) {
NSLog(#"UITableViewCellEditingStyleDelete");
[listData removeObjectAtIndex:indexPath.row];
[self.tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
[self.tableView reloadData];
}
}
And I have tried adding:
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
Here is a screenshot:
The problem was that the table size was larger than my screen size. The solution is to set the constraints to match the width of the view.
// During startup (-viewDidLoad or in storyboard) do:
self.tableView.allowsMultipleSelectionDuringEditing = NO;
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
// Return YES if you want the specified item to be editable.
return YES;
}
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
//add code here for when you hit delete
}
}

How to limit the multi selection in UITableViewController

Here are tableView data source and delegate implementation, and I set the maximum selection is 5.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
...
if ([multiOptions count] > 5) {
[self tableView:tableView didDeselectRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryNone;
cell.selected = NO;
//show alert
}
...
}
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
...
[multiOptions removeObject:selectedOption];
...
}
but here comes a question, if the options exceed the limit, the first click on cell will work just fine. but second time click the cell will call
didDeselectRowAtIndexPath
again, that's not what i expected, and I tried
[tableView deselectRowAtIndexPath:indexPath animated:YES];
in didSelectRowAtIndexPath, it didn't work, can someone give me a hint, how to correct it? thanks.
You have to check this in tableView:willSelectRowAtIndexPath:
Have a look at the UITableView class reference
especially at the last sentence:
Return Value An index-path object that confirms or alters the selected
row. Return an NSIndexPath object other than indexPath if you want
another cell to be selected. Return nil if you don't want the row
selected.
So something like this will work within tableView:willSelectRowAtIndexPath::
if ([multiOptions count] > 5) return nil;

UITableView - Section header. How to change text?

I have a project which uses Storyboards. I have a UITableView with Static cells and Group style.
I need to change the section text in one section depending on which selection is made in a segmented control (in another section)
I have found some solutions which indicate that you should use override this method:
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
and trigger an update by calling:
[[self tableView]reloadSections:[NSIndexSet indexSetWithIndex:SectionToChange] withRowAnimation:UITableViewRowAnimationFade];
The problem is when I call reloadSections then all the rows and cells in the section in question get deleted. The text updates correctly thought but with this unwanted side effect.
I think I found the answer here: Changing UITableView section header without tableView:titleForHeaderInSection
It may not be very elegant but it seams to work.
I can trigger an update to only the section header with none of the unwanted side effects by calling:
[self.tableView headerViewForSection:1].textLabel.text = [self tableView:self.tableView titleForHeaderInSection:1];
So the only thing needed is to implement:
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
if (section == 1){
if (self.segmentX.selectedSegmentIndex == 0) // or some condition
return #"Header one";
else
return #"Header two";
}
return nil;
}
If you have implemented these functions then removing them should fix your problem:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
-(UIView*)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{ if (section == 0)
{
lbl.text = #"abc";
}
if (section == 2)
{
lbl.text = #"2ndsectionbeigns";
}
return headerview;
}

How to rearrange UITableView with custom cells?

I have a table view with custom cells. The cells are filled with my data.
Now I want to enable the user to rearrange the rows. I have implemented the methods, but while dragging to reorder the cell, I can see it shows like it is trying to do but cannot move anywhere. It moves like 10 pixel as if it will do the rearrange but goes back to its position. How to reorder the rows with custom cell?
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
[self.dataSource removeObjectAtIndex:indexPath.row];
[tableView reloadData];
}
}
-(UITableViewCellEditingStyle)tableView:(UITableView*)tableView editingStyleForRowAtIndexPath:(NSIndexPath*)indexPath
{
if (self.mytableView.editing)
{
return UITableViewCellEditingStyleDelete;
}
return UITableViewCellEditingStyleNone;
}
-(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
-(BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
-(void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{
id stringToMove = [self.dataSource objectAtIndex:sourceIndexPath.row];
[self.dataSource removeObjectAtIndex:sourceIndexPath.row];
[self.dataSource insertObject:stringToMove atIndex:destinationIndexPath.row];
}
-(NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath
{
if (proposedDestinationIndexPath.section != sourceIndexPath.section)
{
return sourceIndexPath;
}
return proposedDestinationIndexPath;
}
I know this is old but I will still answer it. The issue here is with your tableView: targetIndexPathForMoveFromRowAtIndexPath: toProposedIndexPath: method (your last method)
Your logic is preventing any moving from happening. Your if-statement:
if (proposedDestinationIndexPath.section != sourceIndexPath.section)
is saying if the desired location (the location the user wants to bring the cell) is not my current location, then return my current location (so do not move the cell). Otherwise, if my desired location (the new location I want to go) is my current location then return the desired location (which is actually my current location).
I hope that makes sense, so basically you are saying that no matter what, make sure every cell always remains in its current location. To fix this, either remove this method (this is not needed unless there are moves that are illegal) or switch your two return statements, so:
-(NSIndexPath *)tableView:(UITableView *)tableView
targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath
toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath {
if (proposedDestinationIndexPath.section != sourceIndexPath.section) {
return proposedDestinationIndexPath;
}
return sourceIndexPath;
}
In fact, the only method required to allow re-arranging is: tableView: moveRowAtIndexPath: toIndexPath:. So again, unless you want specific behavior out of the other methods you can save some code and just remove most of them (especially since in this situation you are mainly just implementing the defaults).

Resources