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

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

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

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

Q&A

0回答

402閲覧

appendしたデータの読み込みが上手くいきません

退会済みユーザー

退会済みユーザー

総合スコア0

Swift

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

0グッド

0クリップ

投稿2021/01/12 11:04

「興味のある」を選択したユーザーを読み込みたいです

アプリ内で興味のある人に対して「興味ある」というボタンを押すことが出来ます。そこで一覧として誰に「興味ある」を押したのかまとめてあるページを作りたいなと思っています。

起きている問題としては要素がappendされるのが遅く、[]のままcellForRowAtやnumberOfRowsInSectionに渡され値が何も表示されないことです。

いつもtableviewのreloadをいろんな場所に挟んだりして試行錯誤やっているのですが、いつも根本の原因がわからなかったのでここで解決させてください。よろしくお願いします。

import UIKit import FirebaseFirestore import FirebaseAuth import FirebaseStorage import Nuke class InterestListViewController: UIViewController, UITableViewDelegate, UITableViewDataSource{ @IBOutlet var interestListTableView: UITableView! var interestedUser = [User]() override func viewDidLoad() { super.viewDidLoad() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) loadInterestedInUsers() print("||||||||||||||||||") print(interestedUser) print("||||||||||||||||||") } private func loadInterestedInUsers(){ guard let loggedInUser = Auth.auth().currentUser else { return } Firestore.firestore().collection("users").document(loggedInUser.uid).collection("interestedTo").getDocuments { (interestedToUsers, error) in if error != nil { print(error) }else{ interestedToUsers?.documents.forEach({ (snapshot) in let dic = snapshot.data() let interestedUserInfo = User(dic: dic) self.interestedUser.append(interestedUserInfo) }) } } self.interestListTableView.reloadData() } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return interestedUser.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")! cell.textLabel!.text = interestedUser[indexPath.row].userName print("##################") print(interestedUser[indexPath.row].userName) print("##################") return cell } }

以下の部分では[]のように表示され何も渡されない結果が表示されてしまいます。

print("||||||||||||||||||") print(interestedUser) print("||||||||||||||||||")

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

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

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

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

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

hoshi-takanori

2021/01/12 11:11

Firestore はクラウド上にデータを保存するために非同期で処理が行われます。 append の直後に reloadData すればいいのでは。
退会済みユーザー

退会済みユーザー

2021/01/12 13:13

お返事ありがとうございます。 appendの直後にreloadDataを入れたのですが結果は変わりませんでした。
hoshi-takanori

2021/01/12 14:57

ごめんなさい、reloadData は append の直後よりはループ終了後のほうがいいですね。 ってのはさておき、Firestore のデータの読み書きは非同期で行われます。つまり、viewWillAppear から loadInterestedInUsers を呼び出しても、loadInterestedInUsers はすぐに (データを取得する前に) 終了して次の print 文が実行されます。 loadInterestedInUsers の getDocuments の後ろの { (interestedToUsers, error) in 〜 } の部分がクロージャと言って、実際にデータが取得された時に実行される部分になりますが、これが実行されるのは loadInterestedInUsers の実行が終わって、viewWillAppear の中の print が実行された後になります。
退会済みユーザー

退会済みユーザー

2021/01/13 07:45

ありがとうございます。少し調べてみたのですがcompletionというものを知りました。これ理解できればこの問題は解決しそうですか?
退会済みユーザー

退会済みユーザー

2021/01/13 11:05

``` import UIKit import FirebaseFirestore import FirebaseAuth import FirebaseStorage import Nuke class InterestListViewController: UIViewController, UITableViewDelegate, UITableViewDataSource{ @IBOutlet var interestListTableView: UITableView! @IBOutlet var nameLabel: UILabel! var interestedUser = [User]() override func viewDidLoad() { super.viewDidLoad() interestListTableView.dataSource = self interestListTableView.delegate = self loadInterestedInUsers { self.interestListTableView.reloadData() print("???????????????") print(self.interestedUser) print("???????????????") } } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) } func loadInterestedInUsers(completion: @escaping () -> Void){ guard let loggedInUser = Auth.auth().currentUser else { return } Firestore.firestore().collection("users").document(loggedInUser.uid).collection("interestedTo").getDocuments { (interestedToUsers, error) in if error != nil { print(error) }else{ interestedToUsers?.documents.forEach({ (snapshot) in let dic = snapshot.data() let interestedUserInfo = User(dic: dic) self.interestedUser.append(interestedUserInfo) }) self.interestListTableView.reloadData() } } completion() } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return interestedUser.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")! cell.textLabel!.text = interestedUser[indexPath.row].userName return cell } ```
退会済みユーザー

退会済みユーザー

2021/01/13 11:05

completion を使って書いてみたのですが、結果変わりませんでした。
hoshi-takanori

2021/01/13 11:17

コードは良さそうに見えますけど、結果が変わらないというのは、 ・TableView に何も表示されない ・print("???????????????") のところに [] と表示される ってことですか? loggedInUser.uid のところにデータは存在するんですよね?
退会済みユーザー

退会済みユーザー

2021/01/13 11:56

print("???????????????") のところに [] と表示されます。 loggedInUser.uidのところにはデータは確かに存在します。printで確認しました。
hoshi-takanori

2021/01/13 12:08

print(loggedInUser.uid) で何かが表示されたってことですね? 次は loadInterestedInUsers の値を print してご確認ください。(または、ブラウザで Firestore の "users" コレクションの loggedInUser.uid で表示された ID のドキュメントの "interestedTo" サブコレクションのデータを確認するとか。)
退会済みユーザー

退会済みユーザー

2021/01/13 12:41 編集

interestedUserInfoやappendした直後のinterestedUserは存在が確認できています。
退会済みユーザー

退会済みユーザー

2021/01/13 13:11

completion()の位置を1つ上のかっこの中に入れてあげたらちゃんと作動し、表示もできるようになりました。 ただなんでcompletion()を1つ上にやってあげる必要があったのかが分かっていないのでもし何かご存知でしたら教えて下さい。
hoshi-takanori

2021/01/13 13:18

動いて良かったです。completion() の位置ですが、よく見たら元のコードではクロージャの外側になっていたので、それだと Firestore の結果が返ってくる前に実行されてしまい、interestedUser は空ですね。completion() の位置をずらすことで、クロージャの内側になって、Firestore の結果が返ってきた後で実行されるようになったのだと思います。
退会済みユーザー

退会済みユーザー

2021/01/13 13:25

本当にありがとうございました
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

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

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

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問