如何获得 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 附件按钮向左移动

如何在iOS 7上的UITableViewCell左侧获得复选标记,就像在设置中一样?

如何在 UITableViewCell swift 中获得正确的 UIView 宽度