SwiftUI Nested ForEach causes unexpected ordering
It fails due to non-unique identifiers for rows. It is used index, but it is repeated in different sections, so List row reuse caching engine confused.
In the described scenario it should be selected something unique for items that are shown in rows, like (scratchy)
ForEach(self.game.rounds) { round in // make round identifiable
// ...
ForEach(self.game.players) { player in // make player identifiable
and rounds
ids should not overlap with player
ids as well.
SwiftUI Nested ForEach causes Fatal error: each layout item may only occur once
Every item in ForEach
needs a unique ID. The code can be modified by adding the following line to the Text view in the inner ForEach
to assign a unique ID:
.id("body\(roomPickupData.id)-\(roomData.key)")
ForEach(self.checkfrontVM.roomPickupDataArray) { roomPickupData in
Group {
Text(roomPickupData.sku)
.frame(width: 80, alignment: .leading)
.background(roomTypeColor[roomPickupData.sku])
.border(Color.black)
ForEach(roomPickupData.roomsForDate.sorted(by: { $0.key < $1.key}), id: \.key) { roomData in
Text(roomData.value.description)
.id("body\(roomPickupData.id)-\(roomData.key)") //<-
}
}
}
Swiftui listRowInsets makes unexpected changes when adding to an empty array
It does seem to be related to the if/else
statement. When the List
is dropped from the view hierarchy and then added back in, the insets seem to get messed up.
The inset amount looked familiar to me -- like the amount it should be inset if there were a delete button on the leading side. So, on a hunch I added an explicit call to set the edit mode to .inactive
. That seems to work.
At the top of your view, add this:
@Environment(\.editMode) private var editMode
Then, in your deleteScorecard(scorecard:Scorecard)
:
func deleteScorecard(scorecard:Scorecard) {
scorecards = scorecards.filter{$0.id != scorecard.id}
editMode?.wrappedValue = .inactive //<-- here
}
This seems to explicitly turn off the editing mode and then avoids the bug when the List
is added back into the view hierarchy.
Update -- secondary solution.
Here's another solution I came up with, since my code works with your sample code, but not with your app. In this version, the List
is included in the view hierarchy the whole time, but the frame is set to a height of 0
if there aren't any items. There may be side effects because of your background color that you're setting, which is one of the reasons I didn't include this initially, but since the original solution wasn't ideal, now it's worth including:
var body: some View {
VStack {
Button {
scorecards = [
Scorecard(date: Date()),
]
} label: {
Text("Add Scorecard")
}
if scorecards.count < 1 {
VStack {
Spacer()
HStack{
Spacer()
Text("No previous scorecards. Start a scorecard!")
.font(.headline)
.padding(20)
.multilineTextAlignment(.center)
Spacer()
}
Spacer()
}
}
List {
ForEach(sortedScorecards, id:\.self) { scorecard in
if #available(iOS 15.0, *) {
Button {
} label: {
Card(scorecard: scorecard)
}.buttonStyle(.plain)
.listRowInsets(.init(top:7.5,
leading:0,
bottom:7.5,
trailing:0))
.swipeActions(edge: .trailing, allowsFullSwipe: false) {
Button("Delete Scorecard", role: .destructive) {
deleteScorecard(scorecard: scorecard)
}
}
} else {
// Fallback on earlier versions
}
}
}
.frame(maxHeight: scorecards.count == 0 ? 0 : .infinity)
.onAppear {
UITableView.appearance().backgroundColor = .black
}
}
}
Can you specify a Where in a SwiftUI ForEach statement?
you could try something like this without the ForEach:
if let item = ItemList.first(where: {$0.id == "xxxx"}) {
Text(item.description)
}
Related Topics
How to Initialize a Mlmultiarray in Coreml
How to Catch Error When Setting Launchpath in Nstask
Swift 3 Issue with Cvararg Being Passed Multiple Times
iOS Swift - Uitableviewcell Custom Subclass Not Displaying Content
How to Access Modifiers of a View in Swiftui
Need Explanation About Random Function Swift
Swift Generics: Non-Nominal Type Does Not Support Explicit Initialization
Dynamic Datasource/Delegates for Uitableview in Swift
Convert [(Key: String, Value: String)] in [String:String]
How to Use View Controller (Calendarkit) in Swiftui Application
How to Get Rid of Array Brackets While Printing
Swift:Difference in '!' and '' in Swift