转义闭包捕获变异的“自我”参数Firebase [英] Escaping closure captures mutating 'self' parameter, Firebase

查看:88
本文介绍了转义闭包捕获变异的“自我”参数Firebase的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码,如何在不将结构更改为类的情况下完成此操作。转义转义捕获突变的'self'参数,

I have the following code, How can i accomplish this without changing struct into class. Escaping closure captures mutating 'self' parameter,

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

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 不适合加载某些外部数据。

SwiftUI view can be created (recreated) / copied many times during rendering cycle, so View.init is not appropriate place to load some external data. Use instead dedicated view model class and load explicitly only when needed.

Like

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()
         }
    }
}

这篇关于转义闭包捕获变异的“自我”参数Firebase的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