SwiftUI - 更新 Firebase 实时数据库上的数据

SwiftUI - Update data on Firebase's Realtime database

我已成功将数据显示到 UI,但我希望用户在点击“保存”按钮时能够再次更新我的数据。希望你能帮助我!

简介



I have successfully displayed the data to the UI, but I want the user to be able to update my data again when tapping the "Save" button . Hope you can help me!


有很多方法可以实现您想要的。这只是一种方法,通过 将 profileViewModel 传递给 EditProfile:

class ProfileViewModel: ObservableObject {
    @Published var user = Profile(id: "", image: "", birthDay: "", role: [], gender: "", name: "")
    private var ref: DatabaseReference = Database.database().reference()

    func fetchData(userId: String? = nil) {
        // 8hOqqnFlfGZTj1u5tCkTdxAED2I3
        ref.child("users").child(userId ?? "default").observe(.value) { [weak self] (snapshot) in
            guard let self = self,
                  let value = snapshot.value else { return }
            do {
                print("user: \(value)")
                self.user = try FirebaseDecoder().decode(Profile.self, from: value)
            } catch let error {
                print(error)
            }
        }
    }
    
    func saveUser() {
        // save the user using your ref DatabaseReference
        // using setValue, or updateChildValues 
        // see https://firebase.google.com/docs/database/ios/read-and-write
    }
}

struct EditProfile: View {
    @ObservedObject var profileViewModel: ProfileViewModel  // <--- here
    var body: some View {
        VStack {
            Text(profileViewModel.user.name)  // <--- you probably meant TextField
                .font(.custom("Poppins-Regular", size: 15))
                .foregroundColor(Color.black)
            Text("\(profileViewModel.user.birthDay)!")
                .font(.custom("Poppins-Regular", size: 22))
                .fontWeight(.bold)
                .foregroundColor(Color.black)
            Text("\(profileViewModel.user.gender)")
                .font(.custom("Poppins-Regular", size: 22))
                .fontWeight(.bold)
                .foregroundColor(Color.black)
            Text(profileViewModel.user.role.first ?? "")
                .font(.custom("Poppins-Regular", size: 22))
                .fontWeight(.bold)
                .foregroundColor(Color.black)
           
       Button(action: {
            // save the profileViewModel.user to database
            profileViewModel.saveUser()  // <--- here
            }) {
                Text("Save")
            }

        }
        .padding()
    }
}
struct CategoriesView: View {
    @ObservedObject var viewModel = SectionViewModel()
    @EnvironmentObject var loginViewModel : LoginViewModel
    @StateObject var profileViewModel = ProfileViewModel()
    
    var body: some View {
            ZStack {
                VStack (alignment: .leading, spacing:0) {
                    EditProfile(profileViewModel: profileViewModel)  // <--- here
                        .padding()
                        .padding(.bottom,-10)
                 }
             }
          .onAppear() {
                self.viewModel.fetchData()
                profileViewModel.fetchData(userId: loginViewModel.session?.uid)
            }
        }
}

EDIT1:关于更新的代码。

在您的新代码中,在 ProfileHost 中您没有传递 ProfileViewModel。 使用:

NavigationLink(destination: ProfileEditor(profileViewModel: viewModel)) {
     ProfileRow(profileSetting: profile)
}
                        

并在 ProfileEditor 中将 profile 替换为 profileViewModel.user
您可能需要调整 profileItem 并将其放入 .onAppear {...} 中。像这样:

struct ProfileEditor: View {
    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
    @ObservedObject var profileViewModel: ProfileViewModel
    @EnvironmentObject var loginViewModel: LoginViewModel
    
    let profileLabel: [String] = ["Name", "Account", "Gender", "Role", "Email"]
    @State var profileItem: [String] = []
    @State var profileEditorRow: [ProfileEditorItem] = []
    
    var body: some View {
        VStack {
            ForEach(profileEditorRow) { editor in
                if editor.id == 5 {
                    ProfileEditorRow(editor: editor, showLastLine: true)
                } else {
                    ProfileEditorRow(editor: editor, showLastLine: false)
                }
            }
            Button("Save") {
                profileViewModel.updateData(userId: loginViewModel.session?.uid)
            }
        }
        .onAppear {
            profileItem = [profileViewModel.user.name,
                           profileViewModel.user.birthDay,
                           profileViewModel.user.gender,
                           profileViewModel.user.role.first ?? "",
                           profileViewModel.user.birthDay]

            for n in 1...5 {
                profileEditorRow.append(ProfileEditorItem(id: n, label: profileLabel[n-1], item: profileItem[n-1]))
            } 
        }
    }
    
}

EDIT2:更新函数

func updateData() {
    ref.("users").child(user.id).updateChildValues([
        "name": user.name,
        "birthDay": user.birthDay,
        "gender": user.gender,
        "role": user.role.first ?? ""])
}

并在 ProfileEditor 中使用它:

        Button("Save") {
             profileViewModel.updateData()
         }