swipe to delete when already in edit mode - objective-c

I have an iphone app using a uitableview where I'd like the "reorder" controls to always be displayed, and have the user swipe to delete rows.
The approach I'm currently taking is to put the tableview in edit mode and allow selection in edit mode
self.tableView.editing = YES;
self.tableView.allowsSelectionDuringEditing = YES;
I then hide the red delete circles using
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewCellEditingStyleNone;
}
- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath
{
return NO;
}
I cant figure out how to get the swipe gesture to bring up the "delete" on the right side when the tableview is already in edit mode, can somebody point me in the right direction?
alternatively, if someone knows how to get the cell reordering controls to show when NOT in edit mode, that would also be a workable solution
cheers

When the user swipes on a given row, you need to store a reference somewhere so that you can change the value returned by editingStyleForRowAtIndexPath and shouldIndentWhileEditingRowAtIndexPath. Your best bet is likely to use indexPathForCell on the cell that is swiped and store that. Then in the two display methods above you need to check if the NSIndexPath is the same or not (I'm not sure if they will be the same pointer or if you'll need to compare the section/row values - testing required). If they match, display the delete button.
Note that you may need to call reloadData on your tableView to have the effect appear without scrolling away and back again.

I'm wondering if the way you're headed now would break the Human Interface guidelines, which would result in the app not getting approved.
I can't see why you can't capture the swipe gesture and then use that to 'unhide' the red delete (stop sign) icons for the delete confirmation?

Related

Animation issue when deleting the last row of UITableView

UPDATE: This is now fixed in iOS 8.0 and above. See my accepted answer for details.
I have an iOS 7 UITableView that I allow swipe-to-delete on rows. I'm handling deletions in:
tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
With:
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationTop];
All rows are deleted with the correct animation, except for the last one in the table. When the user swipes to show the delete button, then taps it, the cell slides completely off screen to the left but leaves a white cell behind with the delete button still on it for a few tenths of a second before disappearing abruptly. It appears that this is happening with all the cells, but all other cells have a row below them that slides up, covering it up.
This even happens when the row in question is the only row in the table, where I delete the entire section instead of just the row. The section header slides up into oblivion but the white cell with the delete button sticks around for a little bit.
I would like this last cell to have the same UITableViewRowAnimationTop animation that the others do. Any ideas of what's going on?
UPDATE: This bug has been corrected in iOS 8. That final cell deletion now slides off to the left, the delete button slides up and away, and the background is clear (no more white area that abruptly disappears after the animations complete). The iOS 7 fix below is still needed when running below iOS 8.
iOS 7 Fix:
I was able to correct this problem by adding another section to the end of the table with a sufficiently tall section header view. This header view is styled to look like the blank area at the bottom of the table, so you can't see that it's there. When the last row of the table is deleted, this blank section header slides up and over it, hiding the delete button that's stuck there. This is a bit of a hack, but it looks like it's a table view bug.
As an alternative to the keep-an-empty-row trick mentioned by Frank Li, I've gotten around this ugly glitch by simply special-casing the deletion of the last row: Instead of animating the cell away, simply call -reloadData on the table view.
You won't get any animation, but you also won't see the glitch so your table view won't look broken. A worthwhile tradeoff.
my solution was to simply disable the broken animation by hiding the cell that's being deleted.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell* cell = [tableView cellForRowAtIndexPath:indexPath];
cell.hidden = YES;
}
I think a way-around is to always maintain an empty row below the last row in the table view. That will do the trick.
You can also use the UITableView.tableFooterView property:
- (void)viewDidLoad
{
[super viewDidLoad];
...
CGRect frame = [self.tableView rectForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
UIView *view = [[UIView alloc] initWithFrame:frame];
view.backgroundColor = self.tableView.backgroundColor;
self.tableView.tableFooterView = view;
}
This code goes into the view controller holding the UITableView.
Code assumes ARC.
It's a different story if you use background image for the table.
The code can be surrounded by "if (iOS > 7)" clause.

Forward horizontal swipe events on UITableView to parent view

I have a UITableView that I want to have respond to taps and vertical swipes, but still have something like userInteractionEnabled = NO for horizontal swipes. By that I mean, it would not handle touches and pass the touch event back to its superview.
Things I've tried that didn't work:
returning NO in - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
Overriding touchesBegan/touchesMoved/touchesEnded and passing the event to the next responder
Adding gesture recognizers for horizontal swipes and setting cancelsTouchesInView to YES
I've been trying to fix this on and off for several weeks, so any help is greatly appreciated!
better you can subview empty view for tableview.view color should be
empty and add gesture to that view.if gesture direction is
vertical.scroll tableview
Did you try just adding a horizontal swipe gesture recognizer to your table view's parent view? Also turn off horizontal scrolling on your table view. (set alwaysBounceHorizontal=NO)
Disabling user's interaction for each table view cell should help.
I suggest doing it in cellForRowAtIndexPath method.
The answer to this question is not simple, because UITableView manages a lot of touches, and this touches are managed by different components.
So, to give you a correct and working answer, you have to explain:
what kind of swipes you want to disable (left-to-right, right-to-left)
where (on the empty table view, on the cell)
what happens now when you do this swipe (the cell goes in edit mode, a navigation controller goes to the previous page ecc....)
For example: the swipe-to-delete on a UITableViewCell can't be avoided by overriding touchesBegan:withEvent, because the touch is received by the internal content view (UITableViewCellContentView private class, so you can't subclass and override touchesBegan:withEvent).
But this is not necessary, because you can disable this behavior adding this method to UITableViewController:
-(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewCellEditingStyleNone;
}
When you disable the editing (for example) the cell and the table view are no more capable of managing the touch, so the touch is forwarded to the next responder in the chain.
This is only one example, you must explain all the cases that are giving you undesider behavior to let us help you more.
Last suggestions:
At this Page you will find a very good and interesting explanation on how the hit test end event handling process works.
I'll update the answer with more specific information when you'll add more details.
Regards
Fabio

