这是我想要做的:

  • UITableView在编辑模式下有2个部分。
  • 用户可以将单元格从第二部分移到第一部分,反之亦然。
  • 在第一部分中,用户可以根据需要对单元进行重新排序。
  • 在第二部分中,单元的位置是固定的,因此,如果用户将单元从第一部分移至第二部分,则应将其移至特定位置,而不是用户想要的位置。

  • 为了实现此行为,我有2个数组:一个用于第一部分,一个用于第二部分(不确定是否是最佳选择)。

    以下是控制用户应将单元格移至何处的代码:
    func tableView(tableView: UITableView, targetIndexPathForMoveFromRowAtIndexPath sourceIndexPath: NSIndexPath, toProposedIndexPath proposedDestinationIndexPath: NSIndexPath) -> NSIndexPath {
        if proposedDestinationIndexPath.section == 1 {
            let item = (sourceIndexPath.section == 0 ? firstSectionItems[sourceIndexPath.row] : secondSectionItems[sourceIndexPath.row]).item
            return NSIndexPath(forRow: item.displayOrder.integerValue, inSection: 1)
        }
    
        return proposedDestinationIndexPath
    }
    

    这是在部分之间移动项目的代码:
    func tableView(tableView: UITableView, moveRowAtIndexPath sourceIndexPath: NSIndexPath, toIndexPath destinationIndexPath: NSIndexPath) {
    
        let section = (source: sourceIndexPath.section, destination: destinationIndexPath.section)
    
        switch section {
        case (0, 0):
            let itemToMove = firstSectionItems.removeAtIndex(sourceIndexPath.row)
            itemToMove.item.order = destinationIndexPath.row
            firstSectionItems.insert(itemToMove, atIndex: destinationIndexPath.row)
        case (1, 1):
            let itemToMove = secondSectionItems.removeAtIndex(sourceIndexPath.row)
            secondSectionItems.insert(itemToMove, atIndex: destinationIndexPath.row)
        case (1, 0):
            let itemToMove = secondSectionItems.removeAtIndex(sourceIndexPath.row)
            itemToMove.item.order = destinationIndexPath.row
            firstSectionItems.insert(itemToMove, atIndex: destinationIndexPath.row)
        case (0, 1):
            let itemToMove = firstSectionItems.removeAtIndex(sourceIndexPath.row)
            itemToMove.item.order = -1
            secondSectionItems.insert(itemToMove, atIndex: destinationIndexPath.row)
        default:
            break
        }
    
        DatabaseConnector.saveContext()
    }
    

    问题是,如果我在第一部分中有多个项目,并且尝试将最后一个移到第二部分中,那么当我将单元格放在第二部分上并在App Delegate上向我显示EXC_BAD_ACCESS时,它会崩溃,而控制台无输出。
    调试导航器不会告诉我太多,moveRowAtIndexPath:不会被调用。最后一个被调用的方法是-[UISectionRowData insertRowAtIndex:inSection:rowHeight:tableViewRowData:]

    有时当崩溃时,我会在控制台中收到一条奇怪的消息:

    警告:无法从加载任何Objective-C类信息
    dyld共享缓存。这将大大降低打字质量
    可用信息。

    我正在使用Swift 2。

    最佳答案

    嗯,问题出在displayOrder方法中某个项目的tableView(_:targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath:)中。

    如果您在一个数组中有5个元素,并且要插入的displayOrder是7,那么它将崩溃,因为该部分中的最后一个indexPath.row将为5,但是您尝试使用indexPath.row = 7进行插入。这是不可能的。不过,您可以插入indexPath.row = 6,因为它是表视图中最后一个indexPath之后的下一个。

    因此,该方法现在如下所示:

    func tableView(tableView: UITableView, targetIndexPathForMoveFromRowAtIndexPath sourceIndexPath: NSIndexPath, toProposedIndexPath proposedDestinationIndexPath: NSIndexPath) -> NSIndexPath {
        if proposedDestinationIndexPath.section == 1 {
            let item = (sourceIndexPath.section == 0 ? firstSectionItems[sourceIndexPath.row] : secondSectionItems[sourceIndexPath.row]).item
            let rowIndex = item.displayOrder > secondSectionItems.count ? secondSectionItems.count : item.displayOrder
            return NSIndexPath(forRow: rowIndex, inSection: 1)
        }
    
        return proposedDestinationIndexPath
    }
    

    而且效果很好。

    (愚蠢的错误:-/)

    关于ios - 在节之间移动行时EXC_BAD_ACCESS,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31221027/

    10-11 05:58