I am working on a Swift project where I need to display an array of dictionaries in a List. I cannot get the formatting to work in keep running into random errors like it's not expecting a [NSDictionary] type of binding errors.
My array is like so:
items = [{"name": "jack"}, {"name" : "joe"}, {"name" : "john"}]
Where each dictionary is an NSDictionary. I tried doing some sort of List{ ForEach()}
but that also wasn't working. I feel like this data set-up is pretty common, and looping through the list of dictionaries to complete a list shouldn't be too hard.
List(items) {item in
Text(items.name)
}
Something as simple as this I've seen work elsewhere, but gives me an error of:
Cannot convert value of type '[NSDictionary]' to expected argument type 'Binding<Data>'
Generic parameter 'Data' could not be inferred
Initializer 'init(_:)' requires that 'Binding<Subject>' conform to 'StringProtocol'
CodePudding user response:
Isn't that a typo? It should be item.name
instead of items.name
. Items is the list itself, you are suppose to past the item object to the UI.
List(items) {item in
Text(item.name)
}
CodePudding user response:
You could try this approach, as shown in the example code in SwiftUI.
Since you require an array of dictionaries, you need 2 ForEach
loops,
one over the array of dictionaries, and one over the keys of a particular dictionary.
Note, it is somewhat simpler if you use Dictionary
instead of NSDictionary
.
struct ContentView: View {
@State var items: [NSDictionary] = [["name" : "jack"], ["name" : "joe"], ["name" : "john"]]
var body: some View {
List {
ForEach(items, id: \.self) { item in // <-- loop over the dictionaries
ForEach(item.allKeys as! [String], id: \.self) { key in // <-- loop over dictionary keys
Text(item[key] as? String ?? "")
}
}
}
}
}
If you are only going to have "name"
as the only key in the dictionary, then you can use this:
List {
ForEach(items, id: \.self) { item in
Text(item["name"] as? String ?? "")
}
}
Another approach, if you have only name
as key:
struct ContentView: View {
@State var items: [NSDictionary] = [["name" : "jack"], ["name" : "joe"], ["name" : "john"]]
var body: some View {
List(items.compactMap{ ($0.allValues.first as? String)}, id: \.self) { name in
Text(name)
}
}
}
Using a Dictionary
such as [String:String]
:
struct ContentView: View {
@State var items = [["name" : "jack"], ["name" : "joe"], ["name" : "john"]]
var body: some View {
List(items, id: \.self) { item in
Text(item["name"] ?? "")
}
}
}