UITableView Drag&跌倒桌面=崩溃 [英] UITableView Drag & Drop Outside Table = Crash

查看:266
本文介绍了UITableView Drag&跌倒桌面=崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我的拖放掉落功能几乎可以奇妙地工作。我长按一个单元格,它顺利地允许我将压制单元移动到另外两个单元格之间的新位置。表调整,更改保存到核心数据。很好!





我的问题是,如果我拖动单元格在桌子下面的单元格下方,即使我不放开(un-press)的单元格...应用程序崩溃。如果我慢慢拖动,真的会崩溃,因为单元格穿过最后一个单元格的y中心...所以我认为这是一个与获取位置的快照相关的问题。不太重要但可能相关的是,如果我长时间按下最后一个单元格的值,它也会崩溃。



拖放运行一个开关根据状态运行三组代码之一的语句:




  • 新闻开始时有一种情况

  • 单元格被拖动时的一种情况

  • 当用户放弃单元格时,有一种情况



我的代码改编自本教程:



解决方案

p> 丑陋



似乎您只需要先行检查,以确保您的 indexPath 不是nil:

  var indexPath = tableView.indexPathForRowAtPoint(locationInView)
if(indexPath! = nil){
//将代码移动到此块
}

希望有帮助!


The Good

My drag & drop function almost works wonderfully. I longPress a cell and it smoothly allows me to move the pressed cell to a new location between two other cells. The table adjusts and the changes save to core data. Great!

The Bad

My problem is that if I drag the cell below the bottom cell in the table, even if I don't let go (un-press) of the cell... the app crashes. If I do the drag slowly, really it crashes as the cell crosses the y-center of the last cell... so I do think it's a problem related to the snapshot getting a location. Less important, but possibly related, is that if I long press below the last cell with a value in it, it also crashes.

The drag/drop runs off a switch statement that runs one of three sets of code based on the status:

  • One case when the press begins
  • One case when the cell is being dragged
  • One case when when the user lets go of the cell

My code is adapted from this tutorial:

Drag & Drop Tutorial

My code:

 func longPressGestureRecognized(gestureRecognizer: UIGestureRecognizer) {

    let longPress = gestureRecognizer as! UILongPressGestureRecognizer
    let state = longPress.state

    var locationInView = longPress.locationInView(tableView)
    var indexPath = tableView.indexPathForRowAtPoint(locationInView)

    struct My {
        static var cellSnapshot : UIView? = nil
    }
    struct Path {
        static var initialIndexPath : NSIndexPath? = nil
    }

    let currentCell = tableView.cellForRowAtIndexPath(indexPath!) as! CustomTableViewCell;

    var dragCellName = currentCell.nameLabel!.text
    var dragCellDesc = currentCell.descLabel.text


    //Steps to take a cell snapshot. Function to be called in switch statement
    func snapshotOfCell(inputView: UIView) -> UIView {
        UIGraphicsBeginImageContextWithOptions(inputView.bounds.size, false, 0.0)
        inputView.layer.renderInContext(UIGraphicsGetCurrentContext())
        let image = UIGraphicsGetImageFromCurrentImageContext() as UIImage
        UIGraphicsEndImageContext()
        let cellSnapshot : UIView = UIImageView(image: image)
        cellSnapshot.layer.masksToBounds = false
        cellSnapshot.layer.cornerRadius = 0.0
        cellSnapshot.layer.shadowOffset = CGSizeMake(-5.0, 0.0)
        cellSnapshot.layer.shadowRadius = 5.0
        cellSnapshot.layer.shadowOpacity = 0.4
        return cellSnapshot
    }


    switch state {
        case UIGestureRecognizerState.Began:
            //Calls above function to take snapshot of held cell, animate pop out
            //Run when a long-press gesture begins on a cell
            if indexPath != nil && indexPath != nil {
                Path.initialIndexPath = indexPath
                let cell = tableView.cellForRowAtIndexPath(indexPath!) as UITableViewCell!
                My.cellSnapshot  = snapshotOfCell(cell)
                var center = cell.center

                My.cellSnapshot!.center = center
                My.cellSnapshot!.alpha = 0.0

                tableView.addSubview(My.cellSnapshot!)

                UIView.animateWithDuration(0.25, animations: { () -> Void in
                    center.y = locationInView.y

                    My.cellSnapshot!.center = center
                    My.cellSnapshot!.transform = CGAffineTransformMakeScale(1.05, 1.05)
                    My.cellSnapshot!.alpha = 0.98

                    cell.alpha = 0.0

                    }, completion: { (finished) -> Void in

                        if finished {
                            cell.hidden = true
                        }
                })
            }
        case UIGestureRecognizerState.Changed:

            if My.cellSnapshot != nil && indexPath != nil {
                //Runs when the user "lets go" of the cell
                //Sets CG Y-Coordinate of snapshot cell to center of current location in table (snaps into place)
                var center = My.cellSnapshot!.center
                center.y = locationInView.y
                My.cellSnapshot!.center = center

                var appDel: AppDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)
                var context: NSManagedObjectContext = appDel.managedObjectContext!
                var fetchRequest = NSFetchRequest(entityName: currentListEntity)
                let sortDescriptor = NSSortDescriptor(key: "displayOrder", ascending: true )
                fetchRequest.sortDescriptors = [ sortDescriptor ]


                //If the indexPath is not 0 AND is not the same as it began (didn't move)...
                //Update array and table row order
                if ((indexPath != nil) && (indexPath != Path.initialIndexPath)) {

                    swap(&taskList_Cntxt[indexPath!.row], &taskList_Cntxt[Path.initialIndexPath!.row])
                    tableView.moveRowAtIndexPath(Path.initialIndexPath!, toIndexPath: indexPath!)

                    toolBox.updateDisplayOrder()
                    context.save(nil)

                    Path.initialIndexPath = indexPath
                }
            }
        default:
            if My.cellSnapshot != nil && indexPath != nil {
                //Runs continuously while a long press is recognized (I think)
                //Animates cell movement
                //Completion block: 
                //Removes snapshot of cell, cleans everything up
                let cell = tableView.cellForRowAtIndexPath(Path.initialIndexPath!) as UITableViewCell!

                cell.hidden = false
                cell.alpha = 0.0
                UIView.animateWithDuration(0.25, animations: { () -> Void in
                    My.cellSnapshot!.center = cell.center
                    My.cellSnapshot!.transform = CGAffineTransformIdentity
                    My.cellSnapshot!.alpha = 0.0
                    cell.alpha = 1.0
                    }, completion: { (finished) -> Void in
                        if finished {
                            Path.initialIndexPath = nil
                            My.cellSnapshot!.removeFromSuperview()
                            My.cellSnapshot = nil
                        }
                })//End of competion block & end of animation

            }//End of 'if nil'

    }//End of switch

}//End of longPressGestureRecognized

Potential Culprit

My guess is that the issue is related to the cell being unable to get coordinates once it is below the last cell. It isn't really floating, it is constantly setting its location in relation to the other cells. I think the solution will be an if-statement that does something magical when there's no cell to reference for a location. But what!?! Adding a nil check to each case isn't working for some reason.

Clearly Stated Question

How do I avoid crashes and handle an event where my dragged cell is dragged below the last cell?

Screenshot of crash:

解决方案

The Ugly

It seems that you simply need to do a preemptive check, to ensure your indexPath is not nil:

var indexPath = tableView.indexPathForRowAtPoint(locationInView)
if (indexPath != nil) {
    //Move your code to this block
}

Hope that helps!

这篇关于UITableView Drag&跌倒桌面=崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