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:

几点观察:

  1. 如果您不实施 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)
    }
    
  2. trailingSwipeActionsConfigurationForRowAt 可能不是放置“重新排序”命令的正确位置。部分原因是一旦 table 视图处于编辑模式并且您点击 ⛔️,就会显示尾随操作,并且“重新排序”在该上下文中没有意义。例如,我在这里点击 ⛔️,我看到了令人困惑的操作。

    我建议只添加“删除”作为尾随操作。这样,如果您在 isEditing 模式下点击 ⛔️,您 (a) 只会获得“删除”,而且 (b) 也会获得 stand-alone 滑动操作。

  3. 您不能从拖尾的滑动动作中启动 isEditing(而且,如上所述,无论如何,我认为您不想这样做)。因此,如果您在尾部滑动操作中没有“重新排序”,则需要一些其他方法来进入编辑模式。例如,在上面,我在导航栏中添加了一个“编辑”按钮,用于切换 isEditing:

    @IBAction func didTapEdit(_ sender: Any) {
        tableView.isEditing.toggle()
    }
    

    然后,您可以保留滑动删除功能,但是当您点击编辑按钮时,您可以点击 ⛔️ 删除功能(加上重新排序的句柄,因为我们添加了 tableView(_:moveRowAt:to:),如第一步,上面):

  4. 实现重新排序的另一种方法是只允许在 table 视图中拖放,您可以在其中 long-press 一行然后拖动它:

    这是通过设置 dragInteractionEnableddropDelegate:

    启用的
    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 一致性,并使您的模型对象符合 NSItemProviderReadingNSItemProviderWriting。但以上内容应该足以在 UITableView.

    内拖放以重新排序