簡體   English   中英

Escaping 閉包捕獲變異的“自我”參數,Firebase

[英]Escaping closure captures mutating 'self' parameter, Firebase

我有以下代碼,如何在不將結構更改為 class 的情況下完成此操作。 Escaping 閉包捕獲變異的“自我”參數,

struct RegisterView:View {
    var names = [String]()

    private func LoadPerson(){
        FirebaseManager.fetchNames(success:{(person) in
        guard let name = person.name else {return}
        self.names = name //here is the error
    }){(error) in
        print("Error: \(error)")
    }

    init(){
        LoadPerson()
    }a
    
    var body:some View{
        //ui code
    }
}

Firebasemanager.swift

struct FirebaseManager {
    
    func fetchPerson(
        success: @escaping (Person) -> (),
        failure: @escaping (String) -> ()
    ) {
        Database.database().reference().child("Person")
        .observe(.value, with: { (snapshot) in
            if let dictionary = snapshot.value as? [String: Any] {
                success(Person(dictionary: dictionary))
            }
        }) { (error) in
            failure(error.localizedDescription)
        }
    }
}

SwiftUI 視圖可以在渲染周期中多次創建(重新創建)/復制,因此View.init不適合加載一些外部數據。 改用專用視圖 model class 並僅在需要時顯式加載。

喜歡

class RegisterViewModel: ObservableObject {
    @Published var names = [String]()

    func loadPerson() {
// probably it also worth checking if person has already loaded
//      guard names.isEmpty else { return }

        FirebaseManager.fetchNames(success:{(person) in
        guard let name = person.name else {return}
        DispatchQueue.main.async {
           self.names = [name]
        }
    }){(error) in
        print("Error: \(error)")
    }
}

struct RegisterView: View {

    // in SwiftUI 1.0 it is better to inject view model from outside
    // to avoid possible recreation of vm just on parent view refresh
    @ObservedObject var vm: RegisterViewModel

//    @StateObject var vm = RegisterViewModel()   // << only SwiftUI 2.0

    var body:some View{
       Some_Sub_View()
         .onAppear {
            self.vm.loadPerson()
         }
    }
}

使names屬性@State變量。

struct RegisterView: View {
    @State var names = [String]()

    private func LoadPerson(){
        FirebaseManager.fetchNames(success: { person in
            guard let name = person.name else { return }
            DispatchQueue.main.async {
                self.names = [name]
            }
        }){(error) in
            print("Error: \(error)")
        }
    }
    //...
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM