好
我的拖累和掉落功能几乎可以很好地工作。我长按一个单元格,它顺利地允许我将按下的单元格移动到另外两个单元格之间的新位置。表格进行调整,更改保存到核心数据。太好了!
错误
我的问题是,如果我将单元格拖到桌子底部单元格下方,即使我不放手(取消按下)单元格...应用程序崩溃。如果我慢慢拖动,当细胞穿过最后一个细胞的y中心时真的会崩溃......所以我认为这是一个与获取位置的快照相关的问题。不太重要但可能相关的是,如果我长时间按下最后一个单元格下面的值,它也会崩溃。
拖放运行一个switch语句,该语句根据状态运行三组代码之一:
我的代码改编自本教程:
我的代码:
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语句,当没有单元格引用某个位置时,它会做一些神奇的事情。但是什么!?!为每种情况添加零检查由于某种原因不起作用。
明确陈述的问题
如何避免崩溃并处理将拖动的单元格拖到最后一个单元格下方的事件?
崩溃的屏幕截图:
答案 0 :(得分:3)
丑陋
您似乎只需要进行先发制人检查,以确保indexPath
不是零:
var indexPath = tableView.indexPathForRowAtPoint(locationInView)
if (indexPath != nil) {
//Move your code to this block
}
希望有所帮助!
答案 1 :(得分:0)
您没有说明崩溃发生在代码中的哪个位置,这使得确定发生的事情变得更加困难。在异常上设置断点以确定哪条线是罪魁祸首。为此,请使用XCode中断点列表左下角的“+”。
我认为主要问题是indexPath。有几个问题:
你正在使用indexPath,即使它可能是nil,在这一行:
let currentCell = tableView.cellForRowAtIndexPath(indexPath!) as! CustomTableViewCell;
indexPath可能无效,即使它不是nil。检查其部分和行成员是否与NSNotFound不同。
最后,我一直在使用一个预先制作的开源UITableView子类,它可以为您完成所有动作,因此您不必再自己实现它了。它还负责自动滚动,你还没有考虑过它。直接使用它,或将其用作代码的灵感: https://www.cocoacontrols.com/controls/fmmovetableview