0

In my app, I have a place to show news, located in one of the 4 tab views. For changing the information, all the aspects related to it are stored in firestore (title, subtitle, text). Currently, I'm using addSnapshotListener to fetch the data, because whenever I change the data in firestore it will automatically and instantly update. However, each time the user clicks on the tabview icon related to the news view, a different call to read data is done. I understand that it would cause lots of readings when the user base grow, causing a higher monthly payment to firebase and maybe delay, right? To fix this, the only solution I think about is changing addSnapshotListener to getDocuments. But, if I do any changes on firestore, the user would need to close the app and then open it to see the updated info. Is there a way to update instantly the info, but only if changes are made in the database?

This is how I get the information from Firestore:

struct Info: Identifiable{ var id: String = UUID().uuidString var title: String var subtitle: String } class InfoViewModel: NSObject, ObservableObject { @Published var infos = [Info]() func fetchData(){ Firestore.firestore().collection("infos").addSnapshotListener { (querySnapshot, error) in guard let documents = querySnapshot?.documents else {return} self.infos = documents.compactMap { (queryDocumentSnapshot) -> Info? in let data = queryDocumentSnapshot.data() if let title = data["title"] as? String, let subtitle = data["subtitle"] as? String{ print("info successful") return Info(title: title, subtitle: subtitle) } else{ print("info failed") return nil } } } } } 

In the view I want to display the info, I have @ObservedObject var infoModel = InfoViewModel(), a ForEach to display the data and then .onAppear(){self.infoModel.fetchData()}

Each time I change to this view when clicking the tabView icon, I get, on debug, 3x "info successful, as I have 3 documents stored on infos collection.

TabBar View:

struct TabBar: View{ @State var current = 0 @StateObject var LocationModel = LocationViewModel() var body: some View{ NavigationView{ TabView(selection: $current) { HomeView() .tag(0) .tabItem { Image(systemName: "house") Text("início") } SearchView(LocationModel: LocationModel) .tag(1) .tabItem { Image(systemName: "magnifyingglass") Text("buscar") } CalendarView() .tag(2) .tabItem { Image(systemName: "calendar") Text("histórico") } AccountView() .tag(3) .tabItem { Image(systemName: (self.current == 3 ? "person.fill" : "person")) Text("perfil") } }.accentColor(Color("Color")) } } } 

Where firestorm data is displayed:

struct HomeView: View{ @StateObject var LocationModel = LocationViewModel() @StateObject var model = ModelData() @ObservedObject var infoModel = InfoViewModel() var body: some View{ VStack( spacing: 12) { ScrollView(.vertical, showsIndicators: false){ ScrollView(.horizontal, showsIndicators: false){ HStack(spacing: 15){ ForEach(infoModel.infos){ info in HStack(spacing: 20){ Text(info.title) .frame(height: 220) .frame(width: 330) .background(Color.yellow) .cornerRadius(18) } } }.padding(.horizontal, 15) .padding(.bottom, 25) } } .navigationBarTitle("").navigationBarHidden(true) }.navigationBarTitle("").navigationBarHidden(true) .onAppear(perform: { LocationModel.locationManager.delegate = LocationModel self.infoModel.fetchData() }) .alert(isPresented: $LocationModel.alert, content: { Alert(title: Text("Mensagem"), message: Text(LocationModel.alertMsg), dismissButton: .destructive(Text("Pronto").foregroundColor(Color.blue))) }) } } 
11
  • You need separation of ui (VC) and data "service", which can be a addSnapshotListener and preserve data for VC to display Commented Dec 16, 2020 at 14:44
  • @KirilS. Hey, thank you for replying. I'm kind of new to Firebase/Swift, so if you have any links to information that could help my I would be grateful. Commented Dec 16, 2020 at 18:04
  • For example: peterfriese.dev/swiftui-firebase-fetch-data Commented Dec 16, 2020 at 18:51
  • This kind of question is very hard to answer as it contains not code so we don't know the use case. For example this a different call to read data is done - we don't know what 'a different call' is or does. We also don't know if there's an issue with other code as well. Please take a moment and review How do I ask a good question? and How to create a Minimal, Complete, and Verifiable example. The Question is also unclear so maybe you can clarify it? Commented Dec 16, 2020 at 19:04
  • Hey Jay, thank you for the feedback. Just added code information Commented Dec 17, 2020 at 1:09

1 Answer 1

1

Your VC could have a reference to a controller that manages all communication with the Firestore. In that controller, you can init the snapshot listener. That will fetch all your documents once, which you can store as state in that controller. Any .added, .modified and .removed document changes from that point on can just change the state your controller is holding and update the VC with e.g. a closure.

Sign up to request clarification or add additional context in comments.

1 Comment

Hey, thank you for replying. I'm kind of new to Firebase/Swift, so if you have any links to information that could help my I would be grateful.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.