【问题标题】:How to get notified of UITableViewCell move start and end?如何获得 UITableViewCell 移动开始和结束的通知?
【发布时间】:2012-04-11 12:09:47
【问题描述】:

我的 iOS 应用中有一个 UITableView,它会定期刷新。用户还可以随时移动 tableview 行(tableview 始终处于编辑模式)。

我想在用户开始拖动一行时停止刷新计时器,并在删除该行时再次启动它。

moveRowAtIndexPath 的最后一部分应该很容易,但是如何获得有关拖动开始的通知?

【问题讨论】:

    标签: ios iphone uitableview drag


    【解决方案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”时,我必须“关闭”卡片视图手势,并在未拖动单元格时返回手势。
    猜你喜欢
    • 2010-11-27
    • 2012-03-12
    • 1970-01-01
    • 2018-09-29
    • 1970-01-01
    • 1970-01-01
    • 2019-08-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多