繁体   English   中英

使用 SwiftUI 从 Firestore 获取数据

[英]Get data from Firestore with SwiftUI

我有一个 class,我从 Firebase 获取数据。 但是我不能完全按照我的意愿得到它,例如 document("abc") 这里我需要从另一个地方获取名称“abc”,每次点击可能会出现不同的名称。

我无法将其分配给我从中获取数据的 class,您能帮帮我吗?

import SwiftUI
import Firebase


struct StadiumNameView: View {
        
    var body: some View {
        VStack{
            List(stadiumnameeeee) { i in
                NavigationLink(destination: SelectedStadiumView(selectedStadium:i.name)){
                    Text(i.name)
                }
                
            }
        }
    }
}

struct StadiumNameView_Previews: PreviewProvider {
    static var previews: some View {
        StadiumNameView()
    }
}

我需要将此处的“i.name”传递给以下 class。

import SwiftUI
import Firebase

class UserInfoModel : ObservableObject {
    
    @Published var city=""
    @Published var email=""
    @Published var name=""
    @Published var surname=""
    @Published var phone=""
    @Published var town=""
    @Published var type=""
    @Published var id=""
    @Published var birthday=""
    @Published var favStadium=[String]()
    
    init(){
        let db=Firestore.firestore()
        db.collection("Users").document(Auth.auth().currentUser!.uid).addSnapshotListener { (snapshot, error) in
            if error == nil {
    
                if let city=snapshot?.get("City") as? String {
                    self.city=city
                }
                if let email=snapshot?.get("Email") as? String {
                    self.email=email
                }
                if let name=snapshot?.get("Name") as? String {
                    self.name=name
                }
                if let surname=snapshot?.get("Surname") as? String {
                    self.surname=surname
                }
                if let phonenumber=snapshot?.get("Phone") as? String {
                    self.phone=phonenumber
                }
                if let town=snapshot?.get("Town") as? String {
                    self.town=town
                }
                if let type=snapshot?.get("Type") as? String {
                    self.type=type
                }
                if let id=snapshot?.get("User") as? String {
                    self.id=id
                }
                if let birthday=snapshot?.get("DateofBirth") as? String {
                    self.birthday=birthday
                }
                if let favStadiums=snapshot?.get("FavoriteStadiums") as? [String]{
                    self.favStadium=favStadiums
                }
            }
        }
    }
}

而不是使用 class,您应该 model 将您的数据对象作为结构,然后实现一个包含这些结构集合的视图 model。

此外,考虑使用 Codable 而不是手动映射数据。

这是您的代码的更新版本:

看法

import SwiftUI
// import Firebase --> No need to import Firebase in the view


struct StadiumNameView: View {
  @StateObject userViewModel: UserViewModel()
        
  var body: some View {
    VStack {
      List(userViewModel.users) { user in
       Text(user.name)
     }
   }
  }
}

struct StadiumNameView_Previews: PreviewProvider {
  static var previews: some View {
    StadiumNameView()
  }
}

Model

import Firebase 

struct UserInfoModel: Codable, Identifiable {
  @DocumentID var id: String?
  var city = ""
  var email = ""
  var name = ""
  var surname = ""
  var phone = ""
  var town = ""
  var type = ""
  var id = ""
  var birthday = ""
  var favStadium = [String]()
}

查看 Model

class UserViewModel: ObservableObject {
  @Published var users = [UserInfoModel]()
  @Published var errorMessage: String?
  
  private var db = Firestore.firestore()
  private var listenerRegistration: ListenerRegistration?
  
  public func unsubscribe() {
    if listenerRegistration != nil {
      listenerRegistration?.remove()
      listenerRegistration = nil
    }
  }
  
  func subscribe() {
    if listenerRegistration == nil {
      listenerRegistration = db.collection("users")
        .addSnapshotListener { [weak self] (querySnapshot, error) in
          guard let documents = querySnapshot?.documents else {
            self?.errorMessage = "No documents in 'users' collection"
            return
          }
          
          self?.users = documents.compactMap { queryDocumentSnapshot in
            let result = Result { try queryDocumentSnapshot.data(as: UserInfoModel.self) }
            
            switch result {
            case .success(let userInfo):
              if let userInfo = userInfo {
                // A UserInfoModel value was successfully initialized from the DocumentSnapshot.
                self?.errorMessage = nil
                return userInfo
              }
              else {
                // A nil value was successfully initialized from the DocumentSnapshot,
                // or the DocumentSnapshot was nil.
                self?.errorMessage = "Document doesn't exist."
                return nil
              }
            case .failure(let error):
              // A UserInfo value could not be initialized from the DocumentSnapshot.
              switch error {
              case DecodingError.typeMismatch(_, let context):
                self?.errorMessage = "\(error.localizedDescription): \(context.debugDescription)"
              case DecodingError.valueNotFound(_, let context):
                self?.errorMessage = "\(error.localizedDescription): \(context.debugDescription)"
              case DecodingError.keyNotFound(_, let context):
                self?.errorMessage = "\(error.localizedDescription): \(context.debugDescription)"
              case DecodingError.dataCorrupted(let key):
                self?.errorMessage = "\(error.localizedDescription): \(key)"
              default:
                self?.errorMessage = "Error decoding document: \(error.localizedDescription)"
              }
              return nil
            }
          }
        }
    }
  }
  
}

有关如何使用 Codable 的更多详细信息,请查看我的文章Mapping Firestore Data in Swift - 综合指南 GitHub 上也提供了所有代码: peterfriese/Swift-Firestore-Guide:在 Swift 中使用 Cloud Firestore 的综合指南

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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