ХорошийUITableView Drag & падение Outside Таблица = Краш
Моя перетащить & функция падение почти замечательно работает. I longPress cell, и он плавно позволяет мне переместить нажатую ячейку в новое место между двумя другими ячейками. Таблица настраивается и изменения сохраняются в основных данных. Большой!
Плохой
Моя проблема заключается в том, что если я перетащить ячейку ниже нижней ячейки в таблице, даже если я не отпускаю (ООН-пресс) ячейки ... приложение сбои. Если я медленно перетаскиваю, на самом деле он падает, когда ячейка пересекает y-центр последней ячейки ... поэтому я думаю, что это проблема, связанная с моментальным снимком, получающим местоположение. Менее важным, но, возможно, и связанным, является то, что если я долгое время поджимаю последнюю ячейку со значением в ней, она также падает.
Сопротивления/падение сбегает с заявлением переключателя, который работает один из трех наборов коды на основе статуса:
- Один случая, когда пресса начинает
- Один случая, когда клетка тащит
- Один случай, когда, когда пользователь отпускает клетки
Мой код адаптировано из этого урока:
Мой код:
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, которое делает что-то магическое, когда нет ячейки для ссылки на местоположение. Но что!?! По какой-то причине добавление нуля для каждого случая не работает.
Ясно Заявлен Вопрос
Как избежать аварий и обработки событий, где моя тащили ячейка тащила ниже последнюю ячейку?
Скриншот аварии:
Возможно, он попадает в «индекс массива за пределами границ», думая, что ячейка каким-то образом помещается в позицию в виде таблицы, которая понадобится добавить новый элемент в массив tableview, который невозможен, поэтому система get разозлилась и выйдет из строя, какова ошибка, говорящая конкретно? – Loxx
@ Larcerax Ha! Ну, я думаю, ты на правильном пути. Он выдает код EXC: Bad Instructions. Консоль читает: «фатальная ошибка: индекс массива вне диапазона (lldb)». Любая идея, как сделать это поведение пользователя безопасным и не вызвать сбой? –
да, поэтому перед событием или всегда, когда вы перетаскиваете ячейку, вам может понадобиться какое-то, как выкидывать икоту, например, повторное обновление или отправку, получать событие главной очереди или отправлять после времени бла-бла, дать короткое прерывание. Если вы можете принудительно добавить ячейку вправо при перетаскивании, то вы в порядке, то эта ячейка будет удалена, ячейка woudl будет скрытой ячейкой, но это очень грязно – Loxx