用动画删除UITableViewCell(错误/崩溃)

时间:2015-03-29 15:56:29

标签: ios uitableview swift core-data

我想删除UITableViewCell&带有动画的UITableView的CoreData对象。我写了这段代码:

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

    let mySelectedCell:UITableViewCell = tableView.cellForRowAtIndexPath(indexPath)!

    //1
    let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate

    let managedContext = appDelegate.managedObjectContext!

    //2
    let fetchRequest = NSFetchRequest(entityName:"Person")

    //3
    mySelectedCell.backgroundColor = green
    mySelectedCell.detailTextLabel?.text = "Done"
    mySelectedCell.accessoryType = UITableViewCellAccessoryType.Checkmark        

    let person = people[indexPath.row]
    managedContext.deleteObject(person)
    self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Right)
}

我不知道为什么但是如果我选择了一个我要删除的单元格,应用程序就会崩溃。

2015-03-29 18:00:10.776 MyApp[3001:79507] *** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-3318.93/UITableView.m:1582

崩溃线:self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Right)

有人知道我做错了吗?

更新

tableView.beginUpdates()

var numberItems:Int = people.count

self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Right)
numberItems -= [indexPath].count // something like [indexPath].count

tableView.endUpdates()


func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    application.applicationIconBadgeNumber = people.count
    return people.count
}
  

新错误:

2015-03-29 19:14:15.972 MyApp[3389:89566] *** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-3318.93/UITableView.m:1582

在这行代码中:tableView.endUpdates()

3 个答案:

答案 0 :(得分:1)

您必须以下列方式将方法deleteRowsAtIndexPaths置于这两种方法中:

var path = [NSIndexPath]()

// This is only a example with the index [0..numberOfItemsToDelete-1]
for (var i = 0; i < numberOfItemsToDelete; i++) {
    path.append(NSIndexPath(forRow: i, inSection: 0))
}

tableView.beginUpdates()    

self.tableView.deleteRowsAtIndexPaths(path, withRowAnimation: .Right)
self.numberOfItems -= theNumberYouDeletedAbove // something like [indexPath].count

tableView.endUpdates()

当然,您必须更新numberOfRowsInSection方法,因为它会引发运行时错误,您可以执行以下操作:

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {       
    return numberOfItems
}

numberOfItems匹配用于显示项目的数组大小。

我希望这对你有所帮助。

答案 1 :(得分:0)

如果表格视图使用fetched results controller显示核心数据对象,那么唯一的东西 要删除对象,就是从托管对象上下文中删除该对象:

let context = self.fetchedResultsController.managedObjectContext
context.deleteObject(self.fetchedResultsController.objectAtIndexPath(indexPath) as NSManagedObject)

当然保存上下文以使更改永久化。

然后更新表格视图&#34;自动&#34;通过 获取结果控制器委托方法

func controllerWillChangeContent(controller: NSFetchedResultsController)
func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType)
func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?)
func controllerDidChangeContent(controller: NSFetchedResultsController)

您将在中找到这些方法的典型实现 NSFetchedResultsControllerDelegate文档,如果您还没有 已经实施了它们。

此外,你不应该有#34;副本&#34;您所获取的对象的数量 people数组。直接使用获取的结果控制器 在表视图中的数据源方法,例如:

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return self.fetchedResultsController.sections?.count ?? 0
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    let sectionInfo = self.fetchedResultsController.sections![section] as NSFetchedResultsSectionInfo
    return sectionInfo.numberOfObjects
}

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
    self.configureCell(cell, atIndexPath: indexPath)
    return cell
}

如果您创建一个全新的&#34; Master-Detail +核心数据应用程序&#34;在Xcode中 然后,您将获得所需的所有必要模板代码。

答案 2 :(得分:0)

首先,删除此行尝试复制并导致managedContext作业导致崩溃。

self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Right)

SECOND,现在您应该能够在没有崩溃和没有动画的情况下删除。

THIRD,让NSFetchedResultsController使用“didChange”处理程序删除并触发动画。

func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, 
    didChange anObject: Any, 
    at indexPath: IndexPath?, 
    for type: NSFetchedResultsChangeType, 
    newIndexPath: IndexPath?) 
    {
       print(indexPath)
       if type == .delete{
           tableView.deleteRows(at: [indexPath!], with: .automatic)
    }
}

func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
    tableView.endUpdates()
    //0.4 sec delay before refreshing the table
    DispatchQueue.main.asyncAfter(wallDeadline: .now() + 0.4) {
        self.refresh()
    }
}
func refresh(){
    tableView.reloadData() 
}

如果你不能在SECOND步骤中删除; 检查,如果您已实施:

NSFetchedResultsControllerDelegate

在类定义中并在类中设置委托,例如。

yourResultsController.delegate = self