Reputation: 12184
I have a UIViewController
that implements TableViews delegate and datasource protocols.
Now I want to add "swipe to delete" gesture to cells.
How should I go about it.
I have given a blank implementation of commitEditingStyle
method and also set the Editing property to YES.
Still the swipe feature is not coming .
Now Do I need to separately add UISwipeGesture
to each cell ?
Or am I missing something ?
Upvotes: 75
Views: 87410
Reputation: 1186
After iOS 8.0, you can custom you action in
- (nullable NSArray<UITableViewRowAction *> *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath
Upvotes: 0
Reputation: 1046
If you are using an NSFetchedResultsControllerDelegate
to populate the table view, this worked for me:
tableView:canEditRowAtIndexPath
returns true alwaysIn your tableView:commitEditingStyle:forRowAtIndexPath
implementation, do not delete the row directly from the table view. Instead, delete it using your managed object context, e.g.:
if editingStyle == UITableViewCellEditingStyle.Delete {
let word = self.fetchedResultsController.objectAtIndexPath(indexPath) as! Word
self.managedObjectContext.deleteObject(word)
self.saveManagedObjectContext()
}
func saveManagedObjectContext() {
do {
try self.managedObjectContext.save()
} catch {
let saveError = error as NSError
print("\(saveError), \(saveError.userInfo)")
}
}
Upvotes: 1
Reputation: 15579
In my experience, seems like you must have editing
on UITableView
set to NO
for swiping to work.
self.tableView.editing = NO;
Upvotes: 0
Reputation: 1903
This was a problem for me too...I could only get swiping to delete to work once every 10 or so attempts. It turns out the gesture
on the TV was being blocked by another gesture in the parent view controller. The TV was nested in a MMDrawerController
(swipe able drawer layout).
Just configuring the gesture recognizer in the drawer controller to not respond to close gestures in the flanking drawers allowed swipe to delete to work in my TV.
You could also try doing something like this with the gesture delegate
:
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}
Upvotes: 0
Reputation: 670
Please try this code in swift,
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// let the controller to know that able to edit tableView's row
return true
}
override func tableView(tableView: UITableView, commitEditingStyle editingStyle UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
// if you want to apply with iOS 8 or earlier version you must add this function too. (just left in blank code)
}
override func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {
// add the action button you want to show when swiping on tableView's cell , in this case add the delete button.
let deleteAction = UITableViewRowAction(style: .Default, title: "Delete", handler: { (action , indexPath) -> Void in
// Your delete code here.....
.........
.........
})
// You can set its properties like normal button
deleteAction.backgroundColor = UIColor.redColor()
return [deleteAction]
}
Upvotes: 12
Reputation: 3567
This is the swift version
// Override to support conditional editing of the table view.
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return NO if you do not want the specified item to be editable.
return true
}
// Override to support editing the table view.
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
// Delete the row from the data source
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
} else if editingStyle == .Insert {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
Upvotes: 0
Reputation: 29
NSMutableArray *post= [NSMutableArray alloc]initWithObject:@"1",@"2",@"3",nil];
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView
editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger row = [indexPath row];
NSUInteger count = [posts count];
if (row < count) {
return UITableViewCellEditingStyleDelete;
} else {
return UITableViewCellEditingStyleNone;
}
}
- (void)tableView:(UITableView *)tableView
commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger row = [indexPath row];
NSUInteger count = [posts count];
if (row < count) {
[posts removeObjectAtIndex:row];
}
}
Upvotes: -1
Reputation: 3786
You can see all necessary methods by creating a UITableViewController class (temporary) in XCode 5 and then copy which method you would like to use. Those methods you need will be commented out with pre-filled in lines you desire.
Upvotes: -2
Reputation: 1378
Conclusion of Kyr Dunenkoff chat is
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
}
should not be defined if you need delete button to appear on swipe.
Upvotes: 3
Reputation: 1322
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not 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) {
// Delete the row from the data source
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
Upvotes: 25
Reputation: 10262
As Dan has commented above, you need to implement the following table view delegate methods:
tableView:canEditRowAtIndexPath:
tableView:commitEditingStyle:forRowAtIndexPath:
Note: I have tried this in iOS 6 and iOS 7.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return YES - we will be able to delete all rows
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
// Perform the real delete action here. Note: you may need to check editing style
// if you do not perform delete only.
NSLog(@"Deleted row.");
}
Upvotes: 61
Reputation: 8090
You don't have to set editing:YES
if you need to show Delete button on cell swipe. You have to implement tableView:canEditRowAtIndexPath:
and return YES from there for rows you need to edit/delete. This is not necessary when your tableView's dataSource is a subclass of UITableViewContoller - this method, if not overridden, returns YES by default. In all other cases you have to implement it.
EDIT: Together we have found the problem - tableView:editingStyleForRowAtIndexPath:
returned UITableViewCellEditingStyleNone
if table wasn't in editing mode.
Upvotes: 55
Reputation: 15788
Try adding the following to your class:
// Override to support conditional editing of the table view.
- (BOOL) tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return(YES);
}
Upvotes: 5