|
Hello i want to rewrite code from Swift to SwiftUI but i cant
i got Generic struct 'ForEach' requires that '[String : [Any]]' conform to 'RandomAccessCollection'
this is my. code
let content = try! String(contentsOf: myURL!, encoding: .ascii)
let test = content.data(using: .utf8)!
let dict = try! JSONSerialization.jsonObject(with: test) as? [String:[Any]]
View:
struct ContentView: View {
private var test = dict
var body: some View {
List {
ForEach(test!.indices, id: .self) { index in
Text(index)
}
}
}
}
Image:
(if image doesnt show https://postimg.cc/xNGw49J7

|
|
Dictionary doesn't conform to RandomAccessCollection .
It's a little hard to suggest alternative approaches with so little code to tell us just what you're trying to do. But I would suggest 1) use Codable instead of JSONSerialization , and 2) figure out what it is you're actually trying to list and use that instead of a Dictionary .
|
|
Just sort the dictionary with something like - ForEach(item.sorted(by: >), id: \.key) { key, value in then do as you wish with key or value
|
Sponsor Hacking with Swift and reach the world's largest Swift community!
|
|
i dont want to work with hardcoded datatypes(create struct...). because in json (each object has array) can be added new objects, (from database). and i want to read that objects from json. i want to rewrite the code to SwiftUI. i did that in swift correctly with this code:
example json:
{
"Burgres": [
{
"food_name": "Hovadzi Burger",
"food_description": "Najlepsi burger na svete, uhorka, cibula, majoneza, masko a tak dalej",
"alergens": "1, 3, 6"
},
],
}
swift code :
func makeGetCall() {
guard let myURL = URL(string: "xxxxxx") else {
print("Error: \(String(describing: link)) doesn't seem to be a valid URL")
return
}
do {
let content = try String(contentsOf: myURL, encoding: .ascii)
let test = content.data(using: .utf8)!
if let dict = try JSONSerialization.jsonObject(with: test) as? [String:[Any]] {
for k in dict{
print(k.key)
for i in k.value{
let tmp_i = i as! NSDictionary
for (k,v) in tmp_i
{
print("\(k):\(v)")
}
print("\n")
}
print("---------------------------\n")
}
}
}
catch {
print(error)
}
}
|
|
can you try this , is this what you want ? no error so far , gives me Burgres in list
let dataFood = """
{
"Burgres": [
{
"food_name": "Hovadzi Burger",
"food_description": "Najlepsi burger na svete, uhorka, cibula, majoneza, masko a tak dalej",
"alergens": "1, 3, 6"
},
],
}
"""
.data(using: .utf8)!
struct ContentView: View {
private var test: [String: [Any]] = try! JSONSerialization.jsonObject(with: dataFood) as! [String:[Any]]
var body: some View {
List {
ForEach(test.keys.sorted(), id:\.self) { index in
Text(index)
}
}
}
}
|
|
@AmitShrivastava
yes but what if i want to access food_name(variable and value and print it) in every object, in dictionary
for example:
food_name : Hovadzi Burger
update :
let dataFood = """
{
"Burgres": [
{
"food_name": "Hovadzi Burger",
"food_description": "Najlepsi burger na svete, uhorka, cibula, majoneza, masko a tak dalej",
"alergens": "1, 3, 6"
},
],
}
"""
.data(using: .utf8)!
struct Food: Codable, Hashable {
let food_name : String
let food_description : String
let alergens : String
}
struct ContentView: View {
//private var test: [String: [Any]] = try! JSONSerialization.jsonObject(with: dataFood) as! [String:[Food]]
private var food = try! JSONDecoder().decode([Food].self, from: dataFood)
var body: some View {
List {
ForEach(food, id: \.self) { index in
Text("\(index.food_name)")
}
}
}
}```
but i got this 
https://imgur.com/9B3nas6 if wont show
|
|
@localhost - the error can be resolved by using
private var food = try? JSONDecoder().decode([Food].self, from: json)
ForEach(food ?? [], id: \.self)
But its not showing any thing on list, i tried a few things myself, but its not giving the results
|
|
@AmitShrivastava
Im trying something like this: but i get Generic struct 'ForEach' requires that '[Welcome : [Food]]?' conform to 'RandomAccessCollection
let content = try! String(contentsOf: myURL!, encoding: .ascii)
let test = content.data(using: .utf8)!
let dict = try! JSONSerialization.jsonObject(with: test) as? [Welcome:[Food]]
struct Food: Codable, Hashable {
let name, Description, alergens: String
enum CodingKeys: String, CodingKey {
case name
case Description = "description"
case alergens
}
}
struct Welcome: Codable, Hashable {
let food_type: [Food]
}
struct ContentView: View {
private var test = dict
var body: some View {
Text("Text")
ForEach(test){ key in
Text(key)
}
}
}
|
|
In SwiftUI, ForEach will require that you give it a RandomAccessCollection . However, there are ways to iterate through a dictionary using ForEach if you know what all of the keys are, and can make a RandomAccessCollection out of them.
struct ContentView: View {
let dictionary: [String: Int] = ["Hello": 1, "Hi": 2, "Hey": 3, "Wassup?": 4]
let dictionaryKeys = ["Hello", "Hi", "Hey", "Wassup?"]
var body: some View {
List {
ForEach(dictionaryKeys, id: \.self) { greeting in
if let value = dictionary[greeting] {
Text("\(value)")
}
}
}
}
}
I don't know how helpful this will be in your case. But maybe it will be useful.
|
|
You don't even need to know the keys beforehand:
ForEach(Array(dictionary.keys), id: \.self) { greeting in
Text("\(dictionary[greeting]!)")
}
And, bonus, you don't need the check for a nil value since we know the key exists in the Dictionary .
Or, if you object to the force unwrap on principle or from an abundance of caution, you can enumerate the elements of the Dictionary :
ForEach(Array(dictionary.enumerated()), id: \.0) { (_, elem) in
//elem is a (key, value) pair
Text("\(elem.value)")
}
|
|
Lol... I was trying to figure out how to use dictionary.keys instead, but couldn't think of how to make it into an array rather than a Set.
Easy, Array(dictionary.keys) !
Thanks. I don't know why I couldn't think of that.
|