🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

1回答

2551閲覧

TableViewCellのドラッグアンドドロップがうまくいかない

tatsu757

総合スコア12

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2019/12/05 07:01

編集2019/12/05 08:16

前提・実現したいこと

ToDoアプリのTableViewCellを編集モードを使わずに並べ替えたいのですが、上手くいきません。
以下のサイトを参考にしたのですが、配列arrayに入れたタスク(文字列)をドラッグアンドドロップで並べ替えられるようにするにはどのようにコードを書き換えれば良いでしょうか。

発生している問題・エラーメッセージ

該当のソースコード

swift

1import UIKit 2 3class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource,UINavigationControllerDelegate,UITableViewDragDelegate,UITableViewDropDelegate { 4 5 6 //セクションの数を指定 7 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 8 9 return array.count 10 } 11 12 13 14 //生成したセルを順番に表示 15 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 16 17 let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) 18 //Table View CellのidentifireをCellとする 19 20 cell.textLabel?.text = array[indexPath.row] 21 cell.layer.backgroundColor = UIColor.clear.cgColor 22 return cell 23 } 24 25 //セルの移動許可 26 func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool { 27 return true 28 } 29 30 //セルを移動した時の処理 31 func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) { 32 // TODO: 入れ替え時の処理を実装する(データ制御など) 33 34 } 35 36 37 38 39 @IBOutlet var tableView: UITableView! 40 41 //todoを入れる配列 42 43 var array = [String]() 44 45 override func viewDidLoad() { 46 super.viewDidLoad() 47 tableView.delegate = self 48 tableView.dataSource = self 49 tableView.dragDelegate = self 50 tableView.dropDelegate = self 51 tableView.dragInteractionEnabled = true 52 //現在の配列を取り出す 53 if (UserDefaults.standard.object(forKey: "todo") != nil){ 54 array = UserDefaults.standard.object(forKey: "todo") as! [String] 55 } 56 57 self.tableView.reloadData() 58 59 } 60 61 //セルのドラッグ処理 62 func tableView(_ tableView: UITableView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] { 63 //????? 64 return [?????.dragItem (for: indexPath)] 65 } 66 67 68 func dragItem(for indexPath: IndexPath) -> UIDragItem { 69 //????? 70 let task = array[indexPath.row] 71 let itemProvider = NSItemProvider(object: task as NSString) 72 73 return UIDragItem(itemProvider: NSItemProvider()) 74 } 75 76 77 //セルのドロップ 78 func tableView(_ tableView: UITableView, dropSessionDidUpdate session: UIDropSession, 79 withDestinationIndexPath destinationIndexPath: IndexPath?) -> UITableViewDropProposal { 80 return UITableViewDropProposal(operation: .move, intent: .insertAtDestinationIndexPath) 81 } 82 83 func tableView(_ tableView: UITableView, performDropWith coordinator: UITableViewDropCoordinator) { 84 guard let item = coordinator.items.first, 85 let destinationIndexPath = coordinator.destinationIndexPath, 86 let sourceIndexPath = item.sourceIndexPath else { return } 87 88 tableView.performBatchUpdates({ [weak self] in 89 guard let strongSelf = self else { return } 90 //???? 91 strongSelf.array.moveItem(sourcePath: sourceIndexPath.row, destinationPath: destinationIndexPath.row) 92 tableView.deleteRows(at: [sourceIndexPath], with: .automatic) 93 tableView.insertRows(at: [destinationIndexPath], with: .automatic) 94 }, completion: nil) 95 coordinator.drop(item.dragItem, toRowAt: destinationIndexPath) 96 } 97 98 99 func moveItem(sourcePath: Int, destinationPath: Int) { 100 let moveTask = array.remove(at: sourcePath) 101 array.insert(moveTask, at: destinationPath) 102 } 103 104 105 106 //ここから下のコードはうまく動いている↓

試したこと

参考サイト
UITableViewのdragDelegate, dropDelegateについて調べて試した

補足情報(FW/ツールのバージョンなど)

他におかしい箇所があればご教示いただけますと幸いです。
よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

vanderlvov

2019/12/05 07:20

1. URLをマークダウンの形式にしてください。 2. エラーメッセージのブロックはいらないと削除してください。
takabosoft

2019/12/05 08:29

上手く行かないだけではわかりません。どこまで期待通りに動いていて、何が上手くいかないのでしょうか?
tatsu757

2019/12/05 08:37

わかりにくい書き方で申し訳ありませんでした。ドラッグアンドドロップ以外の機能はうまく動いていますが、本アプリにおけるドラッグアンドドロップを動作させるコードの書き方がわからなくなってしまいました。itemsForBeginningとperformDropWithのところにはこの場合どのようなコードを記述すれば良いのでしょうか。
guest

回答1

0

itemsForBeginningの方ですが、たぶん何も情報は使っていないので

return [UIDragItem(itemProvider: NSItemProvider())]

とでも書いておけばいいです。
(func dragItem(for indexPath: IndexPath) -> UIDragItem 関数はたぶん不要)

strongSelf.array.moveItem(sourcePath: sourceIndexPath.row, destinationPath: destinationIndexPath.row)

こっちはarrayの中身をsourceIndexPath.rowからdestinationIndexPath.rowへ移動させるようなコードを自分で書かないといけないです。
中に何の値が入っているかprintなどして、どうすればいいか考えて実装してください。


一応手元でも動かしてみましたが適当に作ったコードでもドラッグ中のものは勝手に表示されているようです。

swift

1import UIKit 2 3class ViewController: UIViewController, UITableViewDataSource, UITableViewDragDelegate, UITableViewDropDelegate { 4 5 let tableView = UITableView(frame: .zero, style: .plain) 6 let array = ["あああ", "いいい", "ううう", "えええ", "おおお", "かかか", "ききき"] 7 8 override func viewDidLoad() { 9 super.viewDidLoad() 10 // Do any additional setup after loading the view. 11 12 13 tableView.frame = UIScreen.main.bounds 14 tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell") 15 tableView.dataSource = self 16 tableView.dragDelegate = self 17 tableView.dropDelegate = self 18 tableView.dragInteractionEnabled = true 19 view.addSubview(tableView) 20 } 21 22 // MARK: - UITableViewDataSource 23 24 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 25 return array.count 26 } 27 28 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 29 let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) 30 cell.textLabel?.text = array[indexPath.row] 31 //cell.layer.backgroundColor = UIColor.clear.cgColor 32 return cell 33 } 34 35 // MARK: - UITableViewDataSource 36 37 func tableView(_ tableView: UITableView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] { 38 return [UIDragItem(itemProvider: NSItemProvider())] 39 } 40 41 // MARK: - UITableViewDropDelegate 42 43 func tableView(_ tableView: UITableView, dropSessionDidUpdate session: UIDropSession, 44 withDestinationIndexPath destinationIndexPath: IndexPath?) -> UITableViewDropProposal { 45 return UITableViewDropProposal(operation: .move, intent: .insertAtDestinationIndexPath) 46 } 47 48 func tableView(_ tableView: UITableView, performDropWith coordinator: UITableViewDropCoordinator) { 49 guard let item = coordinator.items.first, 50 let destinationIndexPath = coordinator.destinationIndexPath, 51 let sourceIndexPath = item.sourceIndexPath else { return } 52 53 /*tableView.performBatchUpdates({ [weak self] in 54 guard let strongSelf = self else { return } 55 strongSelf.resource.moveItem(sourcePath: sourceIndexPath.row, destinationPath: destinationIndexPath.row) 56 tableView.deleteRows(at: [sourceIndexPath], with: .automatic) 57 tableView.insertRows(at: [destinationIndexPath], with: .automatic) 58 }, completion: nil)*/ 59 coordinator.drop(item.dragItem, toRowAt: destinationIndexPath) 60 } 61}

実行結果:
イメージ説明

投稿2019/12/05 09:03

編集2019/12/09 03:40
takabosoft

総合スコア8356

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tatsu757

2019/12/06 04:35

ありがとうございます。少し考えてみます。
tatsu757

2019/12/06 07:55

return [UIDragItem(itemProvider: NSItemProvider())]と書くとエラーは消えましたが、選択されたセルに配列の要素が渡されていないようです。実機で確認したところ、空のセルがドラッグされてしまう様に見えます。
takabosoft

2019/12/06 08:32

> 選択されたセルに配列の要素が渡されていないようです もうちょっと具体的に何がどうなっているのか教えて下さい。
tatsu757

2019/12/06 09:20

セルを選択すると浮き上がってドラッグできるようにはなりますが、浮き上がったセルには文字列が表示されていない状況です。
takabosoft

2019/12/09 03:44 編集

ドラッグ中の画像がどういう仕組で出ているかはわかりませんが、自分のところではとりあえず出ているので、何故でないかはソースの違いなどから検証してください。
tatsu757

2019/12/10 01:37

ありがとうございます。自身のコードと照らし合わせてみます。
tatsu757

2019/12/10 02:44

takabosoftさんのコードを適用したところ、ドラッグアンドドロップできるようになりました! ありがとうございました。 しかし、配列にテキストを新規追加したり変更を加えるとドラッグアンドドロップで移動したアイテムの順序が元に戻ってしまいます。これはドラッグ&ドロップによって配列の中身が書き換えられていないのでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問