Swiftui Iterating Through Dictionary With Foreach

SwiftUI iterating through dictionary with ForEach

Simple answer: no.

As you correctly pointed out, a dictionary is unordered. The ForEach watches its collection for changes. These changes includes inserts, deletions, moves and update. If any of those changes occurs, an update will be triggered. Reference: https://developer.apple.com/videos/play/wwdc2019/204/ at 46:10:

A ForEach automatically watches for changes in his collection

I recommend you watch the talk :)

You can not use a ForEach because:

  1. It watches a collection and monitors movements. Impossible with an unorered dictionary.
  2. When reusing views (like a UITableView reuses cells when cells can be recycled, a List is backed by UITableViewCells, and I think a ForEach is doing the same thing), it needs to compute what cell to show. It does that by querying an index path from the data source. Logically speaking, an index path is useless if the data source is unordered.

Loop through Dictionary in SwiftUI

I recommend to map the (keys of the) dictionary to an array of a region struct

struct Region { 
let name : String
let countries : [Country]
}

This can be used in a ForEach statement with id: \.name. Further consider that a dictionary is unordered.

This is a simple example with a string array representing the countries

let dictionary = ["Asia": ["Japan", "India"], "Europe": ["Italy", "Norway"]]

struct Region {
let name : String
let countries : [String]
}

let regions = dictionary
.keys
.sorted()
.map{Region(name: $0, countries: dictionary[$0]!)}


NavigationView {
List {
ForEach(regions, id: \.name) { region in

}
}
}

How use use SwiftUI ForEach with a dictionary [ customEnum : customStrut ] - getting conform to 'RandomAccessCollection' error

As states dictionary is not "random access" capable collection, so it cannot be used directly in ForEach, here is possible approach

HStack {
ForEach(Array(filterSelections.keys.enumerated()), id:\.element) { _, key in
Text("TBD \(self.filterSelections[key]?.title ?? "")")
// Will be putting checkboxes here - i.e. so can chose which ones
}
}

SwiftUI ForEach of dictionary identified issue

It looks like you have a misunderstanding. Based on the code you posted, I guess you think that iterating over a dictionary iterates over the values in the dictionary. But that is not how dictionary iteration works.

When you iterate over a dictionary, you receive pairs. Each pair contains one key and the corresponding value from the dictionary. In your code, wordListEntry's type is (key: Int, value: [String: String]), a pair whose first element is key of type Int and whose second element is value of type [String: String].

I think you want to just iterate over the dictionary's keys, and then look up the corresponding values inside the ForEach body, like this:

ForEach(wordList.keys.sorted().identified(by: \.self)) { key in
let lang1 = wordListEntry[wordOrder[0]]
let lang2 = wordListEntry[wordOrder[1]]
return WordRow(lang1, lang2)
}

Is it possible to iterate a dictionary inside ForEach in SwiftUI?

This is because a Dictionary is unordered. So its keys are unordered as well.

You need to make it ordered using Array:

ForEach(Array(viewModel.userDomains.keys).indices, id: \.self) { ...

As they are ordered randomly, you may also want to sort them:

ForEach(Array(viewModel.userDomains.keys).sorted().indices, id: \.self) { ...

But as the ordering and sorting gets more complex, you may think of moving the logic to the ViewModel instead.

SwiftUI How to make ForEach with Dict with array of custom objects auto update

try something like this:

List {
ForEach(Array(coupons.keys), id: \.self) { key in
// or ForEach(coupons.keys.sorted(), id: \.self) { key in
Section(header: Text(key)) {
ForEach(coupons[key] ?? [], id: \.id) { coupon in
Button(ifexpiredString(date: coupon.date)+coupon.data[1]) {
let coupons = UserDefaults.standard.coupons
let couponIndex = coupons.firstIndex(of: coupon)
self.currentview = "Coupon"+String(couponIndex!)
}.foregroundColor(ifexpired(date: coupon.date) ? Color.gray : ifexpireing(date: coupon.date))
}
}
}
}

Iterating through set with ForEach in SwiftUI

It turns out need some playing with code like this way, if you know better way I will accept your answer. thanks.

PS: For using Set in ForEach and unleashing full power of Set, we can use an identifiable type for elements for our Set, then using id: \.id, after that we can have multiple elements with same string and deferent id's also the power of Set.

struct ContentView: View {

@State private var set: Set<String> = ["value1", "value2", "value3", "value4"]

var body: some View {

SetforForEachWithBinding(set: $set)

}
}

struct SetforForEachWithBinding: View {

@Binding var set: Set<String>

var body: some View {

List {
ForEach(set.sorted(by: <), id: \.self) { element in

CustomTextFieldView(string: Binding(
get: { return element },
set: { newValue in

set.remove(element)
set.insert(newValue)

}
))

}
}
}
}





struct CustomTextFieldView: View {

@Binding var string: String
@State private var isUnderEdit: Bool = Bool()
@State private var isUnderEditString: String = String()

var body: some View {
TextField("Enter value here...", text: Binding(
get: {

if isUnderEdit {
return isUnderEditString
}
else {
return string
}

},
set: { newValue in

if isUnderEdit {
isUnderEditString = newValue
}

}
), onEditingChanged: { value in

if value {
isUnderEdit = true
isUnderEditString = string
}
else {
isUnderEdit = false
string = isUnderEditString
}

}, onCommit: { })

}
}


Related Topics



Leave a reply



Submit