Attempting to update values in my database. I checked and the type of ema.updatedIngredients that I’m passing to saveFunctions is a valid type in firestore.
The saveRecipe function works fine if I would use updateData. It deletes the documents as expected, but I know I’m pointing to the right document.
I can also add documents fine, it is when I am deleting an ingredients and updating the data where it doesn’t work.
Save Recipe function to Firebase
func saveRecipe(ingredientList: [String: String], currentRecipe: String){
guard let uid = FirebaseManager.shared.auth.currentUser?.uid else {
return
}
FirebaseManager.shared.firestore
.collection("users")
.document(uid)
.collection("userRecipes")
.whereField("recipeID", isEqualTo: currentRecipe)
.getDocuments() { (querySnapshot, err) in
if let err = err {
print("Error getting documents: (err)")
} else {
for document in querySnapshot!.documents {
FirebaseManager.shared.firestore
.collection("users")
.document(uid)
.collection("userRecipes")
.document(document.documentID)
.setData(["ingredientItem" : ingredientList], merge: true)
print("Updated Recipe")
}
}
}
}
Where I call saveFunction
.toolbar{
ToolbarItem(placement: .navigationBarTrailing){
Button(action: {
ema.editMode.toggle()
//if user is saving when complete is on the button
if !ema.editMode {
//saving to firestore
rm.saveRecipe(ingredientList: ema.updatedIngredients, currentRecipe: recipeID)
}
}){
HStack{
Image(systemName: !ema.editMode ? "pencil.circle" : "")
.foregroundColor(.black)
Text(!ema.editMode ? "Edit" : "Complete")
.foregroundColor(.black)
}
}
}
}
}
}
My View
struct RecipeIngredients: View {
@State private var sheetMode: SheetMode = .quarter
@State private var sizing = ""
@State private var description = ""
@ObservedObject var rm = RecipeLogic()
@ObservedObject var ema: EditModeActive
@Binding var currentRecipeID: String
@Binding var ingredients: [String: String]
//turn into Ordered Dictionary so I can grab ingredients key
func turnIntoDictionary(regularDictionary: [String: String]) -> OrderedDictionary <String, String>{
var dict = OrderedDictionary <String, String> (
uniqueKeys: regularDictionary.keys,
values: regularDictionary.values
)
dict.sort()
return dict
}
private func listContent(for keys: [String]) -> some View {
ForEach(keys, id: .self) { key in
HStack{
Text(key)
.font(.title2)
.foregroundColor(.green)
.fontWeight(.bold)
Text(turnIntoDictionary(regularDictionary: ingredients)[key] ?? "default")
.font(.title3)
}
}
.onDelete { indexSet in
if ema.editMode{
let key = turnIntoDictionary(regularDictionary: ingredients).keys[indexSet.first!]
self.ingredients.removeValue(forKey: key)
ema.updatedIngredients = ingredients
}
}
}
var body: some View {
ZStack{
VStack{
if ema.editMode{
HStack{
TextField("ex. 1 cup", text: $sizing)
.font(.body)
.padding(.leading, 30)
TextField("ex. Chicken Breast", text: $description)
.font(.body)
}
.padding(.top, 25) //set to give space from ingredient/direction section
Button(action: {
if (sizing != "" && description != ""){
ingredients[sizing] = description
ingredients[sizing] = description
ema.updatedIngredients[sizing] = description
sizing = ""
description = ""
}
})
{
Image(systemName: "plus.circle.fill")
.foregroundColor(.blue)
.padding(.leading, 20)
.padding(.top, 20)
.opacity(!sizing.isEmpty && !description.isEmpty ? 1.0 : 0.5)
Spacer()
}
.padding(.top, -10)
.padding(.bottom, 10)
}
List{
self.listContent(for: Array(turnIntoDictionary(regularDictionary: ingredients).keys))
}
.onAppear{
ema.updatedIngredients = ingredients
}
.listStyle(SidebarListStyle())
}
}
}
}
EDIT: For further confusion, if I print right before calling the function, it prints the correct keys/values.
print(ema.updatedIngredients)
rm.saveRecipe(ingredientList: ema.updatedIngredients, currentRecipe: recipeID)
3
Answers
Almost ashamed to admit the simplicity of this solution. Once I went from
setData
toupdateData
it worked as expected.Figured I would share in case someone runs into a similar issue.
I don’t know how in Swift, but in JavaScript you need to pass
{merge: true}
as a second positional argument into.setData()
, and it will update the document like.updateData()
does.Example:
There are two methods for updating:
1 .
set()
– Sets data on the document, overwriting any existing data. If the document does not yet exist, it will be created.2 .
update()
– Updates data on the document. Data will be merged with any existing document data. If no document exists yet, the update will fail.== In flutter ==
To update a value in the document
To add a new value to the existing document.
So in your case
update()
is more suited thanset()