UITableView如何在重新排序单元格

时间:2017-10-23 09:13:41

标签: ios swift uitableview

在我的项目中,我想要实现移动行以及删除它们但不使用库存“删除”按钮,而是通过点击我的自定义 UITableViewCell 中的图像 QueueCell 。我删除函数 deleteByTap2 中的行,它使用 sender.tag cell.indexPath.row )来识别应删除哪个单元格。移动和删除工作都很好,但是当你移动时,例如,第6行到第2行它仍然带有tag = 6,因此当我点击图像删除行时,错误的行被删除。我创建了一个函数 reTag ,它应该更新各个部分中的所有单元格的标签,并且在 deleteByTap2 函数中调用后效果很好但是在结束时调用 func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) 它似乎不知道移动行后tableView的状态。我搜索了论坛,发现有无证件 UITableViewDelegate 功能

- (void)tableView:(UITableView *)tableView didEndReorderingRowAtIndexPath:(NSIndexPath *)indexPath;

但我尝试调用它,它似乎已被删除(或者名称已更改) 我什么时候应该调用 reTag 功能才能正常工作?那么在重新排序后它会知道tableView的顺序吗?

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! QueueCell
        let item = sungs[indexPath.section].songsIn[indexPath.row]
        cell.setup(item: item)
        if indexPath.section == 2{
            let tap = UITapGestureRecognizer(target: self, action: #selector(deleteByTap2(_:)))
            tap.numberOfTapsRequired = 1
            tap.numberOfTouchesRequired = 1
            cell.artwork.addGestureRecognizer(tap)
            cell.artwork.isUserInteractionEnabled = true
            cell.artwork.tag = indexPath.row
        }
        return cell
    }


    override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
    var toMove: MPMediaItem
    tableView.beginUpdates()
    if sourceIndexPath.section == 2{
            if player.isShuffle{
                toMove = player.shufQueue[player.shufIndex + sourceIndexPath.row + 1]
                player.shufQueue.remove(at: player.shufIndex + sourceIndexPath.row + 1)
                if destinationIndexPath.section == 2{
                    player.shufQueue.insert(toMove, at: player.shufIndex + destinationIndexPath.row + 1)
                }
            }else{
                toMove = player.defQueue[player.defIndex + sourceIndexPath.row + 1]
                player.defQueue.remove(at: player.defIndex + sourceIndexPath.row + 1)
                if destinationIndexPath.section == 2{
                    player.defQueue.insert(toMove, at: player.defIndex + destinationIndexPath.row + 1)
                }
            }
        }
    tableView.endUpdates()

    reTag(section: destinationIndexPath.section)
}
//the beginUpdates()-endUpdates() doesn't do much good here, actually it messes some of my cells

func reTag(section: Int){
        var indexPath: IndexPath
        for row in 0 ..< tableView.numberOfRows(inSection: section){
            indexPath = IndexPath(row: row, section: section)
            if let cell = tableView.cellForRow(at: indexPath) as? QueueCell{
                cell.artwork.tag = row
            }
        }
    }

func deleteByTap2(_ sender: UITapGestureRecognizer){
        let tag = (sender.view?.tag)!
        if player.isUsrQueue{
            player.usrQueue.remove(at: player.usrIndex + tag + 1)
            player.usrQueueCount! -= 1
            sungs[2].songsIn.remove(at: tag)
        }else{
            player.defQueue.remove(at: player.defIndex + tag + 1)
            sungs[2].songsIn.remove(at: tag)
            player.defQueueCount! -= 1
        }
        let indexPath = IndexPath(row: tag, section: 2)
        tableView.deleteRows(at: [indexPath], with: .fade)
        reTag(section: 2)
    }

1 个答案:

答案 0 :(得分:1)

这是一个很好的例子,说明为什么在对象上使用.tag来尝试以这种方式跟踪它们是个坏主意。

我建议您在单元格类中移动点击手势,然后添加&#34;回拨&#34;关闭。当然,此示例缺少您的数据类和cell.setup()代码,但您应该能够看到需要更改的内容:

// cell class
class QueueCell: UITableViewCell {

    @IBOutlet weak var artwork: UIImageView!

    var tapCallback: ((QueueCell) -> ())?

    func addTap() {

        if artwork.gestureRecognizers == nil {

            // cells are reused, so only add this once

            let tap = UITapGestureRecognizer(target: self, action: #selector(artworkTap(_:)))
            tap.numberOfTapsRequired = 1
            tap.numberOfTouchesRequired = 1
            artwork.addGestureRecognizer(tap)
            artwork.isUserInteractionEnabled = true

        }

    }

    func artworkTap(_ sender: UITapGestureRecognizer) -> Void {
        tapCallback?(self)
    }

}
// table view class
override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {

    // all you have to do is manage your data, 
    // no need to reload() or "re-tag" anything

}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCell(withIdentifier: "QueueCell", for: indexPath) as! QueueCell

    // your cell configuration
    //let item = sungs[indexPath.section].songsIn[indexPath.row]
    //cell.setup(item: item)

    if indexPath.section == 2 {

        // tell the cell to add the gesture recognizer
        cell.addTap()

        // set the "call back" closure
        cell.tapCallback = {
            theCell in
            if let iPath = tableView.indexPath(for: theCell) {
                self.deleteByTap2(tableView, indexPath: iPath)
            }
        }

    }

    return cell

}

func deleteByTap2(_ tableView: UITableView, indexPath: IndexPath) -> Void {
    print("Tapped on artwork at:", indexPath)
    // you now have a reference to the table view and the indexPath for the cell that
    // contained the artwork image view that was tapped
}

现在,您的deleteByTap2()功能将与熟悉的didSelectRowAt功能相匹配,您可以在那里处理删除。