如何获得 UITableViewCell 移动开始和结束的通知?
Posted
技术标签:
【中文标题】如何获得 UITableViewCell 移动开始和结束的通知?【英文标题】:How to get notified of UITableViewCell move start and end? 【发布时间】:2012-04-11 12:09:47 【问题描述】:我的 ios 应用中有一个 UITableView,它会定期刷新。用户还可以随时移动 tableview 行(tableview 始终处于编辑模式)。
我想在用户开始拖动一行时停止刷新计时器,并在删除该行时再次启动它。
moveRowAtIndexPath
的最后一部分应该很容易,但是如何获得有关拖动开始的通知?
【问题讨论】:
【参考方案1】:我前段时间遇到了同样的问题,但没有找到解决方案。虽然我以解释为什么不能完成这个答案开始这个答案,但我实际上发现了它是如何完成的! :-)
简而言之:您必须创建UITableViewCell
的自定义子类。覆盖layoutSubviews
以将UILongPressGestureRecognizer
附加到UITableViewCellReorderControl
。定义协议并使用委托将拖动状态通知给任何人。
CustomTableViewCell.h:
#import <UIKit/UIKit.h>
@protocol CustomTableViewCellDelegate;
@interface CustomTableViewCell : UITableViewCell
@property (nonatomic, assign) id <CustomTableViewCellDelegate> delegate;
@end
@protocol CustomTableViewCellDelegate
- (void)CustomTableViewCell:(CustomTableViewCell *)cell isDragging:(BOOL)value;
@end
CustomTableViewCell.m:
#import "CustomTableViewCell.h"
@implementation CustomTableViewCell
@synthesize delegate = _delegate;
- (void)handleGesture:(UIGestureRecognizer *)gestureRecognizer
if (gestureRecognizer.state == UIGestureRecognizerStateBegan)
[_delegate CustomTableViewCell:self isDragging:YES]; // Dragging started
else if (gestureRecognizer.state == UIGestureRecognizerStateEnded)
[_delegate CustomTableViewCell:self isDragging:NO]; // Dragging ended
- (void)layoutSubviews
[super layoutSubviews];
for (UIView *view in self.subviews)
if ([NSStringFromClass ([view class]) rangeOfString:@"ReorderControl"].location != NSNotFound) // UITableViewCellReorderControl
if (view.gestureRecognizers.count == 0)
UILongPressGestureRecognizer *gesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)];
gesture.cancelsTouchesInView = NO;
gesture.minimumPressDuration = 0.150;
[view addGestureRecognizer:gesture];
@end
请注意,虽然此代码不使用任何私有 API,但如果 Apple 更改其内部实现(即通过更改 UITableViewCellReorderControl
的类名),它仍可能停止工作。
【讨论】:
谢谢彼得,需要重新考虑我当前的实现是否值得冒险依赖类名,或者我是否更好地更改“tableview 始终在编辑”范式以便我可以停止更新一次用户点击编辑。似乎更可靠,只是不确定如何将其集成到我的 UI 中;) 这是公认的答案,自 Apple 添加并记录了新的委托方法以来,已将其更改为来自 @mprudhom 的答案。 @Cornelius Apple 在哪里添加并记录了新的委托方法?我在 iOS 8 上,它们仍然是私有 API。【参考方案2】:您的 UITableViewDelegate 将收到以下通知以响应重新排序操作:
- (void)tableView:(UITableView *)tableView willBeginReorderingRowAtIndexPath:(NSIndexPath *)indexPath;
- (void)tableView:(UITableView *)tableView didEndReorderingRowAtIndexPath:(NSIndexPath *)indexPath;
- (void)tableView:(UITableView *)tableView didCancelReorderingRowAtIndexPath:(NSIndexPath *)indexPath;
【讨论】:
@mprudhom 我收到了回调,但它们没有记录。您在生产应用程序中有这些委托方法吗?这是否被视为私有 API? 作为后续:我应该提一下,我使用这三种方法的应用程序刚刚获得了 Apple 的批准,因此我们应该认为它们可以安全使用以改善用户体验。 无法快速调用? 在 iOS 9.2 和 Swift 2 中仍然被调用func tableView(tableView: UITableView, didEndReorderingRowAtIndexPath indexPath: NSIndexPath)
。如此有用的方法,我想知道他们为什么不记录它。
对于任何想知道的人。它仍然在 iOS 12 和 Swift 4 中使用以下签名调用:@objc public func tableView(_: UITableView, willBeginReorderingRowAtIndexPath indexPath: IndexPath)
【参考方案3】:
当您完成移动单元格时会调用此方法:
- (void) tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
【讨论】:
不,当您在行之间拖动单元格时会调用此方法。 Kimi Chiu - 不,它要求完成移动,而不是在拖动时【参考方案4】:刚刚我发现了一个 hack,因为苹果会降低 alpha,我猜我们可以使用它
@interface CustomTableViewCell ()
@property (nonatomic, assign) BOOL isDragging;
@end
-(void)draggingWillBegan
//use a delegate method to inform tableview
-(void)draggingDidEnd
//use a delegate method to inform tableview
- (void)layoutSubviews
[super layoutSubviews];
//Since apple wont provide en
if(self.alpha <= 0.95 && !self.isDragging)
self.isDragging = YES;
[self draggingWillBegan];
if(self.alpha >= 0.95 && self.isDragging)
self.isDragging = NO;
[self draggingDidEnd];
【讨论】:
这是唯一对我有用的东西。就我而言,tableview 位于一个也在监听手势的卡片视图中。表格视图的拖动将赶上卡片视图手势。当我在 tableviewcells 中检测到“isDragging”时,我必须“关闭”卡片视图手势,并在未拖动单元格时返回手势。以上是关于如何获得 UITableViewCell 移动开始和结束的通知?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 UITableViewCell 中获得透明的附件视图? (带截图)
如何获得 UITableViewCell 字幕显示特定单元格被点击了多少次?
如何在编辑模式下隐藏 UITableViewCell 右侧的三行“移动”符号?
iOS:如何将 UITableViewCell 附件按钮向左移动