【问题标题】:Reordering controls on UITableView while not in editing mode?不在编辑模式下重新排序 UITableView 上的控件?
【发布时间】:2011-08-31 03:31:14
【问题描述】:

我有一个 UITableView,我希望能够在我不处于编辑模式时重新排序行,这意味着我不想看到删除图标,直到我按下编辑。我希望能够一直看到和使用重新排序控件。这可能吗?

我是否必须始终将 UITableView 保持在编辑模式并手动启用/禁用删除图标?在这种情况下如何禁用滑动删除?

【问题讨论】:

  • 为每个单元格设置 UITableViewCellEditingStyle 标志并实现 canMoveRowAtIndexPath 和 canEditRowAtIndexPath UITableViewDataSource 委托方法。不确定您是否必须永久处于编辑模式才能执行此操作。

标签: iphone ios4 uitableview


【解决方案1】:

我不确定这是否适用于顶部的实际编辑控件,但对于始终显示重新排序控件,这似乎效果最好:

override func layoutSubviews() {
    showsReorderControl = true
    super.layoutSubviews()
}

【讨论】:

    【解决方案2】:

    终于可以在 Non-Edit-Mode 中使用 Swipe-To-Delete 显示 Reorder Control,用于由 Core Data NSFetchedResultsController 管理的行在 Xcode 9.3 上的strong>Swift 4.1 像这样:

    class MyTableViewCell: UITableViewCell {
    
        override func setEditing(_ editing: Bool, animated: Bool) {
            super.setEditing(editing, animated: animated)
    
            setupAccessoryView()
        }
    
        func setupAccessoryView() {
            if accessoryView == nil {
                if let reorderCtrl = subviews.first(where: { (subView) -> Bool in
                    subView.description.contains("Reorder")
                }) {
                    accessoryView = reorderCtrl
                }
            }
        }
    }
    
    class MyTableViewController: UITableViewController, NSFetchedResultsControllerDelegate {
    
        var frc: NSFetchedResultsController<MyRow>!
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            do {
                // Setup the NSFetchedResultsController here
                try frc.performFetch()
    
                setEditing(true, animated: false) // Enable for cell reorder control creation on first load
            } catch {
                print(error)
            }
        }
    
        override func viewWillAppear(_ animated: Bool) {
            super.viewWillAppear(animated)
    
            setEditing(false, animated: false)
        }
    
        override func viewDidDisappear(_ animated: Bool) {
            super.viewDidDisappear(animated)
    
            setEditing(true, animated: false) // Enable for cell reorder control creation when managed object is updated or inserted on other view
        }
    
        // MARK: - Table view data source
    
        override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
            // your data source update here for swipe to delete
        }
    
        override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
            // your data source update here for sort property value change
        }
    
    }
    

    【讨论】:

      【解决方案3】:

      我找到了解决方案。 UITableViewCell 拒绝绘制重新排序控件,除非它处于编辑模式。幸运的是,UITableViewCellUITableView 轨道编辑是分开的,而且至关重要的是,UITableView 实际上处理重新排序,而不管它自己的编辑模式如何。我们只需要欺骗单元格来绘制重新排序控件,我们就可以回家了。

      子类UITableViewCell 像这样:

      class ReorderTableViewCell: UITableViewCell {
      
          override var showsReorderControl: Bool {
              get {
                  return true // short-circuit to on
              }
              set { }
          }
      
          override func setEditing(editing: Bool, animated: Bool) {
              if editing == false {
                  return // ignore any attempts to turn it off
              }
      
              super.setEditing(editing, animated: animated)
          }
      
      }
      

      现在只需在要启用重新排序的单元格上设置editing = true。你可以让它以-tableView:canMoveRowAtIndexPath:为条件。

      在您的表格视图数据源中:

      override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
          let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
      
          // Configure the cell...
         :
      
          cell.editing = self.tableView(tableView, canMoveRowAtIndexPath: indexPath) // conditionally enable reordering
      
          return cell
      }
      

      唯一的缺点是这与表格视图allowsMultipleSelectionDuringEditing选项不兼容;编辑控件总是错误地显示。一种解决方法是仅在实际的表格视图编辑期间启用多项选择。

      在您的表格视图控制器中:

      override func setEditing(editing: Bool, animated: Bool) {
          super.setEditing(editing, animated: animated)
      
          self.tableView.allowsMultipleSelectionDuringEditing = editing // enable only during actual editing to avoid cosmetic problem
      }
      

      另外,在-viewDidLoad 或您的故事板中,将allowsMultipleSelectionDuringEditing 的初始值设置为false。

      【讨论】:

      • 天才。为此经历了 10 多个 SO 解决方案,这是唯一可行的。未来的 iOS 版本需要密切关注这一点,但在 iOS 10.1 上运行良好
      • 华丽、简单的解决方案。从 Swift 4.1 开始,cell.editing 现在在 cellForRow 中为 cell.isEditing
      • +1 用于研究。不幸的是,我立即遇到了两个问题。其他带有披露指示符(人字形)的部分变得错位,好像对布局有一些不利的干扰。您还可以松动动画进入/退出编辑模式。通常的论点是,这种令人愉快的黑客行为总是会冒着意想不到的后果,您必须问是否值得在生产稳健性方面进行交易。 (iOS 11)
      • 这在 iOS 13 中不再有效。在 Beta 1 和 Beta 2 上测试
      • iOS 13 有修复吗?
      【解决方案4】:

      重新排序,不删除也不缩进。

      - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
          return YES;
      }
      
      - (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{
          return UITableViewCellEditingStyleNone; 
      }
      
      - (BOOL)tableView:(UITableView *)tableview shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath {
          return NO;
      }
      
      
      - (BOOL)tableView:(UITableView *)tableview canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
          return YES;
      }
      

      参考:Stefan von Chossy here 发布的解决方案@

      【讨论】:

      • 还需要实现moveRowAt:to:否则重排控件不显示。
      【解决方案5】:

      据我所知,您不能仅使用编辑标志来做到这一点。但是,要达到类似的效果并不难。

      拥有自己的布尔值,即deleting。将表格视图单元格设置为cell.showsReorderControl = YES。 然后实现移动单元格所需的所有方法。我认为您正在寻找的代码是。 – tableView:editingStyleForRowAtIndexPath: 如果deleting == YES 返回UITableViewCellEditingStyleDelete 否则返回UITableViewCellEditingStyleNone。 最后,始终设置tableView.editing = YES。如果在更改 deleting bool 之前和之后运行 [tableView beginUpdates][tableView endUpdates] 一切都应该正常。如果这没有意义,请告诉我,我会再试一次。

      【讨论】:

      • 顺便说一句,这将停止滑动删除。
      • 我确实喜欢这个。工作得很好。不过,我并没有使用滑动来删除它。
      • 我已经尝试过,但我仍然需要实现:tableview.editing=YES; 它显示了用于删除的红色按钮.. 我只想重新排序单元格没有任何编辑功能......你可以提供一些示例代码到:abhishekbedi1432@yahoo.com
      • @AbhishekBedi 确保您正在实施 tableView:editingStyleForRowAtIndexPath 并始终返回 UITableViewCellEditingStyleNone
      • @mackross 我在这里有一个类似的问题stackoverflow.com/questions/21902483/…,但我无法实现您的答案。你介意帮助我吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-18
      相关资源
      最近更新 更多