UITableView 不显示重新排序控件
UITableView Not Showing Reorder Controls
When I use trailingSwipeActionsConfigurationForRowAt
my TableView will show the delete and reorder options, however when selecting reorder
nothing happens.我认为我拥有所有正确的方法并正在调用 setEditing
;还有什么我想念的吗?谢谢!
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
let tableView = UITableView()
override func viewDidLoad() {
super.viewDidLoad()
setupTableView()
}
func setupTableView() {
tableView.frame = self.view.frame
tableView.dataSource = self
tableView.delegate = self
tableView.register(CustomCell.self, forCellReuseIdentifier: "CustomCell")
tableView.dragInteractionEnabled = true
self.view.addSubview(tableView)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 8
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomCell
cell.backgroundColor = .gray
cell.showsReorderControl = true
return cell
}
override func setEditing(_ editing: Bool, animated: Bool) {
super.setEditing(editing, animated: animated)
self.tableView.setEditing(editing, animated: animated)
}
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let deleteAction = UIContextualAction(style: .normal, title: "delete") { (action, view, completion) in
tableView.reloadData()
completion(true)
}
let reorderAction = UIContextualAction(style: .normal, title: "reorder") { (action, view, completion) in
tableView.setEditing(true, animated: true)
completion(true)
}
return UISwipeActionsConfiguration(actions: [deleteAction, reorderAction])
}
}
class CustomCell: UITableViewCell {
}
刷卡结果:
选择后reorder
:
几点观察:
如果您不实施 tableView(_:moveRowAt:to:)
,您将不会获得重新排序控件,例如,假设您有一个名为 objects
的数组模型,您可以执行以下操作:
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
let object = objects.remove(at: sourceIndexPath.row)
objects.insert(object, at: destinationIndexPath.row)
}
trailingSwipeActionsConfigurationForRowAt
可能不是放置“重新排序”命令的正确位置。部分原因是一旦 table 视图处于编辑模式并且您点击 ⛔️,就会显示尾随操作,并且“重新排序”在该上下文中没有意义。例如,我在这里点击 ⛔️,我看到了令人困惑的操作。
我建议只添加“删除”作为尾随操作。这样,如果您在 isEditing
模式下点击 ⛔️,您 (a) 只会获得“删除”,而且 (b) 也会获得 stand-alone 滑动操作。
您不能从拖尾的滑动动作中启动 isEditing
(而且,如上所述,无论如何,我认为您不想这样做)。因此,如果您在尾部滑动操作中没有“重新排序”,则需要一些其他方法来进入编辑模式。例如,在上面,我在导航栏中添加了一个“编辑”按钮,用于切换 isEditing
:
@IBAction func didTapEdit(_ sender: Any) {
tableView.isEditing.toggle()
}
然后,您可以保留滑动删除功能,但是当您点击编辑按钮时,您可以点击 ⛔️ 删除功能(加上重新排序的句柄,因为我们添加了 tableView(_:moveRowAt:to:)
,如第一步,上面):
实现重新排序的另一种方法是只允许在 table 视图中拖放,您可以在其中 long-press 一行然后拖动它:
这是通过设置 dragInteractionEnabled
和 dropDelegate
:
启用的
class ViewController: UIViewController {
@IBOutlet weak var tableView: UITableView!
let formatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.numberStyle = .spellOut
return formatter
}()
private var objects: [Foo] = ...
override func viewDidLoad() {
super.viewDidLoad()
...
tableView.dragInteractionEnabled = true
tableView.dropDelegate = self
}
}
// MARK: - UITableViewDataSource
extension ViewController: UITableViewDataSource { ... }
// MARK: - UITableViewDelegate
extension ViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let deleteAction = UIContextualAction(style: .destructive, title: "delete") { [weak self] action, view, completion in
self?.objects.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .middle)
completion(true)
}
return UISwipeActionsConfiguration(actions: [deleteAction])
}
// This is used if table view is in `isEditing` mode and by `UITableViewDropDelegate`
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
let object = objects.remove(at: sourceIndexPath.row)
objects.insert(object, at: destinationIndexPath.row)
}
}
// MARK: - UITableViewDropDelegate
extension ViewController: UITableViewDropDelegate {
func tableView(_ tableView: UITableView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UITableViewDropProposal {
guard
session.items.count == 1, // Accept only one drag item ...
tableView.hasActiveDrag // ... from within this table view
else {
return UITableViewDropProposal(operation: .cancel)
}
return UITableViewDropProposal(operation: .move, intent: .insertAtDestinationIndexPath)
}
func tableView(_ tableView: UITableView, performDropWith coordinator: UITableViewDropCoordinator) {
guard let destinationIndexPath = coordinator.destinationIndexPath else { return }
for item in coordinator.items {
if let sourceIndexPath = item.sourceIndexPath {
DispatchQueue.main.async {
tableView.moveRow(at: sourceIndexPath, to: destinationIndexPath)
}
}
}
}
}
显然,如果您要启用从这个应用程序到其他应用程序的拖动,您需要在此处添加 UITableViewDragDelegate
一致性,并使您的模型对象符合 NSItemProviderReading
和 NSItemProviderWriting
。但以上内容应该足以在 UITableView
.
内拖放以重新排序
When I use trailingSwipeActionsConfigurationForRowAt
my TableView will show the delete and reorder options, however when selecting reorder
nothing happens.我认为我拥有所有正确的方法并正在调用 setEditing
;还有什么我想念的吗?谢谢!
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
let tableView = UITableView()
override func viewDidLoad() {
super.viewDidLoad()
setupTableView()
}
func setupTableView() {
tableView.frame = self.view.frame
tableView.dataSource = self
tableView.delegate = self
tableView.register(CustomCell.self, forCellReuseIdentifier: "CustomCell")
tableView.dragInteractionEnabled = true
self.view.addSubview(tableView)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 8
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomCell
cell.backgroundColor = .gray
cell.showsReorderControl = true
return cell
}
override func setEditing(_ editing: Bool, animated: Bool) {
super.setEditing(editing, animated: animated)
self.tableView.setEditing(editing, animated: animated)
}
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let deleteAction = UIContextualAction(style: .normal, title: "delete") { (action, view, completion) in
tableView.reloadData()
completion(true)
}
let reorderAction = UIContextualAction(style: .normal, title: "reorder") { (action, view, completion) in
tableView.setEditing(true, animated: true)
completion(true)
}
return UISwipeActionsConfiguration(actions: [deleteAction, reorderAction])
}
}
class CustomCell: UITableViewCell {
}
刷卡结果:
选择后reorder
:
几点观察:
如果您不实施
tableView(_:moveRowAt:to:)
,您将不会获得重新排序控件,例如,假设您有一个名为objects
的数组模型,您可以执行以下操作:func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) { let object = objects.remove(at: sourceIndexPath.row) objects.insert(object, at: destinationIndexPath.row) }
trailingSwipeActionsConfigurationForRowAt
可能不是放置“重新排序”命令的正确位置。部分原因是一旦 table 视图处于编辑模式并且您点击 ⛔️,就会显示尾随操作,并且“重新排序”在该上下文中没有意义。例如,我在这里点击 ⛔️,我看到了令人困惑的操作。我建议只添加“删除”作为尾随操作。这样,如果您在
isEditing
模式下点击 ⛔️,您 (a) 只会获得“删除”,而且 (b) 也会获得 stand-alone 滑动操作。您不能从拖尾的滑动动作中启动
isEditing
(而且,如上所述,无论如何,我认为您不想这样做)。因此,如果您在尾部滑动操作中没有“重新排序”,则需要一些其他方法来进入编辑模式。例如,在上面,我在导航栏中添加了一个“编辑”按钮,用于切换isEditing
:@IBAction func didTapEdit(_ sender: Any) { tableView.isEditing.toggle() }
然后,您可以保留滑动删除功能,但是当您点击编辑按钮时,您可以点击 ⛔️ 删除功能(加上重新排序的句柄,因为我们添加了
tableView(_:moveRowAt:to:)
,如第一步,上面):实现重新排序的另一种方法是只允许在 table 视图中拖放,您可以在其中 long-press 一行然后拖动它:
这是通过设置
启用的dragInteractionEnabled
和dropDelegate
:class ViewController: UIViewController { @IBOutlet weak var tableView: UITableView! let formatter: NumberFormatter = { let formatter = NumberFormatter() formatter.numberStyle = .spellOut return formatter }() private var objects: [Foo] = ... override func viewDidLoad() { super.viewDidLoad() ... tableView.dragInteractionEnabled = true tableView.dropDelegate = self } } // MARK: - UITableViewDataSource extension ViewController: UITableViewDataSource { ... } // MARK: - UITableViewDelegate extension ViewController: UITableViewDelegate { func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? { let deleteAction = UIContextualAction(style: .destructive, title: "delete") { [weak self] action, view, completion in self?.objects.remove(at: indexPath.row) tableView.deleteRows(at: [indexPath], with: .middle) completion(true) } return UISwipeActionsConfiguration(actions: [deleteAction]) } // This is used if table view is in `isEditing` mode and by `UITableViewDropDelegate` func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) { let object = objects.remove(at: sourceIndexPath.row) objects.insert(object, at: destinationIndexPath.row) } } // MARK: - UITableViewDropDelegate extension ViewController: UITableViewDropDelegate { func tableView(_ tableView: UITableView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UITableViewDropProposal { guard session.items.count == 1, // Accept only one drag item ... tableView.hasActiveDrag // ... from within this table view else { return UITableViewDropProposal(operation: .cancel) } return UITableViewDropProposal(operation: .move, intent: .insertAtDestinationIndexPath) } func tableView(_ tableView: UITableView, performDropWith coordinator: UITableViewDropCoordinator) { guard let destinationIndexPath = coordinator.destinationIndexPath else { return } for item in coordinator.items { if let sourceIndexPath = item.sourceIndexPath { DispatchQueue.main.async { tableView.moveRow(at: sourceIndexPath, to: destinationIndexPath) } } } } }
显然,如果您要启用从这个应用程序到其他应用程序的拖动,您需要在此处添加
内拖放以重新排序UITableViewDragDelegate
一致性,并使您的模型对象符合NSItemProviderReading
和NSItemProviderWriting
。但以上内容应该足以在UITableView
.