「興味のある」を選択したユーザーを読み込みたいです
アプリ内で興味のある人に対して「興味ある」というボタンを押すことが出来ます。そこで一覧として誰に「興味ある」を押したのかまとめてあるページを作りたいなと思っています。
起きている問題としては要素が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("||||||||||||||||||")
Firestore はクラウド上にデータを保存するために非同期で処理が行われます。
append の直後に reloadData すればいいのでは。
お返事ありがとうございます。
appendの直後にreloadDataを入れたのですが結果は変わりませんでした。
ごめんなさい、reloadData は append の直後よりはループ終了後のほうがいいですね。
ってのはさておき、Firestore のデータの読み書きは非同期で行われます。つまり、viewWillAppear から loadInterestedInUsers を呼び出しても、loadInterestedInUsers はすぐに (データを取得する前に) 終了して次の print 文が実行されます。
loadInterestedInUsers の getDocuments の後ろの { (interestedToUsers, error) in 〜 } の部分がクロージャと言って、実際にデータが取得された時に実行される部分になりますが、これが実行されるのは loadInterestedInUsers の実行が終わって、viewWillAppear の中の print が実行された後になります。
ありがとうございます。少し調べてみたのですがcompletionというものを知りました。これ理解できればこの問題は解決しそうですか?
```
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
}
```
completion を使って書いてみたのですが、結果変わりませんでした。
コードは良さそうに見えますけど、結果が変わらないというのは、
・TableView に何も表示されない
・print("???????????????") のところに [] と表示される
ってことですか? loggedInUser.uid のところにデータは存在するんですよね?
print("???????????????") のところに [] と表示されます。
loggedInUser.uidのところにはデータは確かに存在します。printで確認しました。
print(loggedInUser.uid) で何かが表示されたってことですね? 次は loadInterestedInUsers の値を print してご確認ください。(または、ブラウザで Firestore の "users" コレクションの loggedInUser.uid で表示された ID のドキュメントの "interestedTo" サブコレクションのデータを確認するとか。)
interestedUserInfoやappendした直後のinterestedUserは存在が確認できています。
completion()の位置を1つ上のかっこの中に入れてあげたらちゃんと作動し、表示もできるようになりました。
ただなんでcompletion()を1つ上にやってあげる必要があったのかが分かっていないのでもし何かご存知でしたら教えて下さい。
動いて良かったです。completion() の位置ですが、よく見たら元のコードではクロージャの外側になっていたので、それだと Firestore の結果が返ってくる前に実行されてしまい、interestedUser は空ですね。completion() の位置をずらすことで、クロージャの内側になって、Firestore の結果が返ってきた後で実行されるようになったのだと思います。
本当にありがとうございました
あなたの回答
tips
プレビュー