如何防止在拖放 table 视图单元格时将数据附加到现有单元格?
How to prevent appending data to an existing cell on drag drop of table view cell?
我正在拖放 table 视图单元格。但它在单元格顶部显示一个加号图标,如果我放下,文本会被附加。如何防止此加号图标和追加行为并只允许重新排序?
extension CheckListTableViewController: UITableViewDragDelegate {
func tableView(_ tableView: UITableView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
if let item = self.boardMan.getCheckListItem(indexPath: indexPath) {
if let stringData = item.title.data(using: .utf8) {
let itemProvider = NSItemProvider(item: stringData as NSData, typeIdentifier: kUTTypePlainText as String)
let dragItem = UIDragItem(itemProvider: itemProvider)
dragItem.localObject = (item, indexPath, tableView)
return [dragItem]
}
}
return []
}
extension CheckListTableViewController: UITableViewDropDelegate {
func tableView(_ tableView: UITableView, performDropWith coordinator: UITableViewDropCoordinator) {
if coordinator.session.hasItemsConforming(toTypeIdentifiers: [kUTTypePlainText as String]) {
coordinator.session.loadObjects(ofClass: NSString.self) { (items) in
switch (coordinator.items.first?.sourceIndexPath, coordinator.destinationIndexPath) {
case (.some(let sourceIndexPath), .some(let destinationIndexPath)):
Log.debug("src: \(sourceIndexPath) dest: \(destinationIndexPath)")
let updatedIndexPaths: [IndexPath]
if sourceIndexPath.row < destinationIndexPath.row {
updatedIndexPaths = (sourceIndexPath.row...destinationIndexPath.row).map { IndexPath(row: [=12=], section: 0) }
} else if sourceIndexPath.row > destinationIndexPath.row {
updatedIndexPaths = (destinationIndexPath.row...sourceIndexPath.row).map { IndexPath(row: [=12=], section: 0) }
} else {
updatedIndexPaths = []
}
if let checkListItem = self.utils.getCheckListItem(indexPath: sourceIndexPath) {
self.tableView.beginUpdates()
_ = self.utils.removeCheckListItem(indexPath: sourceIndexPath)
_ = self.utils.insertCheckListItem(checkListItem, indexPath: destinationIndexPath)
self.tableView.reloadRows(at: updatedIndexPaths, with: .none)
self.tableView.endUpdates()
}
default:
Log.debug("default case")
}
}
}
}
func tableView(_ tableView: UITableView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UITableViewDropProposal {
if tableView.hasActiveDrag {
return UITableViewDropProposal(operation: .move, intent: .insertAtDestinationIndexPath)
}
return UITableViewDropProposal(operation: .forbidden)
}
}
table 视图设置了拖放委托并添加了滑动手势。
self.tableView.dragDelegate = self
self.tableView.dropDelegate = self
self.tableView.dragInteractionEnabled = true
请看下面的截图。
如果您只想为了重新排序行而支持拖放,则不需要您发布的任何代码。
实现UITableViewDataSource和UITableViewDelegate的正常"reorder"相关方法。设置 table 的 dragDelegate
和 dropDelegate
。您只需要从 UITableViewDragDelegate 和 UITableViewDropDelegate 中分别实现一个方法,它们的实现很简单。
对于简单的单节 table 查看,您只需要以下内容:
override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
return true
}
override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
// Update your data model array to move the item at sourceIndexPath.row to destinationIndexPath.row
}
// MARK: - UITableViewDragDelegate
func tableView(_ tableView: UITableView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
return []
}
// MARK: - UITableViewDropDelegate
func tableView(_ tableView: UITableView, performDropWith coordinator: UITableViewDropCoordinator) {
// no-op
}
确保在 viewDidLoad
或故事板中将 table 视图的 dragDelegate
和 dropDelegate
属性设置为 self
。您还需要打开 dragInteractionEnabled
属性.
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.dragDelegate = self
self.tableView.dropDelegate = self
self.tableView.dragInteractionEnabled = true
}
这就是支持使用拖放进行行重新排序所需的全部内容。当然,对于复杂的数据模型和多个部分,您可能还需要实现 targetIndexPathForMoveFromRowAt
委托方法,您在 moveRowAt
中的逻辑可能需要进一步的逻辑。
有趣的是,只有 iPhone 需要设置 dropDelegate
和启用 dragInteractionEnabled
。 iPad(和 Mac Catalyst)版本不需要这些设置。
我正在拖放 table 视图单元格。但它在单元格顶部显示一个加号图标,如果我放下,文本会被附加。如何防止此加号图标和追加行为并只允许重新排序?
extension CheckListTableViewController: UITableViewDragDelegate {
func tableView(_ tableView: UITableView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
if let item = self.boardMan.getCheckListItem(indexPath: indexPath) {
if let stringData = item.title.data(using: .utf8) {
let itemProvider = NSItemProvider(item: stringData as NSData, typeIdentifier: kUTTypePlainText as String)
let dragItem = UIDragItem(itemProvider: itemProvider)
dragItem.localObject = (item, indexPath, tableView)
return [dragItem]
}
}
return []
}
extension CheckListTableViewController: UITableViewDropDelegate {
func tableView(_ tableView: UITableView, performDropWith coordinator: UITableViewDropCoordinator) {
if coordinator.session.hasItemsConforming(toTypeIdentifiers: [kUTTypePlainText as String]) {
coordinator.session.loadObjects(ofClass: NSString.self) { (items) in
switch (coordinator.items.first?.sourceIndexPath, coordinator.destinationIndexPath) {
case (.some(let sourceIndexPath), .some(let destinationIndexPath)):
Log.debug("src: \(sourceIndexPath) dest: \(destinationIndexPath)")
let updatedIndexPaths: [IndexPath]
if sourceIndexPath.row < destinationIndexPath.row {
updatedIndexPaths = (sourceIndexPath.row...destinationIndexPath.row).map { IndexPath(row: [=12=], section: 0) }
} else if sourceIndexPath.row > destinationIndexPath.row {
updatedIndexPaths = (destinationIndexPath.row...sourceIndexPath.row).map { IndexPath(row: [=12=], section: 0) }
} else {
updatedIndexPaths = []
}
if let checkListItem = self.utils.getCheckListItem(indexPath: sourceIndexPath) {
self.tableView.beginUpdates()
_ = self.utils.removeCheckListItem(indexPath: sourceIndexPath)
_ = self.utils.insertCheckListItem(checkListItem, indexPath: destinationIndexPath)
self.tableView.reloadRows(at: updatedIndexPaths, with: .none)
self.tableView.endUpdates()
}
default:
Log.debug("default case")
}
}
}
}
func tableView(_ tableView: UITableView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UITableViewDropProposal {
if tableView.hasActiveDrag {
return UITableViewDropProposal(operation: .move, intent: .insertAtDestinationIndexPath)
}
return UITableViewDropProposal(operation: .forbidden)
}
}
table 视图设置了拖放委托并添加了滑动手势。
self.tableView.dragDelegate = self
self.tableView.dropDelegate = self
self.tableView.dragInteractionEnabled = true
请看下面的截图。
如果您只想为了重新排序行而支持拖放,则不需要您发布的任何代码。
实现UITableViewDataSource和UITableViewDelegate的正常"reorder"相关方法。设置 table 的 dragDelegate
和 dropDelegate
。您只需要从 UITableViewDragDelegate 和 UITableViewDropDelegate 中分别实现一个方法,它们的实现很简单。
对于简单的单节 table 查看,您只需要以下内容:
override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
return true
}
override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
// Update your data model array to move the item at sourceIndexPath.row to destinationIndexPath.row
}
// MARK: - UITableViewDragDelegate
func tableView(_ tableView: UITableView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
return []
}
// MARK: - UITableViewDropDelegate
func tableView(_ tableView: UITableView, performDropWith coordinator: UITableViewDropCoordinator) {
// no-op
}
确保在 viewDidLoad
或故事板中将 table 视图的 dragDelegate
和 dropDelegate
属性设置为 self
。您还需要打开 dragInteractionEnabled
属性.
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.dragDelegate = self
self.tableView.dropDelegate = self
self.tableView.dragInteractionEnabled = true
}
这就是支持使用拖放进行行重新排序所需的全部内容。当然,对于复杂的数据模型和多个部分,您可能还需要实现 targetIndexPathForMoveFromRowAt
委托方法,您在 moveRowAt
中的逻辑可能需要进一步的逻辑。
有趣的是,只有 iPhone 需要设置 dropDelegate
和启用 dragInteractionEnabled
。 iPad(和 Mac Catalyst)版本不需要这些设置。