質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.47%
Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

TableView

TableView(UITableView)とは、リスト形式で表示するコントロールで、ほとんどのアプリに使用されています。画面を「行」に分けて管理し、一般的には各行をタップした際に詳細画面に移動します。

ドキュメント

ドキュメントは、IT用語では、ソフトウェアやハードウェアに関する情報であり、意図された目的、機能性、メインテナンスを含みます。ドキュメントは、多くの様々なフォームとフォーマットに存在しますが、その目的は常に教育することにあります。

Swift

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

Q&A

1回答

1558閲覧

tableviewのcellからドキュメントidを取得する方法

smawe

総合スコア0

Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

TableView

TableView(UITableView)とは、リスト形式で表示するコントロールで、ほとんどのアプリに使用されています。画面を「行」に分けて管理し、一般的には各行をタップした際に詳細画面に移動します。

ドキュメント

ドキュメントは、IT用語では、ソフトウェアやハードウェアに関する情報であり、意図された目的、機能性、メインテナンスを含みます。ドキュメントは、多くの様々なフォームとフォーマットに存在しますが、その目的は常に教育することにあります。

Swift

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

0グッド

0クリップ

投稿2021/09/06 03:12

編集2021/09/06 09:56

firebaseの情報を反映させたswifttのtableviewでタップされたセルのドキュメントidを取得する方法を教えてください。

swift

