具有破坏性样式的UIContextualAction似乎默认删除行

时间:2017-11-04 00:07:15

标签: uitableview swipe ios11

我看到的问题是,当我在UIContextualAction中创建.destructive true 传递completionHandler时,似乎有删除行的默认操作。

如果您从Xcode的模板创建一个新的Master-Detail应用程序,并在MasterViewController ...

中添加此代码
override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
    let testAction = UIContextualAction(style: .destructive, title: "Test") { (_, _, completionHandler) in
        print("test")
        completionHandler(true)
    }
    return UISwipeActionsConfiguration(actions: [testAction])
}

您要滑动的行将被删除。请注意,没有代码更新表视图。此外,模型不会更新,如果向上滚动导致重新加载行,它将重新出现。

在这种情况下传递false不会删除该行。或者使用.normal样式和true也不会删除该行。

.destructivetrue会导致默认情况下删除该行。

任何人都可以解释这种行为吗?为什么要删除行?

4 个答案:

答案 0 :(得分:6)

根据破坏性选项的文档:

  

删除数据或执行某种类型的破坏性任务的操作。

完成意味着表明行动是否成功。传递真实意味着破坏性任务是成功的,因此应删除该行。

您需要在发生破坏性操作时手动更新dataSource,否则会导致滚动以重新显示数据。您还需要告诉tableView数据已被删除。

以下是一些显示工作示例的代码:

UIContextualAction(style: .destructive, title: "Delete") { [weak self] (_, _, completion) in
    if self?.canDelete(indexPath) { // We can actually delete
        // remove the object from the data source
        self?.myData.remove(at: indexPath.row)
        // delete the row.  Without deleting the row or reloading the
        // tableview, the index will be off in future swipes
        self?.tableView?.deleteRows(at: [indexPath], with: .none)
        // Let the action know it was a success.  In this case the 
        // tableview will animate the cell removal with the swipe
        completion(true)    
    } else { // We can't delete for some reason
        // This resets the swipe state and nothing is removed from
        // the screen visually.
        completion(false)
    }         
}

然后我需要重新加载tableview或致电deleteRows,以便在下次滑动时正确计算indexPath

如果我有10行并且我将第5行刷到要删除,那么除非重新加载tableview或者tableview被告知要删除的行,否则之后的每一行都将关闭一行以某种方式。

答案 1 :(得分:2)

我无法在iOS 13中重现此问题。要么是iOS 12及更低版本中的行为是一个错误,要么只是被撤消了(也许是因为它令人困惑)。

在iOS 13中,如果您只是通过调用.destructivecompletion(true)操作中返回而没有做任何事情,那么什么也没发生,这就是结束的事情。不会为您删除该单元格。

答案 2 :(得分:0)

我同意Kris Gellci的回答,但是请注意,如果您使用的是 NSFetchedResultsController ,可能会使事情复杂化。似乎对于破坏性的UIContextualAction,调用completion(true)将删除该行,但NSFetchedResultsController的委托也可能删除。因此,您很容易以这种方式导致错误。我决定使用NSFetchedResultsController调用completion(false)(使上下文菜单关闭),而不管该操作是否成功,然后让委托负责如果删除了相应的对象,则删除表行。

答案 3 :(得分:-1)

使用以下标志禁用完全滑动。

<块引用>

执行FirstActionWithFullSwipe

默认情况下,它会自动执行在 UISwipeActionsConfiguration 中配置的第一个操作。因此,如果您想禁用完全滑动删除,请将“performsFirstActionWithFullSwipe”设置为 false。

func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
    let test = UIContextualAction(style: .destructive, title: "test") { (action, view, completion) in
        
        // Your Logic here
        completion(true)
    }
    
    let config = UISwipeActionsConfiguration(actions: [test])
    config.performsFirstActionWithFullSwipe = false
    return config
} 

希望这能解决您的问题。