I'm still new to SwiftUI and hope I will be able to explain my problem well.
I followed a tutorial on reading, writing, and deleting data from the Firestore Database in SwiftUI and it all worked. In the tutorial, there is only 1 view used, but I wanted to take it a step further and use further views:
- List View (to show all items)
- Form View (form with fields and function to add items)
- Detail View (shows details of each item and function to delete item)
While I can add new items to my database through Form View and they also show up after going back to List View, when I try to implement the function to delete items in Detail View, XCode throws the error: Cannot convert value of type 'String' to expected argument type 'Model'
I understand I am not using the right parameter in my function, but failing to understand what the right one here is.
Model
import Foundation
struct Model: Identifiable {
var id: String
var name: String
var itemName: String
}
ItemListModel
import Foundation
import FirebaseCore
import FirebaseFirestore
class ItemListModel: ObservableObject {
@Published var list = [Model]()
@Published var name = [Model]()
…
func deleteItem(itemDelete: Model) {
// Get a reference to the database
let database = Firestore.firestore()
// Specifiy the document to delete. Data passed through the method.
database.collection("xxx").document(itemDelete.id).delete { error in
// Check for errors
if error == nil {
// No errors
// Update the UI from the main thread
DispatchQueue.main.async {
// Remove the item that was just deleted
self.list.removeAll { items in
// Check for the item to remove
return items.id == itemDelete.id
}
}
}
}
}
…
}
ItemList
My thinking was to include an ID to tell the function what to delete exactly, so I included it in this file and pass it to the Detail View. Not sure if I need to pass the ID at this point though.
import SwiftUI
struct ItemList: View {
@EnvironmentObject var model: ItemListModel
@State var name = ""
@State var itemName = ""
@State var itemId = ""
var body: some View {
…
ForEach(model.list) { item in
NavigationLink(destination: Detail(name: item.name, itemName: item.itemName, itemId: item.id)) {
HStack {
Text(item.name)
Text(item.itemName)
}
}
}
}
}
Detail
And this is the view where XCode throws the error message Cannot convert value of type 'String' to expected argument type 'Model'.
import SwiftUI
struct Detail: View {
@EnvironmentObject var model: ItemListModel
var name: String
var itemName: String
var itemId: String
var body: some View {
VStack {
Text(name)
Text(itemName)
Button {
// delete (hopefully) the current item
model.deleteItem(itemDelete: itemId) // XCode throws error Cannot convert value of type 'String' to expected argument type 'Model'.
} label: {
Text("Delete")
}
…
}
}
}
Thank you for reading through all of this and I truly hope someone can help me and my confused brain here!
CodePudding user response:
The expected type is Model
. -> deleteItem(itemDelete: Model)
The easy solution is to pass a Model
instance rather than the three strings
struct Detail: View {
@EnvironmentObject var model: ItemListModel
let item: Model
var body: some View {
VStack {
Text(item.name)
Text(item.itemName)
Button {
model.deleteItem(itemDelete: item)
} label: {
Text("Delete")
}
…
}
}
}
and in ItemList
replace
NavigationLink(destination: Detail(name: item.name, itemName: item.itemName, itemId: item.id)) {
with
NavigationLink(destination: Detail(item: item)) {