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

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

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

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

Cloud Firestore

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

Q&A

解決済

1回答

1241閲覧

Firestoreから取得したデータが正しく表示されない

tomaa

総合スコア84

Firebase

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

Cloud Firestore

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

0グッド

1クリップ

投稿2021/05/22 04:33

前提・実現したいこと

SwiftUIFirebase(FirebaseFirestoreSwift)を利用してアプリの開発をしています。

あるViewを表示する際に、Firestoreからデータを取得し、その中のあるデータを表示したいのですが、実際にFirestoreに保存されているものと、違うデータが表示されてしまいます。

解決の方法ご存知の方おりましたら、ご教授いただきたいです。

発生している問題

以下のようなビューの画面で、タイトルを入力し、[Add]をタップすると、入力した内容がFireStoreCollectionに保存され、その後全てのDocumentを取得し、表示するという動きをしたいのですが正しく表示されません。

イメージ説明

例えば、以下のようになります

  1. AAAと入力し[Add] → AAAと表示される
  2. BBBと入力し[Add] → BBBと表示される
  3. CCCと入力し[Add] → BBBと表示される

この際に、Firebaseのコンソール画面で、データを確認すると入力したとおりに保存されている事を確認できます(AAA,BBB,CCC)。

イメージ説明

該当のソースコード

Swift

1 2import SwiftUI 3import Firebase 4import FirebaseFirestoreSwift 5 6struct GetDataTest: View { 7 8 @State var items:[Item] = [] 9 @State var title:String = "" 10 11 var body: some View { 12 VStack{ 13 List{ 14 ForEach(self.items.indices, id: .self){index in 15 16 ListRowTest( 17 title:self.items[index].title 18 ) 19 20// Text(self.items[index].title) 21// .font(.title) 22// .fontWeight(.bold) 23 } 24 } 25 26 Button(action: { 27 self.getAllItems() 28 }, label: { 29 Text("Update") 30 }) 31 32 TextField("Enter titel",text:self.$title) 33 .textFieldStyle(RoundedBorderTextFieldStyle()) 34 35 Button(action: { 36 37 let item = Item(title: self.title) 38 39 self.addItem(item: item){ (status) in 40 self.getAllItems() 41 } 42 43 self.title = "" 44 }, label: { 45 Text("Add") 46 }) 47 } 48 .onAppear{ 49 self.getAllItems() 50 51 } 52 } 53 54 func getAllItems(){ 55 56 self.items = [] 57 58 let ref = Firestore.firestore() 59 60 ref.collection("Items").getDocuments{ 61 (snap, err) in 62 guard let docs = snap else{return} 63 64 docs.documentChanges.forEach{ (doc) in 65 let item = try! doc.document.data(as:Item.self) 66 self.items.append(item!) 67 } 68 } 69 } 70 71 func addItem(item:Item , completion:@escaping (Bool) -> ()){ 72 73 let ref = Firestore.firestore() 74 75 do{ 76 let _ = try 77 ref.collection("Items").addDocument(from: item){ (error) in 78 if error != nil{ 79 completion(false) 80 return 81 } 82 completion(true) 83 } 84 }catch{ 85 print(error.localizedDescription) 86 completion(false) 87 } 88 } 89} 90 91 92struct ListRowTest: View { 93 94 @State var title:String 95 96 var body: some View { 97 HStack{ 98 Text(title) 99 .font(.title) 100 .fontWeight(.bold) 101 } 102 } 103} 104 105 106struct Item : Identifiable,Codable { 107 108 @DocumentID var id : String? 109 var title : String 110 111 enum CodingKeys : String,CodingKey { 112 case id 113 case title 114 } 115} 116 117

試したこと

ListRowTest( title:self.items[index].title )

のところを、以下のように変更すると、正しく表示されます。
structをコンポーネントとして利用したいので、この方法では解決できません

Text(self.items[index].title) .font(.title) .fontWeight(.bold)

補足情報

Xcode: Version 12.3

iOS: 14.0

Life Cycle: SwiftUI App

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

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

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

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

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

hoshi-takanori

2021/05/22 22:27

ForEach で id に \.self つまり index を使ってるためでしょうね。 Item は Identifiable なので、ForEach(self.items) { item in とすれば良いのでは。
tomaa

2021/05/23 12:46

コメントありがとうございます。 この先の開発の仕様の関係で、配列データのindexの利用が必要になるので、ForEach(self.items) { item inの使い方ができないのです。
guest

回答1

0

ベストアンサー

ListRowTestで宣言しているtitle変数は、インスタンス生成時の引数で値を渡すようにしていると思いますが、その変数の宣言が

swift

1@State var title:String

となっています。

インスタンス生成時の引数で値を渡す変数で、変数の値を更新しないものであれば、@State をつけずに var title:String で宣言すべき(変数の値を更新するものであれば、 @Binging で宣言し、生成元はProjected Valueを渡すべき)だと思います。

内部の動作状況を確認してみたところ、@State をつけた変数をインスタンス生成時の引数に指定しても、正しく値が設定されていないようでした。そのため、不正な値が表示されたのではないかと思います。

投稿2021/05/23 13:41

TakeOne

総合スコア6299

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

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

tomaa

2021/05/23 14:00

回答いただきありがとうございます。 `@State`を付けずに`var title:String`にすると、期待どおりに動作するようになりました! アドバイスありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問