Ios Swift-使用长手势识别器拖放TableViewCell

Ios Swift-使用长手势识别器拖放TableViewCell,ios,uitableview,swift,uigesturerecognizer,Ios,Uitableview,Swift,Uigesturerecognizer,因此,我看到了很多关于使用“编辑模式”对单元格重新排序的帖子,但没有一篇是针对我遇到的问题。(如果我错了,请原谅) 我正在构建一个排名应用程序,并寻找一种方法来使用长手势识别器对UITableView中的单元格进行重新排序。从本质上讲,用户将能够与他们的朋友在一个组中对充满字符串的单元格进行重新排序和“排序” 我会选择在导航栏中使用“编辑”栏按钮项的标准路线,但我已经在使用导航栏右上角向tableview添加新字符串了。(下图描述了我的意思) 到目前为止,我补充说` var lpgr =

因此,我看到了很多关于使用“编辑模式”对单元格重新排序的帖子,但没有一篇是针对我遇到的问题。(如果我错了,请原谅)

我正在构建一个排名应用程序,并寻找一种方法来使用长手势识别器对UITableView中的单元格进行重新排序。从本质上讲,用户将能够与他们的朋友在一个组中对充满字符串的单元格进行重新排序和“排序”

我会选择在导航栏中使用“编辑”栏按钮项的标准路线,但我已经在使用导航栏右上角向tableview添加新字符串了。(下图描述了我的意思)

到目前为止,我补充说`

    var lpgr = UILongPressGestureRecognizer(target: self, action: "longPressDetected:")

    lpgr.minimumPressDuration = 1.0;
    tableView.addGestureRecognizer(lpgr)`
,并开始创建以下函数:

    func longPressDetected(sender: AnyObject) {

    var longPress:UILongPressGestureRecognizer = sender as UILongPressGestureRecognizer
    var state:UIGestureRecognizerState = longPress.state

    let location:CGPoint = longPress.locationInView(self.tableView) as CGPoint
    var indexPath = self.tableView.indexPathForRowAtPoint(location)?

    var snapshot:UIView!
    var sourceIndexPath:NSIndexPath!

}
我在互联网上搜索的所有资源最终都向我展示了一个庞大的、长长的功能添加剂列表,以获得期望的结果,但这些示例涉及核心数据。在我看来,必须有一种更简单的方法,只需长按即可对tableview单元格重新排序


试一试本教程,您可能会在20分钟内启动并运行:

这很容易。我只开发了3个月,就能够实现这一点。我还试过其他几种,这是我能理解的

它是用Swift写的,几乎是剪切粘贴的。将longPress代码添加到viewDidLoad中,然后将函数粘贴到类的“body”中。本教程将指导您,但没有更多内容

快速解释代码:此方法使用switch语句检测长按是刚刚开始、更改还是处于默认状态。每种情况下运行不同的代码。它为长时间按下的单元格拍摄快照/图片,隐藏单元格,并移动快照。完成后,它将取消隐藏单元格并从视图中删除快照

警告:我要提醒的一点是,尽管此拖放操作看起来很不错,工作也很完美,但在将单元格拖到最低/底部单元格下方时,似乎确实存在崩溃的问题

戴夫的回答很好。 以下是本教程的swift 4版本:

WayPointCell
是您的
CustomUITableViewCell
wayPoints
是UITableView的数据源数组

首先,将其放在viewDidLoad中,如Alfi所述:

override func viewDidLoad() {
    super.viewDidLoad()

    let longpress = UILongPressGestureRecognizer(target: self, action: #selector(longPressGestureRecognized(gestureRecognizer:)))
    self.tableView.addGestureRecognizer(longpress)
}
然后实现该方法:

func longPressGestureRecognized(gestureRecognizer: UIGestureRecognizer) {

    let longpress = gestureRecognizer as! UILongPressGestureRecognizer
    let state = longpress.state
    let locationInView = longpress.location(in: self.tableView)
    var indexPath = self.tableView.indexPathForRow(at: locationInView)

    switch state {
    case .began:
        if indexPath != nil {
            Path.initialIndexPath = indexPath
            let cell = self.tableView.cellForRow(at: indexPath!) as! WayPointCell
            My.cellSnapShot = snapshopOfCell(inputView: cell)
            var center = cell.center
            My.cellSnapShot?.center = center
            My.cellSnapShot?.alpha = 0.0
            self.tableView.addSubview(My.cellSnapShot!)

            UIView.animate(withDuration: 0.25, animations: {
                center.y = locationInView.y
                My.cellSnapShot?.center = center
                My.cellSnapShot?.transform = CGAffineTransform(scaleX: 1.05, y: 1.05)
                My.cellSnapShot?.alpha = 0.98
                cell.alpha = 0.0
            }, completion: { (finished) -> Void in
                if finished {
                    cell.isHidden = true
                }
            })
        }

    case .changed:
        var center = My.cellSnapShot?.center
        center?.y = locationInView.y
        My.cellSnapShot?.center = center!
        if ((indexPath != nil) && (indexPath != Path.initialIndexPath)) {

            self.wayPoints.swapAt((indexPath?.row)!, (Path.initialIndexPath?.row)!)
            //swap(&self.wayPoints[(indexPath?.row)!], &self.wayPoints[(Path.initialIndexPath?.row)!])
            self.tableView.moveRow(at: Path.initialIndexPath!, to: indexPath!)
            Path.initialIndexPath = indexPath
        }

    default:
        let cell = self.tableView.cellForRow(at: Path.initialIndexPath!) as! WayPointCell
        cell.isHidden = false
        cell.alpha = 0.0
        UIView.animate(withDuration: 0.25, animations: {
            My.cellSnapShot?.center = cell.center
            My.cellSnapShot?.transform = .identity
            My.cellSnapShot?.alpha = 0.0
            cell.alpha = 1.0
        }, completion: { (finished) -> Void in
            if finished {
                Path.initialIndexPath = nil
                My.cellSnapShot?.removeFromSuperview()
                My.cellSnapShot = nil
            }
        })
    }
}

func snapshopOfCell(inputView: UIView) -> UIView {

    UIGraphicsBeginImageContextWithOptions(inputView.bounds.size, false, 0.0)
    inputView.layer.render(in: UIGraphicsGetCurrentContext()!)
    let image = UIGraphicsGetImageFromCurrentImageContext()!
    UIGraphicsEndImageContext()
    let cellSnapshot : UIView = UIImageView(image: image)
    cellSnapshot.layer.masksToBounds = false
    cellSnapshot.layer.cornerRadius = 0.0
    cellSnapshot.layer.shadowOffset = CGSize(width: -5.0, height: 0.0)
    cellSnapshot.layer.shadowRadius = 5.0
    cellSnapshot.layer.shadowOpacity = 0.4
    return cellSnapshot
}

struct My {
    static var cellSnapShot: UIView? = nil
}

struct Path {
    static var initialIndexPath: IndexPath? = nil
}

由于iOS 11,这可以通过实现内置的UITableView拖放委托来实现

在对类似问题的回答中,您将看到关于如何实施它们的详细说明:

是的,您绝对不需要使用核心数据。您只想通过拖放对单元格进行重新排序吗?在手势识别时,将tableview单元格复制为可拖动视图,然后删除该视图,并在手势结束后相应地更新表格内容。这是我看到的第一个基本上“有效”的教程。谢谢分享!谢谢成功了。问题:我又为longPressEvent添加了一个状态“end”,之后它停止工作…如cellSnapShot重叠其他行等。基本上,我是想让longpress手势的末尾更新我的DB。别忘了将这两行添加到ViewDidLoad:let longpress=UILongPressGestureRecogener(目标:self,操作:“LongPressGestureRecognited:”)表格视图。添加GestureRecognitizer(longpress)当LongPressGestureRecognitor点击屏幕底部时滚动tableView如何?@CliftonLabrum查看此问题的SO帖子:此解决方案有效!但我遇到崩溃:由于未捕获异常“nsInternalInconsistenceException”终止应用程序,原因:“无效更新:第0节中的行数无效。行数包含更新(9)后现有节中的ed必须等于更新(9)前该节中包含的行数,加上或减去从该节插入或删除的行数(0插入,0删除),加上或减去移入或移出该节的行数(0移入,1移出).“当将单元格移动到另一个tableview分区时。如何解决此问题?@AlionSego我在expand-collapse UITableview中也开发了相同的功能,但我无法在UITable的末尾添加滚动。如何解决此问题?”