1コード 2import UIKit 3import Firebase 4 5class roomlist:UIViewController{ 6 private let cellId = "cellId" 7 private var rooms = [Room]() 8 private var selectedRoom : Room? 9 10 @IBOutlet weak var roomlisttable: UITableView! 11 12 override func viewDidLoad() { 13 super.viewDidLoad() 14 15 roomlisttable.delegate = self 16 roomlisttable.dataSource = self 17 fechroominfofirestore() 18 19 } 20 private func fechroominfofirestore(){ 21 22 Firestore.firestore().collection("rooms").getDocuments{(snapshots,error) in 23// print("uuuuuuuuu",Firestore.firestore().collection("rooms").document("")) 24 25 if error != nil{ 26 print("sippai") 27 28 return 29 30 } 31 snapshots?.documents.forEach({ (snapshots) in 32 let dic = snapshots.data() 33 let room = Room.init(dic: dic) 34 35 self.rooms.append(room) 36 self.roomlisttable.reloadData() 37 38 self.rooms.forEach{(rooms) in 39 print("room",room.bsubname) 40 41 } 42 }) 43 44 } 45 } 46} 47extension roomlist:UITableViewDelegate, UITableViewDataSource{ 48 49 50 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 51 return rooms.count 52 } 53 54 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 55 let cell = roomlisttable.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! roomlistcell 56 cell.room = rooms[indexPath.row] 57 58 return cell 59 } 60 61 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){ 62 63 print(indexPath) 64 print("didSelectRowAt") 65 tableView.deselectRow(at: indexPath, animated: false) 66 67 Firestore.firestore().collection("rooms").getDocuments() { (querySnapshot, err) in 68 if let err = err { 69 print("Error getting documents: (err)") 70 } else { 71 for doc in querySnapshot!.documents { 72 let documentID = doc.documentID 73 74 print(documentID) 75 } 76 } 77 } 78 79 80 81 } 82 83 func tableView(_ tableView: UITableView, didHighlightRowAt indexPath: IndexPath) { 84 85 } 86 87 override func prepare(for segue : UIStoryboardSegue, sender: Any?){ 88 89 print("Will move to next view controller.") 90 switch segue.identifier { 91 case "RoomdetqailsViewController": 92 if let RoomdetqailsViewController = segue.destination as? RoomdetqailsViewController { 93 print("Decided a destination as RoomdetqailsViewController.") 94 if let indexPath = self.roomlisttable.indexPathForSelectedRow { 95 let room = self.rooms[indexPath.row] 96 RoomdetqailsViewController.received = room 97 } 98 } 99 default: 100 print("There is no identifier of segue.") 101 break 102 } 103 } 104} 105class roomlistcell : UITableViewCell{ 106 107 var room: Room?{ 108 didSet{ 109 roomname.text = room?.bsubname 110 } 111 } 112 113 @IBOutlet weak var roomimage: UIImageView! 114 @IBOutlet weak var roomname: UILabel! 115 override func awakeFromNib() { 116 super.awakeFromNib() 117 118 roomimage.layer.cornerRadius = roomimage.frame.width/2 119 } 120 override func setSelected(_ selected: Bool, animated: Bool) { 121 super.setSelected(selected, animated: animated) 122 } 123 }

このコードで全てのcellのドキュメントを取得する方法は実装できたのですが、タップされたcellだけのドキュメントidを取得する方法がわかたずに困っています。

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

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

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

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

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

hoshi-takanori

2021/09/06 08:37

TableView に表示するには取得したドキュメントの配列を持ってるはずなので、タップされたセルの indexPath から目的のドキュメントにアクセスできるのでは。
smawe

2021/09/06 08:52 編集

初学者で申し訳ないのですが、できれば具体的な方法を教えていただきたいです。。。 cellをタップして遷移した画面においてドキュメントに内容の追加を行いたいのでcellのidの取得が必要であると考えております。
hoshi-takanori

2021/09/06 09:46

そもそも質問文のコードが具体的でないというか断片的で、例えば let documentID = 〜 の値をどう使ってるか分からないので具体的に答えようがないのです…。TableView に表示してるなら何らかの配列に保存してるのではないのですか?
smawe

2021/09/06 10:01 編集

大変失礼いたしました。コードを追記により記載させていただきました。 遷移後の画面にて print(received!.documentID) としても何も返ってこないので間違っていると思っておりました。
guest

回答1

0

まず、fechroominfofirestore で documentID を取得して Room に設定しましょう。

diff

1 struct Room { 2+ var id: String 3 var bsubname: String 4 5- init(dic: [String: Any]) { 6+ init(id: String, dic: [String: Any]) { 7+ self.id = id 8 self.bsubname = dic["name"] as? String ?? "no name" 9 ...

diff

1 private func fechroominfofirestore() { 2 Firestore.firestore().collection("rooms").getDocuments{(snapshots,error) in 3 // 略 4 5 snapshots?.documents.forEach({ (snapshots) in 6+ let id = snapshots.documentID 7 let dic = snapshots.data() 8- let room = Room.init(dic: dic) 9+ let room = Room(id: id, dic: dic) 10 11 // 略

そして、didSelectRowAt の際には、もう一度 Firestore からデータを取得する必要はありません。documentID が必要なら room.id が使えます。

swift

1 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 2 print(indexPath) 3 print("didSelectRowAt") 4 tableView.deselectRow(at: indexPath, animated: false) 5 6 let room = rooms[indexPath.row] 7 print(room.id) 8 print(room.bsubname) 9 }

あと、余計なお世話とは思いますが、fechroominfofirestore は、

  • すでにデータがある状態でもう一度呼ばれた時のために、一旦 rooms を空にすると良いでしょう。
  • forEach の中で使う変数名は snapshot や room のように単数型にしましょう。
    配列.forEach { 要素 in 〜 } の形で、配列は複数形、要素は一つずつ処理するので単数型です。
    特に rooms の表示に関しては、クロージャの引数が rooms なのに room.bsubname を表示しているためにおかしくなってました。
  • reloadData は rooms に要素を追加し終わってから一度だけ呼べば良いでしょう。
    表示も、forEach の中で表示するなら room を一つだけ表示すれば良いし、rooms の要素をすべて表示したいなら forEach の後にしましょう。

swift

1 private func fechroominfofirestore() { 2 Firestore.firestore().collection("rooms").getDocuments{ (snapshots, error) in 3 if error != nil{ 4 print("sippai") 5 return 6 } 7 8 self.rooms = [] 9 snapshots?.documents.forEach { snapshot in 10 let id = snapshot.documentID 11 let dic = snapshot.data() 12 let room = Room(id: id, dic: dic) 13 self.rooms.append(room) 14 } 15 self.roomlisttable.reloadData() 16 17 self.rooms.forEach { room in 18 print("room", room.bsubname) 19 } 20 } 21 }

投稿2021/09/06 21:15

hoshi-takanori

総合スコア7895

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

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

smawe

2021/09/07 04:09

お忙しい中ご回答いただきありがとうございます。初学者のため大変勉強になりました。 早速試させていただいたのですが、let room = Room(id: id, dic: dic)の部分において’Extra argument 'id' in call’というエラーが発生いたしました。 調べてみたところ要素の並べすぎにより発生する。10個以内にすれば解消するということだったのですが、Room.swiftの要素は10個以内のためなぜこのエラーが発生しているのか分からずに困っています。教えていただけましたら幸いです。
hoshi-takanori

2021/09/07 05:42

言葉が足らなくてごめんなさい。Room という構造体を自分で定義してたら、そこに id プロパティを追加して、イニシャライザの引数にも id を追加するという意味だったんですが、もしかして Room という型は別の方法 (Core Data とか Realm とか) で定義してたりしますか?
smawe

2021/09/07 12:28

いえいえ。とんでもないです。 別のRoom.swiftというファイルにまとめてそこから引っ張れるように?しています。 具体的なコードは import Foundation import Firebase class Room { var id: String let auniname:String let bsubname:String let createdAt:Timestamp init(dic: [String: Any]){ self.auniname = dic["auniname"] as? String ?? "" self.bsubname = dic["bsubname"] as? String ?? "" self.createdAt = dic["createdAt"] as? Timestamp ?? Timestamp() self.id = dic["id"] as? String ?? "" } } このようになっています。
hoshi-takanori

2021/09/07 12:42

あ、もともと Room クラスに id があるんですね。その id は Firestore の documentID として使っていいなら、init メソッドを次のように変更すれば良いかと。(それとも、id という属性を別途持たせてたりしますか?) init(id: String, dic: [String: Any]) { self.id = id // 略 }
smawe

2021/09/07 13:07

遷移後の画面においてfirebaseに保存されている内容の変更を行うためにidを使用しようと考えておりました(tableviewのcellにfirebaseの情報を記載、遷移後にその詳細を表示。ユーザーが変更したい場合はボタンを押して変更という流れ)。このfirebaseの情報を変更、追加する際には対象となるドキュメントidが必要とのことだったのでcellをタップしたときにidを取得して次の画面で使用できるようにしようと考えました。 ひとまずRoom.swiftで init(id: String, dic: [String: Any]) { self.id = id //略 } としてみました。遷移後の画面でボタンを押したらprint(id) としてみたらnilが帰ってくきてしまうのですがどのように処理されているのですかね??
hoshi-takanori

2021/09/07 13:44

その print(id) の id とは何でしょうか? たぶん画面遷移の際にうまく情報を渡せてないのでは。というか、画面遷移はどうやってますか?
smawe

2021/09/07 14:25

segueを使用しこの部分で画面遷移を行なっています。 また、RoomdetqailsViewController.received = room のところで情報を渡しています。 print(id)ではなくてprint(received?.id)でした。 private var rooms = [Room]() var received : Room? としてからprint(received?.id)をしました。 遷移と情報私の部分↓ override func prepare(for segue : UIStoryboardSegue, sender: Any?){ print("Will move to next view controller.") switch segue.identifier { case "RoomdetqailsViewController": if let RoomdetqailsViewController = segue.destination as? RoomdetqailsViewController { if let indexPath = self.roomlisttable.indexPathForSelectedRow { let room = self.rooms[indexPath.row] RoomdetqailsViewController.received = room } }
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

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

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問