When editing UITableView how to prevent that delete button from poping out?

Usually when user click delete button in edit mode of UITableView a delete button will pop up asking for confirmation.
I don't want that.
How do I get rid that confirmation ritual?
I want my delete button to work like the plus button. Just add. Just delete. No need to confirm. At least not when the stake is low like in one issue of my program where deleting will simply flag the table to be invisible when out of edit mode.
Delete confirmation popup is not built into UITableView or UITableViewCell (swipe to delete functionality). Such a thing has to be manually added, therefore getting rid of it is easy: don't add a popup :)
If you are maintaining someone else's code, search for this method:
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return isEditable ? YES : NO;
}
Method documentation says:
The method permits the delegate to exclude individual rows from being treated as editable. Editable rows display the insertion or deletion control in their cells. If this method is not implemented, all rows are assumed to be editable. Rows that are not editable ignore the editingStyle property of a UITableViewCell object and do no indentation for the deletion or insertion control. Rows that are editable, but that do not want to have an insertion or remove control shown, can return UITableViewCellEditingStyleNone from the tableView:editingStyleForRowAtIndexPath: delegate method.
Here's a link to Apple docs Inserting and Deleting Rows and Sections for more complicated cases.
What is your data source? If it's an array, why don't you remove the selected item from the array and then refresh the uitableview?

How to change section headers in iOS?

Bit of background of the app I'm currently writing. It's a tableview and when a cell is tapped it loads a local HTML page.
However, now I'd like to implement section headers, a section header for complete and incomplete. The default header would be incomplete and after an interaction on the table view by a user, the cell is moved to complete. An option would be required to reverse the change should the change be done by mistake.
My first thought was to put in a check box in each cell, checking the box would move the cell and unchecking would move it back but I see iOS offers no such function, instead using switches instead.
For my needs, switches wouldn't work very well. So I'd like to ask others thoughts on this and how to implement such a thing, if anything.
Any thoughts or help appreciated.
Thanks.
You can implement a check mark using this approach. Basically you need to add a button on the cell and change its background image to show selected and deselected state. You can also consider using the default accessory check mark feature in tableview cell.
For eg:-
cell.accessoryType = UITableViewCellAccessoryCheckmark;
and
cell.accessoryType = UITableViewCellAccessoryNone;
In order to implement the section header, you can use - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section method or viewForHeaderInSection: method.
You can move a cell from one section to another one using the below method,
- (void)moveRowAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath

UICollectionView delete button

I have a UICollectionView showing several items. I also have an edit button in the screen toolbar.
How can I have delete icons appear on each UICollectionViewCell when I press the toolbar edit button?
There is very little in the way of examples on google at the moment, so if anyone can point me in the right direction, that would be great.
Thanks
Editing items in UICollectionViews aren't done the same way as they're done in a UITableView. In table views, there's a editing mode that'll show the delete button. But with collection views you gotta take care of that yourself.
Initially, I solved it this way:
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
if (self.editing) {
// Open an action sheet with the possible editing actions
}
}
But after that I removed the edit button and added a UILongPressGestureRecognizer to the UICollectionView. When long pressing an item I show the UIActionSheet that shows the possible actions.
One of those options might be a possibility for you.
Your code defines what a cell in a collection view looks like. You can add a delete icon/button to the contentView of the cells that your data source provides.