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

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

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

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

TableView

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

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

Swift

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

Q&A

解決済

2回答

2451閲覧

Swift:Firebase Realtime Database に保存したデータをTableViewに表示する方法

Y.Kame

総合スコア13

Firebase

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

TableView

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

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

Swift

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

0グッド

0クリップ

投稿2019/08/23 08:00

前提・実現したいこと

Firebase/RealtimeDatabase に保存したデータを、TableViewに配列したいんですが、うまくデータベースから値を取得できません。出力イメージを下に添付しています。

イメージ説明

データベースはこの下記のように保存しています。

イメージ説明

データベースから、シリアルナンバー(number) でフィルターをかけて履歴をTableViewに表示したいと思っています。

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

コードのエラーは出ないんですが、ビルドしてもシミュレータのTableViewに何も表示されません。 データベースからうまく取得できていないみたいです。

該当のソースコード

HomeViewController

1class History { 2 3 var time:String? = "" 4 var status:String? = "" 5 var price:String? = "" 6 7 init(time: String?, status: String?, price: String?) { 8 self.time = time 9 self.status = status 10 self.price = price 11 } 12 13} 14 15class HomeViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { 16 17** 中略 ** 18 19 var historys = [History]() 20 21 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 22 return historys.count 23 } 24 25 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 26 let cell = tableView.dequeueReusableCell(withIdentifier: "historyCell", for: indexPath) as! HomeViewControllerTableViewCell 27 let history = historys[indexPath.row] 28 cell.timeLabel.text = history.time 29 cell.statusLabel.text = history.status 30 cell.priceLabel.text = history.price 31 return cell 32 } 33 34** 中略 ** 35 36 override func viewDidLoad() { 37 super.viewDidLoad() 38 39 tableView.dataSource = self 40 tableView.delegate = self 41 42 // 遷移元のTextFieldに入力したシリアルナンバーを"argString"に値渡し 43 serialLabel.text = argString 44 45 46 //残高に表示するデータをデータベースから取り出し 47 ref = Database.database().reference().child("Action") 48 49 ref.queryOrdered(byChild: "number").queryEqual(toValue: argString).queryLimited(toLast: 1).observeSingleEvent(of: .value, with: {(snapshot) in 50 for item in snapshot.children { 51 let snap = item as! DataSnapshot 52 let dict = snap.value as! [String: Any] 53 let pricedata = dict["balance"] as! Int 54 // データの中身 55 print(pricedata as Any) 56 self.balance = pricedata 57 self.price.text = String(self.balance) + String(self.entext) 58 } 59 }) 60 61 //データベースから履歴に表示させるデータを取り出す 62 func LoadHistory() { 63 ref.queryOrdered(byChild: "number").queryEqual(toValue: argString).observeSingleEvent(of: .value, with: {(snapshot) in 64 for item2 in snapshot.children { 65 let snap2 = item2 as! DataSnapshot 66 let dict2 = snap2.value as! [String: Any] 67 let time = dict2["time"] as! String 68 let status = dict2["status"] as! String 69 let price = dict2["price"] as! String 70 let hist = History(time: time, status: status, price: price) 71 self.historys.append(hist) 72 } 73 self.tableView.reloadData() 74 }) 75 } 76 77 78 } 79 80 81 override func didReceiveMemoryWarning() { 82 super.didReceiveMemoryWarning() 83 } 84 85 86} 87

HomeViewControllerTableViewCell

1 2import UIKit 3 4class HomeViewControllerTableViewCell: UITableViewCell { 5 6 @IBOutlet weak var timeLabel: UILabel! 7 @IBOutlet weak var statusLabel: UILabel! 8 @IBOutlet weak var priceLabel: UILabel! 9 10 override func awakeFromNib() { 11 super.awakeFromNib() 12 // Initialization code 13 } 14 override func setSelected(_ selected: Bool, animated: Bool) { 15 super.setSelected(selected, animated: animated) 16 } 17 18} 19

試したこと

データベースからうまくデータを取得できてるか確認するために、「//データベースから履歴に表示させるデータを取り出す」の部分でprint()コードを記述してみたんですが、とくになにも出力されませんでした(汗)

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

Swift5

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

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

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

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

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

guest

回答2

0

ベストアンサー

データベースからうまくデータを取得できてるか確認するために、「//データベースから履歴に表示させるデータを取り出す」の部分でprint()コードを記述してみたんですが、とくになにも出力されませんでした(汗)

どこに print() を書いていますか?
また、どこで LoadHistory() を呼び出していますか?

コードを見る限りでは、どこにも上記 2 つは見当たらないので、書いてもいないし、呼び出してもいないのではないかと思います。

投稿2019/08/23 08:35

s.m_1

総合スコア293

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

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

Y.Kame

2019/08/23 08:40

回答ありがとうございます。 *** //データベースから履歴に表示させるデータを取り出す func LoadHistory() { ref.queryOrdered(byChild: "number").queryEqual(toValue: argString).observeSingleEvent(of: .value, with: {(snapshot) in for item2 in snapshot.children { let snap2 = item2 as! DataSnapshot let dict2 = snap2.value as! [String: Any] let time = dict2["time"] as! String let status = dict2["status"] as! String let price = dict2["price"] as! String let hist = History(time: time, status: status, price: price) self.historys.append(hist)        print(dict2 as Any) ⇦ここに"print()"を書きました } self.tableView.reloadData() }) } *** また「LoadHistory()」を「override func viewDidLoad() {}」の中に記述してたんですがエラーがでたので削除してどこにも記述していません…
s.m_1

2019/08/23 08:44

どこにも LoadHistory() を記述していなので、データが表示されるわけありません。 LoadHistory() を呼び出した時のエラーを載せてください。
Y.Kame

2019/08/23 08:48

「override func viewDidLoad(){}」の中の、「//データベースから履歴に表示させるデータを取り出す」のすぐ下に「LoadHistory()」を記述してビルドしてみました。 コードでエラーは発生しませんでしたが、遷移元でTextFieldを入力してHomeViewControllerに遷移したところ… let price = dict2["price"] as! String の部分で Thread 1: signal SIGABRT のエラーが発生してアプリが落ちてしまいました(涙)
s.m_1

2019/08/23 08:52

Thread 1: signal SIGABRT ではなく、ログ画面に出ているエラーを載せてください。 おそらくですが、 let price = dict2["price"] as! String で、price を取得しようとしていますが、値は無いためアプリが落ちるんだと思います。 price を取得する前に、dict の中身を確認してみてください。
Y.Kame

2019/08/23 08:54

なるほど…すいません(汗) Could not cast value of type '__NSCFNumber' (0x111fbaa38) to 'NSString' (0x1107b94c8). とログに記載してありました。 priceはStringではなくInt型で保存しているからでしょうか…
s.m_1

2019/08/23 08:57

でしたら、Int 型で取得して、表示する時に、"(price)" と表示すればいいんじゃないですか?
Y.Kame

2019/08/23 09:11

ありがとうございます! let price = dict2["price"] as? Int に書き換えてみました。 すると let hist = History(time: time, status: status, price: price) の部分で Cannot convert value of type 'Int' to expected argument type 'String?' というエラーが発生してしましました… また「表示する時に、"(price)"と表示する・・・っていうのはどの部分のことでしょうか。 たくさんすみません。
s.m_1

2019/08/23 09:13

それでしたら、History クラスの price の型を Int 型にしてみたらどうですか?
Y.Kame

2019/08/23 09:31

さっき試してみたんですけど、すると今度は・・・ func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "historyCell", for: indexPath) as! HomeViewControllerTableViewCell let history = historys[indexPath.row] cell.timeLabel.text = history.time cell.statusLabel.text = history.status cell.priceLabel.text = history.price return cell } この部分の cell.priceLabel.text = history.price ここで Cannot assign value of type 'Int?' to type 'String?' ってなっちゃうんですよ(涙)
s.m_1

2019/08/23 09:34

そこで、先ほど説明した、"(price)" を使います。 この場合だと、 cell.priceLabel.text = "(history.price)" ですが。 label.text には String 型しかセットすることができません。 しかし、history.price は Int 型なので、エラーになるわけです。
Y.Kame

2019/08/23 10:23

なるほど!! ありがとうございます。 言われたようにコードを記述したらエラーはなくなりました! ですが、ビルドしてシミュレートした際にまた遷移する段階でアプリが落ちました・・・ ログにはこう記述されていました… *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<UITableViewCell 0x7fb09302f000> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key price.'
s.m_1

2019/08/23 10:38

price を取得する時にどのようなコードを書いていますか? おそらく、dict["price"] なのですが、dict には price というキーが存在しないためエラーが起きています。 dict の中身だけを print してみて、確認してください。
Y.Kame

2019/08/23 11:07

let price = dict2["price"] as! String で price を取得しています。 print(dict2 as Any) でプリントしたところログに下記のようなログが残りました。 ["number": N525ASU, "balance": 10000, "time": 2019/08/22 18:41:05, "status": チャージ, "price": 10000] ["number": N525ASU, "balance": 15000, "time": 2019/08/22 18:42:47, "status": チャージ, "price": 5000] ["status": 支払い, "number": N525ASU, "price": 2500, "balance": 12500, "time": 2019/08/22 18:42:55] ["status": 支払い, "number": N525ASU, "price": 2500, "balance": 10000, "time": 2019/08/22 18:43:34] ["time": 2019/08/23 01:50:18, "status": チャージ, "price": 10000, "balance": 20000, "number": N525ASU] ["time": 2019/08/23 01:50:22, "status": 支払い, "price": 5000, "balance": 15000, "number": N525ASU] ["time": 2019/08/23 16:10:31, "status": 支払い, "price": 5000, "balance": 10000, "number": N525ASU]
Y.Kame

2019/08/23 11:07

あ、 let price = dict2["price"] as! Int でした。
Y.Kame

2019/08/23 11:13

上記のログの上くらいに Unknown class _TtC8nasucard11HistoryCell in Interface Builder file. っていうログも残っているんですが何か関係あるんでしょうか・・・
s.m_1

2019/08/23 11:15 編集

補足ですが、! はあまり使わないことをおすすめします。 今のように price があることが事前に確認できている場合は良いですが、仮に price が存在しない (nil) 時は、そのコードだとアプリはクラッシュします。 なので、それを防ぐためにも、 let price = dict2["price"] as? Int cell.priceLabel.text = "(history.price ?? 0)" の方が良いでしょう。
Y.Kame

2019/08/23 11:34

参考になることばかりご教授いただき助かります(涙)
Y.Kame

2019/08/23 11:41

追記ですが、 Unknown class _TtC8nasucard11HistoryCell in Interface Builder file. ログに記述されていた上記のエラーですが、TableView のTableViewCell に存在しないクラス名(HistoryCell)をセットしていたためのエラーみたいでした。 クラスのセットをしなおしたら上記のエラーはなくなりました。
guest

0

途中経過

同じような問題に直面している人がいたときの為に、途中経過と残った問題をまとめます。
(Firebase)Databaseに保存したデータをTableViewの各Labelに表示する方法をご教授して頂きました。

問題解決前のコードは質問の際に記載しているものを参照してください。

HomeViewController

1// TableViewを配置しているページのコードです 2 3import UIKit 4 5import Firebase 6import SwiftyJSON 7import FirebaseAuth 8import FirebaseDatabase 9 10class History { 11 12 var time:String? 13 var status:String? 14 var price:Int? // "price"はInt型で保存している為、Intを宣言 15 16 init(time: String?, status: String?, price: Int?) { //ここも"price"はInt型 17 self.time = time 18 self.status = status 19 self.price = price 20 } 21 22} 23 24class HomeViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { 25 26*** 中略 *** 27 28@IBOutlet weak var tableView: UITableView! 29 30var ref:DatabaseReference! 31var argString = "" // 遷移元のTextFieldに入力された"number"を値渡し 32 33 34// データベースから取得した履歴をテーブルビューに表示する 35var historys = [History]() 36 37//リストに表示する件数はある分すべてに設定されています 38func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 39 return historys.count // ここの部分です(return 1)とかだと1件表示になります 40 } 41 42func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 43 let cell = tableView.dequeueReusableCell(withIdentifier: "historyCell", for: indexPath) as! HomeViewControllerTableViewCell 44 let history = historys[indexPath.row] 45 cell.timeLabel.text = history.time 46 cell.statusLabel.text = history.status 47 cell.priceLabel.text = "(history.price ?? 0)" //Int型をString型で表示する 48 return cell 49 } 50 51 52// ▼▼▼ クラス読み込み時に一度だけ実行される処理 ▼▼▼ 53 54 override func viewDidLoad() { 55 super.viewDidLoad() 56 57 tableView.dataSource = self 58 tableView.delegate = self 59 60 //データベースから履歴に表示させるデータを取り出す 61 func LoadHistory() { 62 ref.queryOrdered(byChild: "number").queryEqual(toValue: argString).observeSingleEvent(of: .value, with: {(snapshot) in 63 for item2 in snapshot.children { 64 let snap2 = item2 as! DataSnapshot 65 let dict2 = snap2.value as! [String: Any] 66 let time = dict2["time"] as? String 67 let status = dict2["status"] as? String 68 let price = dict2["price"] as? Int 69 //取得したdict2のデータをプリント 70 print(dict2 as Any) // dict2に入っているデータベースのデータをログに出力(成功) 71 let hist = History(time: time, status: status, price: price) 72 self.historys.append(hist) 73 } 74 self.tableView.reloadData() 75 }) 76 } 77 78 LoadHistory() //これが抜けていました… すぐ上に記述しているコードの実行を命令 79 80 } 81 // ▲▲▲ ここまで ▲▲▲ 82 83 84 override func didReceiveMemoryWarning() { 85 super.didReceiveMemoryWarning() 86 } 87 88 89 90 91} 92

着地

コード記述でエラーは返ってきませんでしたが、遷移元からHomeViewControllerに遷移したタイミングでアプリが落ちる(強制終了)状態から修正することができませんでした。

ログに記載されていたエラー文を下記に記載しておきます。

log

1*** Terminating app due to uncaught exception 'NSUnknownKeyException', 2reason:'[<nasucard.HomeViewControllerTableViewCell 0x7ff629028e00>setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key price.' 3 4//日本語訳 5キャッチされない例外'NSUnknownKeyException'によるアプリの終了 6*理由* 7[<nasucard.HomeViewControllerTableViewCell 0x7ff629028e00> setValue:forUndefinedKey:] 8このクラスは、キー"price"の"key value coding"に準拠していません 9 10

ログのエラー文を見て理解しようとすると、質問の際に記述しました"HomeViewControllerTableViewCell"クラスの"price"の記述の仕方になんらかのミスがあるように理解したんですが・・・

修正を加えてもいまいちうまく抜け出せませんでした・・・

また改めて別質問でまとめさせて頂きたいと思います。

投稿2019/08/24 09:47

Y.Kame

総合スコア13

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問