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

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

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

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

Cloud Firestore

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

Swift

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

Q&A

1回答

1056閲覧

ううFirestoreによるデータの表示がうまくいきません

退会済みユーザー

退会済みユーザー

総合スコア0

Firebase

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

Cloud Firestore

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

Swift

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

0グッド

0クリップ

投稿2020/09/11 16:39

編集2020/09/12 01:44

初めてFirebaseを用いてSNS系アプリを作ろうとしてます。今回はテストなので検索窓から全てのユーザーのアカウントをtableviewで表示させ、tableview cellをタップすると画面遷移してユーザーのプロフィールページにとび、名前やプロフィールを表示させようとしています。

問題点
Stringでユーザー名を画面遷移時に渡しており、print()を使って画面遷移先のviewdidloadで渡されたユーザー名を確認すると正常に渡されていることが確認されました。しかし、それを用いてnameLabel.text に代入して画面遷移先のユーザーの名前を表示するラベルには表示されません。

試したこと
画面遷移時にユーザー固有のIDも一緒に渡しCloud Firestoreから固有のIDをもとにデータを取り出そうと考えたのですがこれもうまくいきませんでした。

下のコードのこの部分で条件分岐の全てがelseに流れたのにおかしさを感じましたが原因がわかりませんでした。
よろしくお願いします。

db.collection("users").getDocuments() { (querySnapshot, error) in if let error = error { print(error) } else { for document in querySnapshot!.documents { if document.documentID == self.passedUserId{ print("yayayaya") print(self.passedUserId) }else{ print(self.passedUserId) print("nononono") } print("(document.documentID) => (document.data())") } } }

画面遷移はSearchViewController.swift→DetailViewController.swiftです

DetailViewController.swift

import UIKit import NCMB import SCLAlertView import FirebaseFirestore import FirebaseAuth import FirebaseStorage class DetailViewController: UIViewController, UITextViewDelegate { @IBOutlet var nameLabel: UILabel! var passedUserName = String() var passedUserId = String() override func viewDidLoad() { nameLabel.text = String(passedUserName) print(passedUserName) print(passedUserId) let db = Firestore.firestore() db.collection("users").getDocuments() { (querySnapshot, error) in if let error = error { print(error) } else { for document in querySnapshot!.documents { if document.documentID == self.passedUserId{ print("yayayaya") print(self.passedUserId) }else{ print(self.passedUserId) print("nononono") } print("(document.documentID) => (document.data())") } } } /* let document = db.collection("users") document.getDocuments { (snapshot, error) in if error != nil{ print(error) }else{ print(snapshot?.documents) } } */ /* let document = db.collection("users").document(passedUserId) document.getDocument { (snapshot, error) in if error != nil { print(error) }else{ print("ああああああああ") } } */ } override func viewWillAppear(_ animated: Bool) { nameLabel.text = passedUserName } func loadDetail(){ } }

修正後
SearchViewController.swift

