Swift - Movable rows in tableView only within a section, not between

余生长醉 提交于 2020-07-22 00:41:21

问题


Is there a way to prevent cells in a tableView from being moved to a different section?

The sections have data for different types of cells, so the app crashes when the user tries to drag a cell into a different section.

I would like to only allow the user to move a cell inside the section, and not in between sections.

Relevant code is below:

override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
    return true
}

override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
    let reorderedRow = self.sections[sourceIndexPath.section].rows.remove(at: sourceIndexPath.row)
    self.sections[destinationIndexPath.section].rows.insert(reorderedRow, at: destinationIndexPath.row)

    self.sortedSections.insert(sourceIndexPath.section)
    self.sortedSections.insert(destinationIndexPath.section)
}

回答1:


You will need to implement the UITableViewDelegate method targetIndexPathForMoveFromRowAt.

Your strategy will be to allow the move if the source and destination section are the same. If they aren't then you can return either row 0, if the proposed destination section is less than the source section or the last row of the section if the proposed destination section is greater than the source section.

This will constrain the move to the source section.

override func tableview(_ tableView: UITableView, targetIndexPathForMoveFromRowAt sourceIndexPath: IndexPath, toProposedIndexPath proposedDestinationIndexPath: IndexPath) -> IndexPath {

    let sourceSection = sourceIndexPath.section
    let destSection = proposedDestinationIndexPath.section

    if destSection < sourceSection {
        return IndexPath(row: 0, section: sourceSection)
    } else if destSection > sourceSection {
        return IndexPath(row: self.tableView(tableView, numberOfRowsInSection:sourceSection)-1, section: sourceSection)
    }

    return proposedDestinationIndexPath
}



回答2:


You can retarget the proposed destination for restriction by implementing the tableView:targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath: method

  func tableView(_ tableView: UITableView, targetIndexPathForMoveFromRowAt sourceIndexPath: IndexPath, toProposedIndexPath proposedDestinationIndexPath: IndexPath) -> IndexPath {

    // Finds number of items in source group
    let numberOfItems = self.tableView(tableView, numberOfRowsInSection: sourceIndexPath.section)

    // Restricts rows to relocation in their own group by checking source and destination sections
    if (sourceIndexPath.section != proposedDestinationIndexPath.section) {

      /*
       if we move the row to the not allowed upper area, it is moved to the top of the allowed group and vice versa
       if we move the row to the not allowed lower area, it is moved to the bottom of the allowed group
       also prevents moves to the last row of a group (which is reserved for the add-item placeholder).
      */
      let rowInSourceSection = (sourceIndexPath.section > proposedDestinationIndexPath.section) ? 0 : numberOfItems - 1;

      return IndexPath(row: rowInSourceSection, section: sourceIndexPath.section)
    }
    // Prevents moves to the last row of a group (which is reserved for the add-item placeholder).
    else if (proposedDestinationIndexPath.row >= numberOfItems) {

      return IndexPath(row: numberOfItems - 1, section: sourceIndexPath.section)
    }
    // Passing all restrictions
    return proposedDestinationIndexPath
  }


来源:https://stackoverflow.com/questions/52242913/swift-movable-rows-in-tableview-only-within-a-section-not-between

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!