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

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

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

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

Swift

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

Q&A

解決済

1回答

1744閲覧

(Swift/Firebase/Firestore)Int型のデータをラベルに表示できない

haruhi.

総合スコア18

Firebase

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

Swift

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

0グッド

0クリップ

投稿2019/07/19 06:06

編集2019/07/19 06:28

Firestoreに記録しているInt型のフィールドを取得・CollectionViewのセル内ラベルに表示したい

お世話になります。
現在、食材検索・食事記録サービスを開発しながらSwiftとFirebaseを学んでいる初学者です。
以前下記リンクのような質問をさせていただきました。
https://teratail.com/questions/199897

この質問にいただいた回答を基に、Firestore内に入れているInt型のデータをラベルに表示するコードを以下のように書いたのですが、実行するとアプリが落ちてしまいます。

なお、Firestoreには

  • 食品名(String)
  • メーカー名(String)
  • 価格(Number)

というデータが2つ入っております。

String型のデータは正しく表示されていることもあり、どうしてInt型だと配列に追加・ラベルに上手く表示できないのか分かりません。
どなたか解決策をご存知の方がいらっしゃいましたら、教えていただきたいです。

該当のソースコード

Swift

1// ViewController 2var foodNameArray: [String] = [] 3var priceArray: [Int] = [] 4class ViewController: UIViewController, UICollectionViewDataSource, UISearchBarDelegate { 5 //中略 6 7 // セルを表示する内容 8 func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 9 10 let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! CollectionViewCell2 11 cell.label1.text = foodNameArray[indexPath.row] 12 // 表示されないラベルは以下 13 cell.label2.text = String(priceArray[indexPath.row]) 14 cell.btn1.tag = indexPath.row 15 cell.setCell() 16 return cell 17 } 18 19 // Firestoreからデータをもってくる 20 private func loadData() { 21 22 let db = Firestore.firestore() 23 db.collection("items").getDocuments() { (querySnapshot, err) in 24 if let err = err { 25 print("Error getting documents: (err)") 26 } 27 for document in querySnapshot!.documents { 28 if let foodName = document.data()["name"] as? String{ 29 foodNameArray.append(foodName) 30 } 31 if let priceDetail = document.data()["price"] as? Int{ 32 priceArray.append(priceDetail) 33 } 34 } 35 self.collectionViewObj.reloadData() 36 } 37 }

質問内容に不備・不明瞭な点がありましたら、ご指摘いただけますと助かります。
よろしくお願いいたします。

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

Swift version 5.0.1
Xcode version 10.2.1

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

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

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

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

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

fuzzball

2019/07/19 06:18

saltDetailArrayってなんでしょうか?定義されてないですが。
fuzzball

2019/07/19 06:20

>>ビルドするとアプリが落ちてしまいます 「アプリが落ちて」ではなく、エラーが出るということでしょうか? それとも、「実行すると」アプリが落ちるのでしょうか?
haruhi.

2019/07/19 06:27

fuzzballさん ご指摘いただきありがとうございます。 配列名は以前使っていた名前のまま記載してしまいました。 正しくは『priceArray』です。 また、『アプリが落ちる』とは『実行し、シミュレーターで該当ページを表示したときにアプリが落ちる』です。 『cell.label2.text = String(priceArray[indexPath.row])』という箇所に『Thread 1: Fatal error: Index out of range』と表示されます。 以上、2点修正いたしました。引き続きよろしくお願いいたします。
fuzzball

2019/07/19 06:32

Firebaseのことはよく分からないのですが、"price"が設定されていない、もしくは数値ではないデータがありませんか?
haruhi.

2019/07/19 06:41

お返事いただきありがとうございます。 FirestoreのitemsコレクションにNumberという型でpriceを設定しています。
fuzzball

2019/07/19 06:54

それは質問に書いてあるので知ってます。 具体的なコードで言うと、 document.data()["price"] as? Int ここでIntに変換できていないデータがあるのではないか?と聞いています。
guest

回答1

0

ベストアンサー

コードを見た感じの問題点は

  • 適切な型を作る
  • グローバル変数は使わない
  • エラーを処理する

です
もちろん例外はありますが、このあたりは基本です。

適切な型を作る

namepriceを別々の配列で保持していますが本当にそれで良いでしょうか?
これらはともに[food]の属性のはずです。
こういう時はそれにあった型を作ります。

swift

1struct Food { 2 let name: String 3 let price: Int 4// let manufacturer: String 5}

そして、このFoodの配列を持つようにします。

グローバル変数は使わない

そのままです。
この場合はプロパティとして持つようにします。

swift

1class ViewController: UIViewController, UICollectionViewDataSource, UISearchBarDelegate { 2 3 private var foods: [Food] = [] 4 5 ... 6}

エラーを処理する

fuzzballさんがおっしゃるようにdocument.data()["price"] as? Intがnilであるためエラーが発生している可能性があります。
ただし、今のままではそれが当たっているかどうかが分かりません。
こういった場合のためエラー処理をします。

swift

1// Firestoreからデータをもってくる 2private func loadData() { 3 4 // reset foods 5 foods = [] 6 7 let db = Firestore.firestore() 8 db.collection("items").getDocuments() { (querySnapshot, err) in 9 10 if let err = err { 11 print("Error getting documents: (err)") 12 return 13 } 14 15 for document in querySnapshot!.documents { 16 gaurd let name = document.data()["name"] as? String else { 17 print("food name is nil.") 18 return 19 } 20 gaurd let price = document.data()["price"] as? Int else { 21 print(document.data(), "\n", "food price is nil.") 22 return 23 } 24 25 self.foods.append(Food(name: name, price: price)) 26 } 27 DispatchQueue.main.sync { 28 self.collectionViewObj.reloadData() 29 } 30 } 31}

これはいわゆるprintデバッグというもので開発中に行うものです。


これで問題解決には至らずとも問題は絞られます。

投稿2019/07/20 02:57

MasakiHori

総合スコア3384

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問