重新排序时无法从当前位置拖动 UITableViewCell

Posted

技术标签:

【中文标题】重新排序时无法从当前位置拖动 UITableViewCell【英文标题】:Can't drag UITableViewCell from its current position when reorder 【发布时间】:2012-02-12 19:05:11 【问题描述】:

我正在尝试使我的核心数据支持的 UITableView 具有重新排序能力,在实现了所有这些委托和一些提到的核心数据技术之后 here 我发现了奇怪的行为。点击编辑按钮后,重新排序图标显示得很好,我可以点击它,阴影出现,但是当我尝试将其移动到另一行时,我突然失去焦点,单元格移回原位。有谁知道这个问题的原因吗?

这是显示问题的视频

http://www.youtube.com/watch?v=ugxuLNL7BnU&feature=youtu.be

这是我的代码

- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath

    return YES;

-tableView:moveRowAtIndexPath:toIndexPath我尝试了下面的代码,只是一个空实现,但问题仍然存在,所以我认为这不是问题。

- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath

    _changeIsUserDriven = YES;

    NSUInteger fromIndex = sourceIndexPath.row;
    NSUInteger toIndex = destinationIndexPath.row;

    NSMutableArray *newsArray = [[self.fetchedResultsController fetchedObjects] mutableCopy];
    News *news = [self.fetchedResultsController.fetchedObjects objectAtIndex:fromIndex];

    [newsArray removeObject:news];
    [newsArray insertObject:news atIndex:toIndex];

    int i = 1;
    for (News *n in newsArray) 
        n.displayOrder = [NSNumber numberWithInt:i++];
    

    [self saveContext];

    _changeIsUserDriven = NO;

FetchedResultController 委托

    - (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
    
        if (_changeIsUserDriven) 
            return;
        
        [self.tableView beginUpdates];
    




       - (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
                   atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
        
            if (_changeIsUserDriven) 
                return;
            
            switch(type) 
                case NSFetchedResultsChangeInsert:
                    [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
                    break;

                case NSFetchedResultsChangeDelete:
                    [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
                    break;
            
        


- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
       atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
      newIndexPath:(NSIndexPath *)newIndexPath

    if (_changeIsUserDriven) 
        return;
    
    UITableView *tableView = self.tableView;

    switch(type) 
        case NSFetchedResultsChangeInsert:
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeUpdate:
            [self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
            break;

        case NSFetchedResultsChangeMove:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]withRowAnimation:UITableViewRowAnimationFade];
            break;
    


    - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
    
        if (_changeIsUserDriven) 
            return;
        
        [self.tableView endUpdates];
    

【问题讨论】:

您是否实施了tableView commitEditingStyle:forRowAtIndexPath: 并实施了UITableViewCellEditingStyleInsert 案例来更新您的数据源并实际移动行(或reloadData)? 我为此使用核心数据和 fetchedResultController,所有保存部分都在 - (void)tableView:moveRowAtIndexPath:toIndexPath: 好了,现在代码多了: 【参考方案1】:

最后我发现问题是因为我使用的外部库 IIViewDeckController,删除后问题就消失了。

【讨论】:

如果你想保留IIViewDeckController,你可以通过禁用平移模式来解决这个问题:viewDeck.panningMode = IIViewDeckNoPanning; 我也遇到了同样的问题,这解决了我的问题。你是我的英雄。 ECSlidingViewController 遇到了同样的问题。使用[self.view removeGestureRecognizer:self.slidingViewController.panGesture]; 暂时删除滑动手势为我解决了这个问题。 谢谢兄弟!救了我! PKReavealController 我也有同样的问题,对于其他面临这个问题的人,只需在 tableView 进入编辑模式时设置self.revealController.recognizesPanningOnFrontView = NO;,在完成编辑时设置self.revealController.recognizesPanningOnFrontView = YES; 同样的问题,但与 SlideNavigationViewController。 [SlideNavigationController sharedInstance].enableSwipeGesture = NO; 解决问题。哇!【参考方案2】:

这确实是由于 ViewDeckController。我在 MonoTouch 中使用端口,但仍然遇到问题。这要归功于(更具体地说)UIPanGestureRecognizer。手势识别器正在拾取平移/拖动移动,并认为它是为自己设计的,因此它取消了发送到 UITableView 的触摸。

不幸的是,没有 UIPanGestureRecognizer.direction (horizo​​nal/vertical) 属性,但这里有一个帖子:UIPanGestureRecognizer - Only vertical or horizontal 关于如何将平移手势限制为仅某个方向。您将需要修改 ViewDeckController 代码,在其中添加 UIPanGestureRecognizer 以使用上述问题中的子类版本。

我还没有测试过这个(因为它是凌晨 2 点,我今天已经完成了!)但是一旦我有时间实现这个,我会更新我的答案。

作为一个快速而肮脏的修复,您可以设置

panner.cancelsTouchesInView = NO;

这将允许您移动您的项目,但它也会产生不取消视图中的触摸的预期结果,因此,根据您的中心视图的内容,它可能会导致您的用户在他们想要的时候按下按钮只需将观景台滑动到一边。

另一种可能性是在将表格设置为编辑模式时将此属性设置为 NO,并在完成后将其更改回 YES。

【讨论】:

以上是关于重新排序时无法从当前位置拖动 UITableViewCell的主要内容,如果未能解决你的问题,请参考以下文章

保存拖动小部件的位置

通过拖动重新排序ListView的元素[重复]

在 iOS 13 上拖动时,UICollectionView 单元格捕捉到原始位置

拖动移动时不更新 React-dnd 元素样式

Android UI 测试长按拖拽

拖动地图时未获取当前位置