如何避免在 UITableViewCell 上滑动删除调用 setEditing
Posted
技术标签:
【中文标题】如何避免在 UITableViewCell 上滑动删除调用 setEditing【英文标题】:How to avoid swipe to delete calling setEditing at the UITableViewCell 【发布时间】:2011-06-22 09:47:03 【问题描述】:我知道,当我实现tableView:willBeginEditingRowAtIndexPath:
和tableView:didEndEditingRowAtIndexPath:
时,滑动删除不会在我的UITableViewController
(作为UITableView
的代表)调用setEditing:animated:
。
我有一个自定义的UITableViewCell
实现,它在进入编辑模式时会进行一些 UI 重新排列。我想变得聪明一点,并在表格视图单元实现本身的setEditing:animated:
中实现这些更改(这显然是有道理的)。
但是,当滑动删除时,我仍然在我的表格视图单元格实现中接到setEditing:animated:
的电话。而且我没有参数告诉我我正在刷卡。调用堆栈也没有显示我自己的任何方法,这些方法可以让我有机会做某事。它表明setEditing:animated
在UITableView
处被调用。唯一明显的是,它没有在委托(在这种情况下是我的控制器)处调用。
当然,我可以在tableView:willBeginEditingRowAtIndexPath:
的单元格中设置一个标志,告诉它下一个setEditing
调用将用于滑动,但这听起来不太好。
编辑:它甚至不起作用,因为不能保证tableView:didEndEditingRowAtIndexPath:
被调用,所以我无法设置标志。
任何想法如何优雅地解决这个问题?
【问题讨论】:
我不确定我是否理解正确。所以你还是想在你的 UITableViewCell 的 setEditing:animated: 中做点什么,对吧?如果没有,这个链接有帮助吗? ***.com/questions/969313/… 我想启用滑动删除。但我希望能够区分“真实”编辑模式和为滑动删除设置的“伪”编辑模式。在UITableViewDelegate
中我可以区分两者,因为在滑动删除时不会调用setEditing:animated:
。但是,我无法在 UITableViewCell
实现中有所作为。还是我不知何故?
【参考方案1】:
我认为 UITableViewCell 的willTransitionToState: 实例方法可能是您正在寻找的。像这样的:
- (void)willTransitionToState:(UITableViewCellStateMask)state
if (state == UITableViewCellStateShowingDeleteConfirmationMask)
swipedToDelete = YES; // BOOL ivar
- (void)setEditing:(BOOL)editing animated:(BOOL)animated
if (swipedToDelete)
// do your stuff, or don't
是吗?
【讨论】:
是的,这解决了在单元格上获得通知以进行滑动的问题。谢谢!可以在 else 分支中的willTransitionToState
中设置标志。但是仍然存在一个问题:如果我开始在表格视图中进行编辑,所有单元格都会收到 setEditing
调用。此外,当我结束编辑但不是在这种情况下:我滑动删除获取“删除”按钮,然后在我的表格视图中按“编辑”。然后细胞不会接到setEditing
的电话。这真的很奇怪。有什么想法吗?
请注意:调试时的问题是单元格的setEditing:animated:
是通过UITableViewController
的setEditing:animated:
实现触发的(在我的例子中是[super setEditing:editing]
)。所以,我只能猜测单元格被通知了,因为有一个单元格带有editing == YES
。
可能苹果在联系人应用程序中遇到了同样的问题。他们通过将“编辑”按钮更改为“完成”按钮来“解决”它,因此无法从删除确认状态进入编辑模式。
如果加上[super willTransitionToState:state];在您的代码中,您保留了常见的单元格行为。以防万一有人(像我一样)复制并粘贴此方法并想知道为什么单元格中的图标消失了.. ;)
正如拉斐尔所说,添加 [super willTransitionToState:state];【参考方案2】:
我知道这可能已经完成了,但提出的解决方案似乎不是一个完整的简单答案,它们似乎也没有提供好的示例代码,所以我想我会添加我的答案。
给你的类添加一个私有实例变量:
@implementation MyTableViewController
BOOL _cellSwiped;
重写 setEditing 方法以查找 _cellSwiped
变量,并且仅在我们不滑动时传播。人们似乎缺少的部分是 _cellSwiped
需要重置为 NO 否则您将永远无法在刷卡后使用编辑按钮!
- (void) setEditing:(BOOL)editing animated:(BOOL)animated
if (!_cellSwiped)
[super setEditing:editing animated:animated];
else if (!editing)
_cellSwiped = NO;
最后,添加这个方法覆盖来检测滑动:
- (void)tableView:(UITableView *)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath
_cellSwiped = YES;
【讨论】:
【参考方案3】:我做的是这样的:
- (void)tableView:(UITableView *)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath
cellSwiped = YES;
self.editing = NO;
然后在
- (void)setEditing:(BOOL)editing animated:(BOOL)animated
方法我只是检查是否设置了 cellSwiped ivar 并相应地修改 UI。
【讨论】:
这正是我在我的问题中提到的。但是,这并不可靠(请参阅问题)【参考方案4】:这是一个老问题,但我想知道为什么似乎没有人知道showingDeleteConfirmation
属性内置在UITableViewCell
中(自ios 2.0 起):
- (void)setEditing:(BOOL)editing animated:(BOOL)animated
[super setEditing:editing animated:animated];
BOOL reallyEditing = editing && !self.showingDeleteConfirmation;
// [...]
无需覆盖-willTransitionToState:
并手动跟踪状态。
【讨论】:
此时,showingDeleteConfirmation
实际上是 NO,并在 setEditing:animated:
调用后设置。【参考方案5】:
- (void)tableView:(UITableView *)tableview commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
if(editingStyle != UITableViewCellEditingStyleDelete)
// add code here
调用时,该方法会执行以下操作
UITableViewCellEditingStyleNone,
UITableViewCellEditingStyleDelete,
UITableViewCellEditingStyleInsert
如果你不想要滑动选项,你可以在委托方法中设置 bool 变量
- (void)willTransitionToState:(UITableViewCellStateMask)state
willTransitionToState
会在之前被调用
commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:
【讨论】:
以上是关于如何避免在 UITableViewCell 上滑动删除调用 setEditing的主要内容,如果未能解决你的问题,请参考以下文章
如何来回移动 UITableViewCell 以显示它可以滑动?
UITableViewCell 如何检测用户向左或向右滑动?