2015-08-27 2 views
4

ХорошийUITableView Drag & падение Outside Таблица = Краш

Моя перетащить & функция падение почти замечательно работает. I longPress cell, и он плавно позволяет мне переместить нажатую ячейку в новое место между двумя другими ячейками. Таблица настраивается и изменения сохраняются в основных данных. Большой!

Плохой

Моя проблема заключается в том, что если я перетащить ячейку ниже нижней ячейки в таблице, даже если я не отпускаю (ООН-пресс) ячейки ... приложение сбои. Если я медленно перетаскиваю, на самом деле он падает, когда ячейка пересекает y-центр последней ячейки ... поэтому я думаю, что это проблема, связанная с моментальным снимком, получающим местоположение. Менее важным, но, возможно, и связанным, является то, что если я долгое время поджимаю последнюю ячейку со значением в ней, она также падает.

Сопротивления/падение сбегает с заявлением переключателя, который работает один из трех наборов коды на основе статуса:

  • Один случая, когда пресса начинает
  • Один случая, когда клетка тащит
  • Один случай, когда, когда пользователь отпускает клетки

Мой код адаптировано из этого урока:

Drag & Drop Tutorial

Мой код:

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 

Потенциал Виновник

Я думаю, что проблема связана с ячейкой будучи не в состоянии получить координаты, когда он находится ниже последней ячейки. Он не плавает, он постоянно устанавливает свое местоположение по отношению к другим ячейкам. Я думаю, что решение будет выражением if, которое делает что-то магическое, когда нет ячейки для ссылки на местоположение. Но что!?! По какой-то причине добавление нуля для каждого случая не работает.

Ясно Заявлен Вопрос

Как избежать аварий и обработки событий, где моя тащили ячейка тащила ниже последнюю ячейку?

Скриншот аварии:

Out of Range

+0

Возможно, он попадает в «индекс массива за пределами границ», думая, что ячейка каким-то образом помещается в позицию в виде таблицы, которая понадобится добавить новый элемент в массив tableview, который невозможен, поэтому система get разозлилась и выйдет из строя, какова ошибка, говорящая конкретно? – Loxx

+0

@ Larcerax Ha! Ну, я думаю, ты на правильном пути. Он выдает код EXC: Bad Instructions. Консоль читает: «фатальная ошибка: индекс массива вне диапазона (lldb)». Любая идея, как сделать это поведение пользователя безопасным и не вызвать сбой? –

+0

да, поэтому перед событием или всегда, когда вы перетаскиваете ячейку, вам может понадобиться какое-то, как выкидывать икоту, например, повторное обновление или отправку, получать событие главной очереди или отправлять после времени бла-бла, дать короткое прерывание. Если вы можете принудительно добавить ячейку вправо при перетаскивании, то вы в порядке, то эта ячейка будет удалена, ячейка woudl будет скрытой ячейкой, но это очень грязно – Loxx

ответ

2

Гадкий

кажется, что вы просто должны сделать упреждающий контроль, чтобы обеспечить ваш indexPath не ноль:

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

Надеюсь, что он LPS!

+0

Переместить весь оператор switch или только отдельные случаи? У меня уже был нулевой чек для моментального снимка, который обертывал код в каждом случае. Я просто добавил ваш код, рассказывая каждому случаю, чтобы проверить, что и снимок, и indexPath не ноль. Тем не менее, я получаю: «фатальная ошибка: индекс массива вне диапазона» –

+0

Добавил мой полный код longPress, чтобы вы могли увидеть мою полную и самую последнюю попытку заставить ее работать (включая ваш код!). Thx для этой первой попытки, надеюсь, что вы мастер, который может решить этот вопрос, потому что он меня заводит, и это похоже на 1 из 2 оставшихся ошибок, которые я должен исправить, прежде чем приложение будет готово для загрузки! –

+0

Этот плакат никогда не отвечал на мои комментарии, но ответ заключается в том, что оператор if if indexPath! = Nil должен немедленно следовать объявлению indexPath var, а остальная часть кода перетаскивания должна находиться в этом if-statement. В каждом случае я проверял nil-проверку, но этого было недостаточно. Кроме того, у меня была вторая проблема, вызвавшая перетаскивание. Все мои ячейки генерируются из CoreData, за исключением того, что я добавляю одну последнюю ячейку-заполнитель. Это заставило функцию «своп» выйти из строя, поэтому я вложил swap в if-statement, только если индекс indexPath.row меньше, чем число моих элементов CoreData. –

0

Вы не указали, где в коде произошел сбой, что затрудняет определение того, что происходит.Установите контрольную точку на исключениях, чтобы определить, какая строка является виновником. Для этого используйте «+» в нижнем левом углу списка точек останова в XCode.

Основная проблема, я думаю, с indexPath. Есть несколько вопросов:

  1. Вы используете indexPath, хотя это может быть нулевым, в этой строке:

    let currentCell = tableView.cellForRowAtIndexPath(indexPath!) as! CustomTableViewCell; 
    
  2. indexPath может быть недействительным, даже если это не ноль , Проверьте, чтобы его члены секции и строки отличались от NSNotFound.

Наконец, я использовал предварительно сделанный, с открытым исходным кодом, UITableView подкласса, что делает все движущееся для вас, так что вы не должны реализовать его самостоятельно больше. Он также заботится об автопрокрутке, о которой вы даже не подумали. Используйте его напрямую или используйте его в качестве вдохновения для своего кода: https://www.cocoacontrols.com/controls/fmmovetableview

+0

Спасибо, что выбрали некоторые идеи. Я добавил скриншот об аварии. Взгляните на ваши предложения сейчас –

Смежные вопросы