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

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

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

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

Cloud Firestore

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

Swift

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

Q&A

解決済

1回答

606閲覧

Firebaseからデータ取得した際、同じデータが保存されているデータの個数分取れてしまう

shun_app

総合スコア1

Firebase

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

Cloud Firestore

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

Swift

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

0グッド

0クリップ

投稿2022/12/14 22:33

前提

タイトルにも書いたのですが、Firebaseに保存されているデータを取得して、アプリで確認したところ、保存されているデータの個数分、同じデータが取得されてしまいます。
例として、FirebaseFirestoreにドキュメントIDとしてAAA,BBB,CCC,DDDと保存されているとして、この4つのデータを取得しようと思ったところ、一番先頭のAAAのデータが4つ取得されてしまいます。
ドキュメントIDを指定すればそのデータは取れるのですが、やりたいこととしてまして、全件取得をしたいです。
ご教授お願いします。
ここに質問の内容を詳しく書いてください。

実現したいこと

上記で記載の通り、登録されているデータの全件取得を行いたいです。

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

エラーメッセージではありませんが現象として、下記のキャプチャのようになってしまいます。
イメージ説明
下記がFirebaseに登録されているデータですが、一番上のデータが3回取得されます。
イメージ説明

該当のソースコード

// データ取得 import Foundation import Firebase import FirebaseFirestore class GetInfoViewModel: ObservableObject { @Published var things = [Thing]() init() { // Task { // try await fetchUser() // } fetchThings() } func fetchThings() { COLLECTION_THINGS.getDocuments { snapshot, _ in guard let documents = snapshot?.documents else { return } self.things = documents.map({Thing(thingsDictionary: $0.data())}) print("\(self.things)") } } }
// モデル import Foundation import Firebase class Thing: Identifiable { let id: String let imageURL: String //画像URL let thingsName: String //名称 let expirationDate: Timestamp //使用期限 let numberOfItems: Int //所持数 let place: String //保管場所 let classification: String //分類 let memo: String //メモ let userID: String //ユーザID(ログインしているユーザ) init(thingsDictionary: [String : Any]) { id = thingsDictionary["id"] as? String ?? "" imageURL = thingsDictionary["imageURL"] as? String ?? "" thingsName = thingsDictionary["thingsName"] as? String ?? "" expirationDate = thingsDictionary["expirationDate"] as? Timestamp ?? Timestamp(date: Date()) numberOfItems = thingsDictionary["numberOfItems"] as? Int ?? 0 place = thingsDictionary["place"] as? String ?? "" classification = thingsDictionary["classification"] as? String ?? "" memo = thingsDictionary["memo"] as? String ?? "" userID = thingsDictionary["userID"] as? String ?? "" } }
// 取得データの表示 import SwiftUI import Kingfisher struct MainView: View { @State private var isShowingAddThingsView = false @State private var isShowingSettingView = false @ObservedObject var getInfoVM = GetInfoViewModel() @EnvironmentObject var authVM: AuthViewModel var body: some View { if authVM.userSession != nil { NavigationView { ZStack{ List{ ForEach(getInfoVM.things){thing in Section(){ HStack{ KFImage(URL(string: thing.imageURL)) .resizable() .frame(width: 100, height: 100) NavigationLink(destination: DetailView(thing: thing)) { Text(thing.thingsName) Text("\(thing.expirationDate.dateValue(), formatter: dateFormat)") } } } } } .listStyle(PlainListStyle()) VStack{ Spacer() Button(action: {self.isShowingAddThingsView.toggle()}) { PlusButton() } AdmobBannerView() } .fullScreenCover(isPresented: $isShowingAddThingsView){ NavigationView{ AddThingsView(showingAddThingsView: $isShowingAddThingsView) } } } .navigationBarTitle("使用期限リスト", displayMode: .inline) .navigationBarBackButtonHidden(true) .toolbar { ToolbarItem(placement: .navigationBarLeading) { Button(action: { isShowingSettingView.toggle() }) { Text("設定") .foregroundColor(Color("BlueEyes")) } } } .fullScreenCover(isPresented: $isShowingSettingView) { SettingView(isShowingSettingView: $isShowingSettingView) } } } else { LoginView() } } } }

試したこと

Firebaseの公式リファレンスをメインに実装しました。

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

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

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

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

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

guest

回答1

0

ベストアンサー

コードの内容を見ると、Thing構造体はIdentifiableに準拠していてidプロパティを持っていますから、その配列が格納されているgetInfoVM.things をForEachで表示する場合、idプロパティを見て同一データか否か識別します。

今の処理は、Firestoreに保存されているidを読み込むようになっていますから、Thingsを書き込む時に、他と重複しない値をidに設定してFirestoreに書き込んでおく必要があります。このidを正しく書き込んでいるか確認してみてください。idがそれぞれのデータごとに別々の値になるように設定されていないと、ForEachの表示はおかしくなります。

Thing構造体のidを自分で払い出してFirestoreに書き込むのではなく、Firestoreが自動的に払い出したドキュメントIDにしたいのであれば、Things読み込み時にFirestoreに保存されているidを読み込むのではなく、読み込んだドキュメントのdocumentIDをThings構造体のidに設定すればいいです。

投稿2022/12/15 02:04

編集2022/12/15 02:07
TakeOne

総合スコア6299

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

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

shun_app

2022/12/17 23:07

返信遅くなり大変申し訳ございません。 ご回答ありがとうございます。 いただいた内容をもとに、検証してみたいと思います。
shun_app

2022/12/25 22:25

TakeOneさん firestoreへのidの設定がおかしかったため、修正したところ、正常に表示されるようになりました。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問