uitaiteView不显示重新订购控件

发布于 2025-01-20 15:54:29 字数 2375 浏览 1 评论 0原文

当我使用trailwipeactionsconfigurationforrowat时,我的tableview将显示删除和重新排序选项,但是选择重新排序时,什么也不会发生。我认为我有所有正确的方法,并且正在调用设置;我还有其他缺少的吗?谢谢!

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 {
 
}

滑动后的结果:

“在此处输入图像描述”

选择重新排序

< img src =“ https://i.sstatic.net/zgfowl.png” alt =“在此处输入图像说明”>

When I use trailingSwipeActionsConfigurationForRowAt my TableView will show the delete and reorder options, however when selecting reorder nothing happens. I think I have all of the correct methods and am calling setEditing; is there anything else I'm missing? Thanks!

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 {
 
}

Result after swiping:

enter image description here

After selecting reorder:

enter image description here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

笑脸一如从前 2025-01-27 15:54:29

一些观察:

  1. 如果您不实现tableView(_:moveRowAt:to:),您将不会获得重新排序控件,例如,假设您有一个模型,它是一个名为对象,您可以执行以下操作:

    func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
        让对象=对象.删除(在:sourceIndexPath.row)
        对象.插入(对象,位于:destinationIndexPath.row)
    }
    
  2. trailingSwipeActionsConfigurationForRowAt 可能不是放置“重新排序”命令的正确位置。部分原因是,一旦表格视图处于编辑模式并且您点击 ⛔️,就会显示尾随操作,并且“重新排序”在这种情况下没有意义。例如,在这里我点击 ⛔️,我看到了令人困惑的操作。

    “在此处输入图像描述"

    我建议仅添加“删除”作为尾随操作。这样,您 (a) 在 isEditing 模式下点击 ⛔️ 时只能获得“删除”,而且 (b) 也可以获得独立的滑动操作。

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

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

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

    “在此处输入图像描述"

  4. 实现重新排序的另一种方法是只允许在表格视图中进行拖放,您可以在其中长按一行然后拖动它:

    “在此处输入图像描述"

    通过设置 dragInteractionEnableddropDelegate 启用此功能:

    类 ViewController: UIViewController {
        @IBOutlet 弱var tableView:UITableView!
    
        让格式化程序:NumberFormatter = {
            让格式化程序 = NumberFormatter()
            formatter.numberStyle = .spellOut
            返回格式化程序
        }()
    
        私有变量对象: [Foo] = ...
    
        覆盖 func viewDidLoad() {
            super.viewDidLoad()
    
            ...
    
            tableView.dragInteractionEnabled = true
            tableView.dropDelegate = 自身
        }
    }
    
    // 标记:- UITableViewDataSource
    
    扩展 ViewController: UITableViewDataSource { ... }
    
    // 标记:- UITableViewDelegate
    
    扩展 ViewController: UITableViewDelegate {
        func tableView(_ tableView: UITableView, TrailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActions 配置? {
            让deleteAction = UIContextualAction(style: .destroy, title: "delete") { [weak self] 动作、视图、完成
                self?.objects.remove(at:indexPath.row)
                tableView.deleteRows(位于:[indexPath],带有:.middle)
                完成(真)
            }
    
            返回 UISwipeActionsConfiguration(操作:[deleteAction])
        }
    
        // 如果表视图处于“isEditing”模式并且由“UITableViewDropDelegate”使用,则使用此方法
    
        func tableView(_ tableView:UITableView,moveRowAt sourceIndexPath:IndexPath,到destinationIndexPath:IndexPath){
            让对象=对象.删除(在:sourceIndexPath.row)
            对象.插入(对象,位于:destinationIndexPath.row)
        }
    }
    
    // 标记:- UITableViewDropDelegate
    
    扩展 ViewController: UITableViewDropDelegate {
        func tableView(_ tableView: UITableView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UITableViewDropProposal {
            警卫
                session.items.count == 1, // 只接受一个拖动项 ...
                tableView.hasActiveDrag // ...从此表视图中
            别的 {
                返回 UITableViewDropProposal(操作:.cancel)
            }
    
            返回 UITableViewDropProposal(操作:.move,意图:.insertAtDestinationIndexPath)
        }
    
        func tableView(_ tableView: UITableView, PerformDropWith 协调器: UITableViewDropCoordinator) {
            Guard 让destinationIndexPath = coordinator.destinationIndexPath else { return }
    
            对于 coordinator.items 中的项目 {
                如果让 sourceIndexPath = item.sourceIndexPath {
                    DispatchQueue.main.async {
                        tableView.moveRow(在:sourceIndexPath,到:destinationIndexPath)
                    }
                }
            }
        }
    }
    

    显然,如果您要启用从此应用程序到其他应用程序的拖动功能,则需要在此处添加 UITableViewDragDelegate 一致性,并使您的模型对象符合 NSItemProviderReading>NSItemProviderWriting。但以上内容应该足以在 UITableView 中进行拖放重新排序。

A few observations:

  1. You are not going to get the reorder controls if you do not implement tableView(_:moveRowAt:to:), e.g., assuming you had a model which was an array called objects, you could do the following:

    func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
        let object = objects.remove(at: sourceIndexPath.row)
        objects.insert(object, at: destinationIndexPath.row)
    }
    
  2. The trailingSwipeActionsConfigurationForRowAt is probably not the right place to put a “reorder” command. Part of the reason is that once the table view is in edit mode and you tap on the ⛔️, the trailing actions show up, and “reorder” does not make sense in that context. E.g., here I am tapping on ⛔️ and I see the confusing actions.

    enter image description here

    I would suggest only adding “delete” as the trailing action. That way, you (a) get only “delete” if you tap on ⛔️ in isEditing mode, but also (b) get the stand-alone swipe action, too.

  3. You cannot initiate isEditing from the trailing swipe actions (and, as discussed above, I do not think you want to, anyway). So, if you do not have “reorder” in the trailing swipe actions, you need some other method to enter edit mode. E.g., above, I added an “edit” button to the navigation bar that toggles isEditing:

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

    Then, you can keep the swipe to delete functionality, but when you tap on edit button, you have the tap on ⛔️ to delete functionality (plus the handles for reordering because we added tableView(_:moveRowAt:to:) as outlined in step one, above):

    enter image description here

  4. Another way to achieve reordering is to just allow drag and drop within the table view where you can long-press on a row and then drag it:

    enter image description here

    This is enabled by setting dragInteractionEnabled and 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)
                    }
                }
            }
        }
    }
    

    Clearly, if you were going to enable drag from this app to others, you would add UITableViewDragDelegate conformance here, and make your model objects conform to NSItemProviderReading and NSItemProviderWriting. But the above should be sufficient for dragging and dropping to reorder within a UITableView.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文