0

I am working on an app with a tableView in a ViewController. In this tableView I have sections and rows and I want my user to be able to long press, drag and drop cells in between sections with UILongPressGestureRecognizer.

With the following code my gesture recognizer works but at the moment that I try to drag the cell and drop it anywhere in the tableView, my app crashes. The crashes occur in two different lines. When the cell is long pressed and drag inside a section it crashes on this line: tableView.moveRowAtIndexPath(Path.initialIndexPath!, toIndexPath: indexPath!) if I try to drag out of a section it crashes on this line: swap(&Categories.categories[indexPath!.row], &Categories.categories[Path.initialIndexPath!.row])

(the arrays with the data for each section and rows are in a separate class, named Categories. The array with sections is called "sections", and the one with rows is named "categories.")

I would appreciate any help with finding out why it fails and how can I fix it.

func setupLongPress() {
    let longpress = UILongPressGestureRecognizer(target: self, action:   "longPressGestureRecognized:")
    tableView.addGestureRecognizer(longpress)
}

func longPressGestureRecognized(gestureRecognizer: UIGestureRecognizer) {
    let longPress = gestureRecognizer as! UILongPressGestureRecognizer
    let state = longPress.state
    let locationInView = longPress.locationInView(tableView)
    let indexPath = tableView.indexPathForRowAtPoint(locationInView)

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

    switch state {
    case UIGestureRecognizerState.Began:
        if indexPath != nil {
            Path.initialIndexPath = indexPath
            let cell = tableView.cellForRowAtIndexPath(indexPath!) as UITableViewCell!
            My.cellSnapshot  = snapshopOfCell(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:
        var center = My.cellSnapshot!.center
        center.y = locationInView.y
        My.cellSnapshot!.center = center
        if ((indexPath != nil) && (indexPath != Path.initialIndexPath)) {
            swap(&Categories.categories[indexPath!.row], &Categories.categories[Path.initialIndexPath!.row])
            tableView.moveRowAtIndexPath(Path.initialIndexPath!, toIndexPath: indexPath!)
            Path.initialIndexPath = indexPath
        }

    default:
        let cell = tableView.cellForRowAtIndexPath(Path.initialIndexPath!) as UITableViewCell!
        cell.hidden = false
        cell.alpha = 0.0
        UIView.animateWithDuration(0.5, 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
            }
        })
    }
}

func snapshopOfCell(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 = 1.0
            cellSnapshot.layer.shadowOpacity = 0.2
    return cellSnapshot
}

Thank you!

romansito
  • 33
  • 1
  • 6
  • 1
    If you could mark the line where it crashes and add the exception message and backtrace - that would be helpful. – A-Live Jan 12 '16 at 17:00
  • You don't want it using editing mode? – Bista Jan 13 '16 at 05:29
  • @the_UB no I don't want to use editing more. – romansito Jan 13 '16 at 19:06
  • @A-Live Hi, thanks for wanting to help me out. When I long press a cell and move it up. It crashes here: `swap(&Categories.categories[indexPath!.row], &Categories.categories[Path.initialIndexPath!.row])` and the console logs "fatal error: Array index out of range" if I move the cell, the line exactly below this last one crashes. – romansito Jan 13 '16 at 19:10
  • I haven't tried your code, assuming this implementation is viable and the gesture recognizer works as expected the only issue would be that you are trying to use an invalid index of `&Categories.categories`. One obvious problem is that your code doesn't seem to consider cells moved between sections as you are trying to swap rows on the same section. – A-Live Jan 14 '16 at 07:35

0 Answers0