UITableView Drag&跌倒桌面=崩溃 [英] UITableView Drag & Drop Outside Table = Crash
问题描述
好
我的拖放掉落功能几乎可以奇妙地工作。我长按一个单元格,它顺利地允许我将压制单元移动到另外两个单元格之间的新位置。表调整,更改保存到核心数据。很好!
坏
我的问题是,如果我拖动单元格在桌子下面的单元格下方,即使我不放开(un-press)的单元格...应用程序崩溃。如果我慢慢拖动,真的会崩溃,因为单元格穿过最后一个单元格的y中心...所以我认为这是一个与获取位置的快照相关的问题。不太重要但可能相关的是,如果我长时间按下最后一个单元格的值,它也会崩溃。
拖放运行一个开关根据状态运行三组代码之一的语句:
- 新闻开始时有一种情况
- 单元格被拖动时的一种情况
- 当用户放弃单元格时,有一种情况
我的代码改编自本教程:
p> 丑陋
似乎您只需要先行检查,以确保您的 indexPath
不是nil:
var indexPath = tableView.indexPathForRowAtPoint(locationInView)
if(indexPath! = nil){
//将代码移动到此块
}
希望有帮助!
The Good
My drag & drop function almost works wonderfully. I longPress a cell and it smoothly allows me to move the pressed cell to a new location between two other cells. The table adjusts and the changes save to core data. Great!
The Bad
My problem is that if I drag the cell below the bottom cell in the table, even if I don't let go (un-press) of the cell... the app crashes. If I do the drag slowly, really it crashes as the cell crosses the y-center of the last cell... so I do think it's a problem related to the snapshot getting a location. Less important, but possibly related, is that if I long press below the last cell with a value in it, it also crashes.
The drag/drop runs off a switch statement that runs one of three sets of code based on the status:
- One case when the press begins
- One case when the cell is being dragged
- One case when when the user lets go of the cell
My code is adapted from this tutorial:
My code:
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
Potential Culprit
My guess is that the issue is related to the cell being unable to get coordinates once it is below the last cell. It isn't really floating, it is constantly setting its location in relation to the other cells. I think the solution will be an if-statement that does something magical when there's no cell to reference for a location. But what!?! Adding a nil check to each case isn't working for some reason.
Clearly Stated Question
How do I avoid crashes and handle an event where my dragged cell is dragged below the last cell?
Screenshot of crash:
The Ugly
It seems that you simply need to do a preemptive check, to ensure your indexPath
is not nil:
var indexPath = tableView.indexPathForRowAtPoint(locationInView)
if (indexPath != nil) {
//Move your code to this block
}
Hope that helps!
这篇关于UITableView Drag&跌倒桌面=崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!