2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[Swift]UITableViewでDrag&Dropする際の注意点

Posted at

はじめに

UITableViewでロングタップを使って並び替えをする際に、
上手く実装できずに時間を浪費してしまったので、参考になる方がいれば嬉しいです。

完成イメージ

UITableViewCellをロングタップするとDrag&Dropで並び替えができるようになります。
RocketSim Recording - iPhone 12 Pro Max - 2020-12-06 19.58.14.gif

基本的な実装方法

詳しい実装方法自体は検索すれば見つかるので概要だけ記載します。
UITableViewにDrag&Dropできるように以下の設定をします。

ViewController.swift
tableView.dragInteractionEnabled = true
tableView.dragDelegate = self
tableView.dropDelegate = self

UITableViewDragDelegateの実装はこんな感じです。
Dragした際にセルの文字列を取得しています。

ViewController.swift
extension HomeViewController: UITableViewDragDelegate {
    func tableView(_ tableView: UITableView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
        let todoName = db.getItem(at: indexPath.row).text // Dragするセルの文字列を取得
        let todoProvider = NSItemProvider(object: todoName as NSItemProviderWriting)
        return [UIDragItem(itemProvider: todoProvider)]
    }
}

Dropした際に、tableView(_ tableView: UITableView, performDropWith coordinator: UITableViewDropCoordinator)が呼ばれて、
並び替えの実装をここでおこないます。

ViewController.swift
extension ViewController: UITableViewDropDelegate {
    func tableView(_ tableView: UITableView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UITableViewDropProposal {
        return UITableViewDropProposal(operation: .move, intent: .insertAtDestinationIndexPath)
    }
    
    func tableView(_ tableView: UITableView, performDropWith coordinator: UITableViewDropCoordinator) {
        // Dropした際の並び替えの実装
    }
}

上手く実装できなかったところ

今回つまずいたところは、Dropした際にtableView(_ tableView: UITableView, performDropWith coordinator: UITableViewDropCoordinator)の処理が呼ばれない問題でした。
他のfunc tableView(_ tableView: UITableView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UITableViewDropProposal
ちゃんと呼ばれることは堪忍できたので、UITableViewDropDelegateが設定できていないわけではないようです。

解決方法

ロングタップのDrag&Dropで並び替えをする前にnavigationItem.leftBarButtonItem = editButtonItemでUITabelViewの左上に編集ボタンを表示して、
並び替えをできるようにしており、こちらの機能を併用していると対象のメソッドが呼ばれなかったです。
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath)などの並び替えするメソッドを削除したところ
ちゃんとtableView(_ tableView: UITableView, performDropWith coordinator: UITableViewDropCoordinator)が呼ばれるました。

まとめ

簡単な実装からステップアップで機能を追加して行く際に、
似たような機能のイベントが影響することもままありそうなので気をつけたいところです。

参考記事

https://dev.classmethod.jp/articles/uitableview-dragdelegate-dropdelegate1/
https://developer.apple.com/documentation/uikit/drag_and_drop/adopting_drag_and_drop_in_a_table_view

2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?