import UIKit import NCMB import Kingfisher import PKHUD import FirebaseAuth import FirebaseFirestore class SearchViewController: UIViewController, UITableViewDelegate, UITableViewDataSource{ var allUsers = [String]() var allUsersId = [String]() var selectedUser = String() var selectedUserId = String() @IBOutlet var searchUserTableView: UITableView! let db = Firestore.firestore() var yay = ["月曜日", "火曜日", "水曜日"] override func viewDidLoad() { super.viewDidLoad() print("1") searchUserTableView.dataSource = self searchUserTableView.delegate = self searchUserTableView.tableFooterView = UIView() loadUsers() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) } func loadUsers(){ db.collection("users").getDocuments(){ (querySnapshot, err) in if let err = err { print(err) } else { for document in querySnapshot!.documents{ //print(document.documentID) let idForDocument = document.documentID self.allUsersId.append(idForDocument) print(self.allUsersId) let docRef = self.db.collection("users").document(idForDocument) docRef.getDocument { (snapshot, error) in if error != nil{ print(error) }else{ //print(snapshot?.data()) let userName = snapshot?.get("userName") as! String print(userName) self.allUsers.append(userName) print("aaaaaaaaaaaaaaaaa") print(self.allUsers) print("2") self.searchUserTableView.reloadData() } } } } } } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { print("3") return allUsers.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")! cell.textLabel?.text = allUsers[indexPath.row] print("4") cell.tag = indexPath.row return cell } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == "toDetail"{ let detailViewController = segue.destination as! DetailViewController detailViewController.passedUserName = selectedUser detailViewController.passedUserId = selectedUserId print("11111") } } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { let selectedUser = allUsers[indexPath.row] let selectedUserId = allUsersId[indexPath.row] print(selectedUser) print(selectedUserId) print("222222") performSegue(withIdentifier: "toDetail", sender: nil) print("333333") tableView.deselectRow(at: indexPath, animated: true) print("444444") }

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

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

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

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

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

guest

回答1

0

コードの流れから、TableView Cell から DetailViewController へ Segue を繋いでいるように見受けられますが、その場合の処理の流れは

  1. prepare(for:sender:) が呼び出される
  2. tableView(_:didSelectRowAt:) が呼び出される

という順番になるため、1. ではの文字列が渡される結果になってしまいます。

つまり、2. で値を渡すための変数に値を代入(選択したセルに関連する値を代入)していますが、その処理の前に遷移のための処理が行われてしまっている、ということです。

したがって、TableView Cell から Segue を繋ぐのではなく、SearchViewController から DetailViewController へ Segue を繋ぎ、identifier を設定し、tableView(_:didSelectRowAt:)の適切な場所からperformSegue(withIdentifier:sender:) を呼び出すような流れにする必要があるかと思います。

ちなみに、両方の ViewController とも、overrideした関数内で親となる関数を呼び出していませんが、これは何らかの理由があるのでしょうか。

今回はこれが原因というわけではありませんが、特段の理由がなければ

Swift

1 override func viewDidLoad() { 2 //処理 3 } 4 5 override func viewWillAppear(_ animated: Bool) { 6 //処理 7 } 8

ではなく、

Swift

1 override func viewDidLoad() { 2 super.viewDidLoad() 3 // 処理 4 } 5 6 override func viewWillAppear(_ animated: Bool) { 7 super.viewWillAppear(animated) 8 //処理 9 }

と、親関数を呼び出してあげない限り、予想外の結果を招くことがあるかと思いますのでご確認ください。

投稿2020/09/11 23:03

TsukubaDepot

総合スコア5086

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

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

退会済みユーザー

退会済みユーザー

2020/09/12 01:44

SearchViewController.swiftの修正後のコードを追加したました。222222→11111→333333→444444 のような挙動を示しました。そして依然DetailViewControllerのnameLabel.textに値が入りません。また、SearchViewController から DetailViewController へ Segue を繋ぎ、identifier を設定しました。 overrideに関しては特に意図はありませんでした。一度消してしまったので、補完機能を使って書いた際に表示されなかったものだと思われます。
TsukubaDepot

2020/09/12 03:08

DetailViewControlle の viewDidLoad() にある print(passedUserName) print(passedUserId) ただ、そのまま値を表示しても、どのメソッドから出力されているかわかりにくくなりますので、 print(#function, passedUserId) や、 print(#file, passedUserId) ように、関数(メソッド)名やファイル名を合わせて出力させた方がわかりやすいかもしれません。 ここの部分では、渡された値は表示されていますでしょうか。
退会済みユーザー

退会済みユーザー

2020/09/12 07:12

print(#function, passedUserName) print(#function, passedUserId) の場合は viewDidLoad() viewDidLoad() となります。 print(#file, passedUserName) print(#file, passedUserId) の場合は Desktop/ios_app/SOBIT1/SOBIT1/DetailViewController.swift Desktop/ios_app/SOBIT1/SOBIT1/DetailViewController.swift と返されます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

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

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問