简体   繁体   中英

How to update data in Cloud Firestore in different views for SwiftUI?

I have multiple views and want to make a change in Firestore database in every different views when button is tapped.

In firstView , I have set my data to Firestore and want to update them in the second view when button is tapped.

I noticed that I can not call Firestore in every different view.

As I'm a beginner, how can I implement data updates in different views?

  import SwiftUI
  import Firebase

  struct firstView: View {
    var body: some View {
      VStack {
        Text("Greetings!")
            
        Button(action: {
          self.writeDatabase()
        }) {
          Text("Next")
        }
      }
    }

    func writeDatabase() {
      let firestoreDatabase = Firestore.firestore()
    
      let firestorePost = [
        "PostedBy": Auth.auth().currentUser!.email!,
        "date": FieldValue.serverTimestamp(), 
        "CityName": "", 
        "DistrictName": ""] as [String : Any]

      firestoreDatabase
        .collection("Posts")
        .document("Dc")
        .setData(firestorePost, merge: true) { error in
        if error != nil {
          print("error")
        }
      }
    }
  }

My second view is as follows:

  import SwiftUI
  import Firebase

  struct secondView: View {
    var body: some View {
      NavigationView {
        VStack {
          Text("Tap to update...")
                
          NavigationLink(destination: good()) {
            Text("Next")
          }
          .onAppear {
            self.update()
          }
        }
      }
    }

    func update() {
        let firestoreDatabase = Firestore.firestore()
        firestoreDatabase
          .collection("Posts")
          .document("Dc")
          .updateData(
            [
              "CityName" : "İstanbul", 
              "DistrictName": "Beşiktaş"
            ]
          ) { (error) in
          if error != nil{
            print("Error")
          }
          else {
            print("succesfully updated")
          }
        }
      }
    }
  }

A couple of notes:

  1. Class names in Swift should start with an uppercase letter, so your views should be named FirstView and SecondView
  2. Instead of assembling your document ( firestorePost ) as a dictionary, you should consider implementing a data object using a struct that implements the Codable protocol:
struct Post: Codable {
  var postedBy: String
  var cityName: String
  var districtName: String
}
  1. You'll then be able to add and update instances of this struct much easier:
  private func addPost(_ post: Post) {
    do {
      let _ = try db.collection("posts").addDocument(from: post)
    }
    catch {
      print(error)
    }
  }

  private func updatePost(_ post: Post) {
    if let documentId = post.id {
      do {
        try db.collection("posts").document(documentId).setData(from: post)
      }
      catch {
        print(error)
      }
    }
  }
  1. Also, retrieving those posts will be easier (again, thanks to Codable ):
class PostsViewModel: ObservableObject {
  @Published var posts = [Post]()
  
  private var db = Firestore.firestore()
  private var listenerRegistration: ListenerRegistration?
  
  deinit {
    unsubscribe()
  }
  
  func unsubscribe() {
    if listenerRegistration != nil {
      listenerRegistration?.remove()
      listenerRegistration = nil
    }
  }
  
  func subscribe() {
    if listenerRegistration == nil {
      listenerRegistration = db.collection("posts").addSnapshotListener { (querySnapshot, error) in
        guard let documents = querySnapshot?.documents else {
          print("No documents")
          return
        }
        
        self.posts = documents.compactMap { queryDocumentSnapshot in
          try? queryDocumentSnapshot.data(as: Post.self)
        }
      }
    }
  }
}
  1. And, finally, try not to put any data access logic into your views. Extract them into view models instead. You can then connect the view to its view model my adding it as an observed object, like so:
@StateObject var viewModel = PostsViewModel()

Check out these articles, which provide more background on how to use SwiftUI with Cloud Firestore:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM