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

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

詳細はこちら
Cloud Firestore

Cloud Firestore は、自動スケーリングと高性能を実現し、アプリケーション開発を簡素化するように構築された NoSQLドキュメントデータベースです。

Swift

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

Q&A

解決済

1回答

809閲覧

Firestoreのデータを表示しているtableViewのセルをタップしたとき、そのセルのドキュメントIDを取得したい。

Ogikubo

総合スコア1

Cloud Firestore

Cloud Firestore は、自動スケーリングと高性能を実現し、アプリケーション開発を簡素化するように構築された NoSQLドキュメントデータベースです。

Swift

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

0グッド

0クリップ

投稿2020/12/05 16:19

編集2020/12/05 16:33

前提・実現したいこと

Firestoreのデータを表示しているtableViewのセルをタップしたとき、そのセルのドキュメントIDを取得したい。

実現したいことは以下の通りです。
1,タップしたセルのドキュメントIDを取得
2,DetaiviewControllerにそのIDを渡す。
3,DetaiviewControllerにあるgetActionボタンを押したらそのIDの投稿をマイページに保存する

プログラミング始めたてで質問の仕方が適切でないかもしれませんが、回答していただけると嬉しいです。

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

タップしたセルのドキュメントIDが取得できません。

該当のソースコード

tableviewController

1 override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 2 let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! TimeLineCell 3 cell.timeLineModel = self.timeLines[indexPath.row] 4 5 return cell 6 } 7 8 override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 9 10 let selectedCell = tableView.cellForRow(at: indexPath) 11 musicName = timeLines[indexPath.row].musicName 12 groupName = timeLines[indexPath.row].groupName 13 constitution = timeLines[indexPath.row].constitution 14 15 performSegue(withIdentifier: "detail", sender: nil) 16 } 17 18 override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 19 20 if segue.identifier == "detail" { 21 22 let detailViewController = segue.destination as! DetailViewController 23 24 detailViewController.musicName = musicName 25 detailViewController.groupName = groupName 26 detailViewController.constitution = constitution 27 }

TimeLineModel

1import Foundation 2import Firebase 3 4class TimeLineModel { 5 6 var musicName:String = "" 7 var groupName:String = "" 8 var constitution:String = "" 9 var ref = Firestore.firestore().collection("timeLine") 10 11 12 init(musicName:String,groupName:String,constitution:String) { 13 14 self.musicName = musicName 15 self.groupName = groupName 16 self.constitution = constitution 17 } 18 19 init(document:QueryDocumentSnapshot) { 20 21 if let value = document.data() as? [String:Any] { 22 23 musicName = value["musicName"] as! String 24 groupName = value["groupName"] as! String 25 constitution = value["constitution"] as! String 26 } 27 } 28 29 func toContents() -> [String:Any] { 30 return ["musicName":musicName,"groupName":groupName,"constitution":constitution] 31 } 32 33 func save() { 34 ref.addDocument(data: toContents()) 35 } 36

試したこと

https://teratail.com/questions/203222
この記事の方法を試しましたが draftData が何を指すのかわからず理解で解決できませんでした。

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

ここにより詳細な情報を記載してください。

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

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

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

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

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

TsukubaDepot

2020/12/05 22:34

問題の本質がFirestoreに関係してくるとなると判断できない部分もありますが、すくなくとも tableView(_ :cellForRowAt:) では、Cell に定義してある timeLineModel に値を渡していますが、タップされた時のメソッド tableView(_:didSelectRowAt:) では、タップされたセルのインスタンをを次の方法で得ているものの、 let selectedCell = tableView.cellForRow(at: indexPath) 値の代入は上記の selectedCell を使わずに musicName = timeLines[indexPath.row].musicName groupName = timeLines[indexPath.row].groupName constitution = timeLines[indexPath.row].constitution と、timeLines を使ってやっているようですが、そのあたりの整合性はどのようになっているのでしょうか。
Ogikubo

2020/12/09 10:41

ご指摘ありがとうございます。 教材のコードを写している部分もあり、恥ずかしながら自分でもよく理解できていなかったですが、渡されている値は正しかったです、、、 selectedCellを使ったやり方をもしよろしければ教えていただきたいです。
Ogikubo

2020/12/09 11:25

tableViewに並んでいる順番とtimeLinesという配列の中の投稿の順番が同じで、timeLines[indexPath.row]と書くことでタップされた投稿の情報を取得できると考えています。
TsukubaDepot

2020/12/10 00:54

指摘したいことは、tableView(_:indexPath:) でカスタムセル内のプロパティ(変数)にtimeLineModel を代入していますが、その他の場所で一切使えわれていないということです。 2020/12/09 20:25  のコメントでもあるように、配列で保持しているデータとセルのデータの順番が一致しているのであれば、あえてセルにデータを持たせる意味は少ないのではないでしょうか。 ちなみに、それを簡潔に解決されているのが、hameji001さんのご回答です。 セルには情報を持たせず、indexPath を使ってアクセスすべきデータを管理しています。
Ogikubo

2020/12/13 04:32

なるほど、、senderを使ってindexpathの情報ごと送ればその必要はなかったですね! ありがとうございます! hajimeさんの回答を参考にまた考え直して見たいと思います! ご指摘本当にありがとうございました!
Ogikubo

2020/12/13 05:01

この方法でも選択したセルの情報を得ることが出来るんですね。 他にも応用できそうな情報ありがとうございます、とてもためになります! 親切な対応ありがとうございます!
guest

回答1

0

ベストアンサー

自分も似たようなことをしています。

簡単な方法はdocumentIDをTimeLineModelに持たせることです。

class TimeLineModelにdocumentID(String型)用にメンバ変数を設定し、
init(document:QueryDocumentSnapshot)で
document.documentIDを取得し、そのメンバ変数に保存すればいいと思います。

あと、classよりstructの方が堅牢なシステムになるので、いいみたいです。

また、TableViewControllerではメンバ変数に
timeLines: [TimeLineModel]を保持しているようなので、
TimeLineModelごと次のDetailViewControllerに渡すように変えるといいと思います。
(DetaiViewControllerにTimeLineModel保持用のメンバ変数を用意する)

TableView

1func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 2 let selectedTimeLine = timeLines[indexPath.row] 3 performSegue(withIdentifier: "detail", sender: selectedTimeLine) 4 // ↑ senderに選択された行のtimeLineを入れる 5} 6 7override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 8 if segue.identifier == "detail" { 9 let detailVC = segue.destination as! DetailViewController 10 detailVC.timeLine = sender as! TimeLineModel 11 // ↑ここでsenderからTimeLineModelを取り出し、次のViewにセット 12 } 13} 14

投稿2020/12/07 14:55

hameji001

総合スコア639

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

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

Ogikubo

2020/12/09 10:26

ご回答本当にありがとうございます!!早速試させていただきました! 追加で少し質問をしたいのですが、、 tabelViewControllerで受け取ったTimeLineModelにある変数(musicNameなど)を取得するにはどうしたら良いでしょうか?
hameji001

2020/12/10 14:14

それはとても簡単です。 たとえば、 DetailViewControllerに pushedTimeLine: TimeLineModel をメンバ変数に用意したとします。そのmusicNameやgroupNameを取得するには、pushedTimeLine.musicNameと記述すれば、String型のデータをそのまま利用できます。 nextView ?
Ogikubo

2020/12/13 04:38

ありがとうございます!できました! 丁寧に教えてくださり本当にありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問