I search couple of article but I didn't find what I'm looking for. Basically, I want to show delete button on each row but I don't want use UITableView.editing property.
Because it looks like this;
There will be "Edit" button. When user click on it, delete button will looks like swipe-style.
Is there any chance to show delete buttons like this;
Maybe there is a some way to deal with it. Otherwise, I'm going to create custom view for this.
Thanks for your advice.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
// Return YES if you want the specified item to be editable.
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
//Do something...
}
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView
editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewCellEditingStyleDelete;
}
Add a boolean property: #property BOOL didPressEdit;
Add UIButton to UITableViewCell
When pressing edit, didPressEdit becomes TRUE and UITableView reloads, such that cell.deleteButton.hidden = !didPressEdit; which makes all Delete buttons available
When pressing delete, remove object from datasource array, reload tableview
Hope this helps
-(NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewRowAction *moreAction2 = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleNormal title:#"Edit" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath){
[self.heartCartTabel setEditing:NO];
[self editButtonClicked:indexPath.row];
}];
moreAction2.backgroundColor = [UIColor blueColor];
UITableViewRowAction *deleteAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDestructive title:#"Delete" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath){
[self tableView:self.heartCartTabel commitEditingStyle: UITableViewCellEditingStyleDelete forRowAtIndexPath:indexPath];
// [self.heartCartTabel deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}];
return #[deleteAction, moreAction2];
}
-(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath{
return YES;
}
- (IBAction)editButtonClicked:(int)indexNumber {
}
You can use a UITableView delegate method to ask for those actions. Implement this method as follows:
- (NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewRowAction *modifyAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:#"Delete" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) {
// Respond to the action.
}];
modifyAction.backgroundColor = [UIColor blueColor];
return #[modifyAction];
}
You can of course return multiple actions and customize the text and background color.
Implementing this method is also required to make the row editable:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
[self.objects removeObjectAtIndex:indexPath.row];
[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.
}
}
You need to call the method editActionsForRowAtIndexPath on your edit button click.
-(void)buttonTouched:(id)sender{
UIButton *btn = (UIButton *)sender;
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:btn.tag inSection:0];
[self tableView:self.tableView editActionsForRowAtIndexPath:indexPath];
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
// Return NO if you do not want the specified item to be editable.
return YES;
}
Related
I am having a table view with some datas. While on left swipe of cell i want 'Delete' and 'Edit'. I got 'Delete' by using the below code. Please help me to solve this..
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 0) {
return NO;
}
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
[self.circleGroupArray removeObjectAtIndex:indexPath.row];
[_myCircleTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
Use this method in your class, If you want more actions you can create more UITableViewRowActions and add them to array.
-(NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewRowAction *editAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleNormal title:#"Clona" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath){
//add edit action here
}];
editAction.backgroundColor = [UIColor blueColor];
UITableViewRowAction *deleteAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleNormal title:#"Delete" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath){
//add delete action here
}];
deleteAction.backgroundColor = [UIColor redColor];
return #[deleteAction,editAction];
}
I've researched this across but dont seem to have found a solution yet. I have a custom UITableViewCell (with various subviews, including a radio button, labels, etc.). I would like the + and - insert / delete editing controls to appear at the left-most part of the cell when the table view is set to editing.
If I used the standard UITableViewCell, this works perfectly. However, whilst using the custom cell, the controls just dont appear. Anyone has any ideas on how to fix the same please?
Below are some snapshots of my table view code....
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (self.isEditing) {
if ([tableView isEqual:self.tableView]) {
if (editingStyle == UITableViewCellEditingStyleInsert) {
// ...
}
else if (editingStyle == UITableViewCellEditingStyleDelete) {
// ...
}
}
}
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([tableView isEqual:self.tableView]) {
if (indexPath.row == 0) {
return UITableViewCellEditingStyleInsert;
}
else {
return UITableViewCellEditingStyleDelete;
}
}
else {
return UITableViewCellEditingStyleNone;
}
}
And the custom table view cell code...
- (void)awakeFromNib
{
[super awakeFromNib];
}
- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
[self setNeedsLayout];
}
- (void)layoutSubviews
{
[super layoutSubviews];
[self configureConstraints];
}
- (void)configureConstraints
{
// This is where the cell subviews are laid out.
}
You didn't implement the setEditing:animated: method correctly in your custom cell. You forgot to call super:
- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
[super setEditing:editing animated:animated];
[self setNeedsLayout];
}
It's a rare overridden method that you don't call super.
Unrelated - in your table view code, don't use isEqual: to compare the two table views, use ==.
if (tableView == self.tableView) {
You actually do want to see if they are the same pointers.
Source: Custom edit view in UITableViewCell while swipe left. Objective-C or Swift
-(NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewRowAction *editAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleNormal title:#"Clona" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath){
//insert your editAction here
}];
editAction.backgroundColor = [UIColor blueColor];
UITableViewRowAction *deleteAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleNormal title:#"Delete" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath){
//insert your deleteAction here
}];
deleteAction.backgroundColor = [UIColor redColor];
return #[deleteAction,editAction];
}
-(NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath {
Course *c = self.courses[indexPath.row];
UITableViewRowAction *button = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:#" - " handler:^(UITableViewRowAction *action, NSIndexPath *indexPath)
{
[c remove];
[tableView beginUpdates];
[tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationNone];
[tableView endUpdates];
}];
button.backgroundColor = [UIColor red];
return #[button];
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
// you need to implement this method too or nothing will work
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES; //tableview must be editable or nothing will work...
}
How do I reset the position of my cell after the action has been pressed? Currently I'm reloading the cell but this ends up giving the cell a jumpy animation.
I'd like my cells to have not only the Delete button while editing but also others. So what is an actual way to do this? I've tried making own UIView object for editingAccessoryView property but the problem is being that the view appears only on direct edit (i.e. clicking Edit button in Navigation Bar) and completely ignores swipes across a cell. Also tableView:editActionsForRowAtIndexPath: method was given a try but didn't work, at least I didn't manage to figure out how to get what I want with its function. Thank you in advance!
You Try This Code
-(NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewRowAction *button = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:#"Button 1" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath)
{
NSLog(#"Action to perform with Button 1");
}];
button.backgroundColor = [UIColor greenColor]; //arbitrary color
UITableViewRowAction *button2 = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:#"Button 2" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath)
{
NSLog(#"Action to perform with Button2!");
}];
button2.backgroundColor = [UIColor blueColor]; //arbitrary color
return #[button, button2]; //array with all the buttons you want. 1,2,3, etc...
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
// you need to implement this method too or nothing will work:
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES; //tableview must be editable or nothing will work...
}
You CanTry also this code
.H File
{
NSMutableArray *dataArray;
}
#property (weak, nonatomic) IBOutlet UITableView *atableView;
#property(nonatomic,strong) NSMutableArray *dataArray;
**`.M file`**
- (void)viewDidLoad
{
[super viewDidLoad];
self.dataArray = [[NSMutableArray alloc] initWithObjects:#"Saurabh Sharma",#"Deepesh Jain",#"Ashish Sharma",#"Chandan",#"kanhaiya",#"Suchitra Bohra",#"Neha",#"Ghanshyam",nil];
self.title = #"Move Rows";
UIBarButtonItem *editButton = [[UIBarButtonItem alloc] initWithTitle:#"Edit" style: UIBarButtonItemStyleBordered target:self action:#selector(editButton:)];
[self.navigationItem setRightBarButtonItem:editButton];
// Do any additional setup after loading the view from its nib.
}
-(void)editButton:(UIBarButtonItem *)button
{
{
if(self.editing)
{
[super setEditing:NO animated:NO];
[atableView setEditing:NO animated:NO];
[atableView reloadData];
[self.navigationItem.rightBarButtonItem setTitle:#"Edit"];
[self.navigationItem.rightBarButtonItem setStyle:UIBarButtonItemStylePlain];
}
else
{
[super setEditing:YES animated:YES];
[atableView setEditing:YES animated:YES];
[atableView reloadData];
[self.navigationItem.rightBarButtonItem setTitle:#"Done"];
[self.navigationItem.rightBarButtonItem setStyle:UIBarButtonItemStyleDone];
}
}
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [dataArray count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifair=#"cellIdentifair";
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:cellIdentifair];
if(cell==nil)
{
cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifair];
}
cell.textLabel.text = [self.dataArray objectAtIndex:indexPath.row];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
#pragma delete row in table view
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionView *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
return 10; // This is the minimum inter item spacing, can be more
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewCellEditingStyleDelete;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return TRUE;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView beginUpdates];
[dataArray removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationTop];
[tableView endUpdates];
NSLog(#"Methods called when row is deleted");
}
#pragma Move Table View Delegte
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
NSString *item = [self.dataArray objectAtIndex:fromIndexPath.row];
[self.dataArray removeObject:item];
[self.dataArray insertObject:item atIndex:toIndexPath.row];
}
Works in Swift as well.
func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [AnyObject]? {
var completionButton = UITableViewRowAction(style: .Normal,
title: "Complete",
handler: {(action, index) in
/* Completion Code */
println("Complete")})
completionButton.backgroundColor = .lightGrayColor()
return [completionButton]
}
Also for iOS 11 you should use
- (UISwipeActionsConfiguration *)tableView:(UITableView *)tableView leadingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath - for right swipe
and
- (UISwipeActionsConfiguration *)tableView:(UITableView *)tableView trailingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath - for left swipe
For ex.:
- (UISwipeActionsConfiguration *)tableView:(UITableView *)tableView trailingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath {
UIContextualAction* action = [UIContextualAction contextualActionWithStyle:UIContextualActionStyleNormal title:#"Title" handler:^(UIContextualAction * _Nonnull action, __kindof UIView * _Nonnull sourceView, void (^ _Nonnull completionHandler)(BOOL)) {
// Do something
completionHandler(YES);
}
UISwipeActionsConfiguration * actionsConfiguration = [UISwipeActionsConfiguration configurationWithActions:#[action]];
return actionsConfiguration;
}
I've been trying to stop the (-) delete indicator from showing up when I put a UITableView into editing mode.
Updates for clarity:
This is what the table looks like:
This is what I have setup in - (NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath
When I tap reorder, I go into edit mode. I don't want these to show:
I've worked around the the 3rd screenshot by limiting the buttons shown from editActionsForRowAtIndexPath to just delete, but I don't even want to get to this part. I want Edit mode to be reorder only
/Updates
I've tried setting UITableViewCell.shouldIndentWhileEditing = NO
On the Cell directly:
cell.indentationLevel = -3;
cell.shouldIndentWhileEditing = NO;
In interface builder
In the appropriate delegate method
- (BOOL)tableView:(UITableView *)tableview shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"shouldIndentWhileEditingRowAtIndexPath");
return NO;
}
I'm also showing over items in the actions list. I hadn't planned on having delete at all when in Editing mode, just reodering. I've adjusted a few things so I only show the delete when a user swipes, but I'd rather the (-) not show at all:
- (void) endEditing
{
self.editMode = NO;
self.editControlButton.title = #"Reorder";
[self setEditing:NO animated:YES];
//[self.tableView reloadData];
}
- (void) startEditing
{
self.editMode = YES;
self.editControlButton.title = #"Done";
[self.tableView setEditing:YES animated:YES];
}
#pragma - mark UITableViewDelegate
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewCellEditingStyleDelete;
}
- (BOOL)tableView:(UITableView *)tableview shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"shouldIndentWhileEditingRowAtIndexPath");
return NO;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
TCORead *item = [self.fetchedResultsControllerDataSource selectedItem];
manager.currentRead = item;
}
- (NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewRowAction *deleteAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDestructive title:#"Delete" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath){
[self.tableView setEditing:NO];
}];
//workaround, rdar://17969970
//normally don't want to be able to get into this menu when reordering
if (!self.editMode) {
UITableViewRowAction *shareAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleNormal title:#"Share" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath){
[self.tableView setEditing:NO];
}];
shareAction.backgroundColor = [UIColor grayColor];
UITableViewRowAction *doneAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDestructive title:#"Done" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath){
[self.tableView setEditing:NO];
}];
doneAction.backgroundColor = [UIColor greenColor];
[self startEditing];
return #[deleteAction, doneAction, shareAction];
}
return #[deleteAction];
}
- (void)tableView:(UITableView *)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath
{
[self endEditing];
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
//empty on purpose
}
I was forcing the delete indicator to appear. Vanyas has a sample project that showed me what I was doing wrong.
My editingStyleForRowAtIndexPath method needed to look like this:
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath: (NSIndexPath *)indexPath
{
//return UITableViewCellEditingStyleDelete;
return tableView.isEditing ? UITableViewCellEditingStyleNone: UITableViewCellEditingStyleDelete;
}
If you don't want to allow deleting, just reordering, then there is no need to do anything about indenting. Instead, just do:
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewCellEditingStyleNone;
}
And don't implement the tableView:commitEditingStyle:forRowAtIndexPath: method at all.
You also avoid returning deleteAction from tableView:editActionsForRowAtIndexPath:.
That will prevent row deletion. You can now support reordering as needed.