1

I am using a UILongPressGestureRecognizer for each cell in a table view that has two sections/section headers. When I do a long press on a cell in my first section and drag to the top of the table view my app crashes. (I have disabled the longPressGestureRecognizer for the second section). I get an exception point at the line below,

var indexPath: NSIndexPath? = self.routeTableView.indexPathForRowAtPoint(location)!

I receive this error in the debugger,

fatal error: unexpectedly found nil while unwrapping an Optional value

my code is below,

func longPressGestureRecognized(gesture: UILongPressGestureRecognizer){
    
    var state: UIGestureRecognizerState = gesture.state
    
    var location:CGPoint = gesture.locationInView(self.routeTableView)
    var indexPath: NSIndexPath? = self.routeTableView.indexPathForRowAtPoint(location)!
    
    if indexPath == nil {
        return
    }
    
    if indexPath?.section != 1 {
        
        switch(state){
            case UIGestureRecognizerState.Began:
                sourceIndexPath = indexPath
                
                var cell: UITableViewCell = self.routeTableView .cellForRowAtIndexPath(indexPath!)! as! RouteSelectionCell
                
                //take a snapshot of the selected row using helper method
                snapshot = customSnapshotFromView(cell)
                
                //add snapshot as subview, centered at cell's center
                var center: CGPoint = cell.center
                snapshot?.center = center
                snapshot?.alpha  = 0.0
                self.routeTableView.addSubview(snapshot!)
                UIView.animateWithDuration(0.25, animations: { () -> Void in
                    center.y = location.y
                    self.snapshot?.center = center
                    self.snapshot?.transform = CGAffineTransformMakeScale(1.05, 1.05)
                    self.snapshot?.alpha = 0.98
                    cell.alpha = 0.0
                }, completion: { (finished) in
                    cell.hidden = true
                })
                
            case UIGestureRecognizerState.Changed:
                var center: CGPoint = snapshot!.center
                center.y = location.y
                snapshot?.center = center
                
                
                //is destination valid and is it different form source?
                if indexPath != sourceIndexPath{
                    //update data source
                    self.messageOptions.exchangeObjectAtIndex(indexPath!.row, withObjectAtIndex: sourceIndexPath!.row)
                    //move the row
                    self.routeTableView.moveRowAtIndexPath(sourceIndexPath!, toIndexPath: indexPath!)
                    //and update source so it is in sync with UI changes
                    sourceIndexPath = indexPath
                }
                
            default:
                //clean up
                let cell: UITableViewCell = routeTableView.cellForRowAtIndexPath(sourceIndexPath!)!
                cell.alpha = 0.0
                cell.hidden = false
                
                UIView.animateWithDuration(0.25, animations: { () -> Void in
                    
                    self.snapshot?.center = cell.center
                    self.snapshot?.transform = CGAffineTransformIdentity
                    self.snapshot?.alpha = 0.0
                    //undo fade out
                    cell.alpha = 1.0
                    
                }, completion: { (finished) in
                    self.sourceIndexPath = nil
                    self.snapshot?.removeFromSuperview()
                    self.snapshot = nil
                })
                break
        }
    }
}

Anyone have any suggestions on how to avoid this issue?

Kozmotronik
  • 2,080
  • 3
  • 10
  • 25
Jaxs_ios
  • 48
  • 10

1 Answers1

0

When you call self.routeTableView.indexPathForRowAtPoint(location)! you are force unwrapping the value that comes back, and in this case, its nil. This is where you are crashing.

Your code should do something like this:

if let indexPath = self.routeTableView.indexPathForRowAtPoint(location) {
  //do normal code
} else {
  //the point didn't map back to a cell! Maybe it was on the header or footer? 
  //Handle this case differently.
}

Also, I found this answer that might help:

indexPathForRowAtPoint returns nil only for first cell in a uitableview

Community
  • 1
  • 1
72A12F4E
  • 1,744
  • 1
  • 14
  • 28
  • Ahhh. So I removed the "!" and am no longer crashing. However, my cell/ snapshot is disabling when I drag to the top of the view. It seems to be hovering over the other cells. – Jaxs_ios Jul 21 '15 at 19:58
  • In the else statement, you will have to manage how to deal with those specific edge cases. For example, if it ends up at the top of the screen, maybe insert it at index 0. If its at the bottom, insert it at the end of your table. – 72A12F4E Jul 21 '15 at 20:14
  • are you talking about snapshot.layer.edgeAntialiasingMask? Sorry. I've only been developing for a little over a year. – Jaxs_ios Jul 21 '15 at 20:49