首页 > 解决方案 > 调用 init() 以查看提取 firebase 数据的最佳方式?

问题描述

我有一个SearchView()

struct SearchView: View {

@ObservedObject var searchViewModel = SearchViewModel()
init() {
    searchViewModel.LoadAllUsers()
}

var body: some View {
    NavigationView {
        VStack {
            List {
                ForEach(searchViewModel.allUsers, id: \.uid) { user in
                    ......
                }
            }
        }
    }
}

在我的SearchViewModel我有一个函数可以从firebase获取所有用户并将它们存储在@Published allUsers数组中:

@Published var allUsers: [User] = []

func LoadAllUsers() {
     Firestore.firestore().collection("users").document(Auth.auth().currentUser!.uid).getDocument{(snapshot, error) in
    ....
}

每次我单击SearchView()它正在运行并运行该函数并调用 firebase 并获取数据时。这是最好的方法吗?从长远来看,这会增加firebase的成本吗?有没有办法在每次加载应用程序时而不是每次加载时调用此函数SearchView()

更新

var window: UIWindow?
var searchViewModel = SearchViewModel()

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
    // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
    // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).

    // Create the SwiftUI view that provides the window contents.
    //let contentView = ContentView()
    
    searchViewModel.LoadAllUsers()
    
    // Use a UIHostingController as window root view controller.
    if let windowScene = scene as? UIWindowScene {
        let window = UIWindow(windowScene: windowScene)
        window.rootViewController = UIHostingController(rootView: InitialView().environmentObject(SessionStore()).environmentObject(searchViewModel))
        self.window = window
        window.makeKeyAndVisible()
    }
}

在我的 SearchViewModel 中,由于以下原因而出现问题:

Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value

由于以下原因:

Auth.auth().currentUser!.uid

标签: swiftfirebaseswiftui

解决方案


在这种情况下,将其SceneDelegate作为环境对象放入并注入层次结构中是合适的,例如

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    var window: UIWindow?
    var searchViewModel = SearchViewModel() // create

    ...
    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {

       searchViewModel.LoadAllUsers()        // << preload !!
       ...
       let contentView = ContentView().environmentObject(searchViewModel) // << inject !!

struct SearchView: View {
    @EnvironmentObject var searchViewModel: SearchViewModel    // << use !!
    // nothing in init


推荐阅读