Why does adding "if" to "ForEach" break UI?

I have some swiftUI code that used to work, but somewhere, in the recent xcode updates it stoped working.


The following simple example demonstrates my problem:

struct ContentView: View {
  @State var inputText: String = "0"
  
  var body: some View {
    let value = Int(inputText) ?? 0
    
    return VStack {
      TextField("Enter Value", text: $inputText)
      HStack {
        ForEach(0..<8, content: { index in
          Text("\(self.nibbleFor(value, pos: index))")
          if index == 3 { } // <-- works when this line is commented out.
        })
      }
    }
      
  }
  
  func nibbleFor(_ value: Int, pos: Int) -> UInt8 {
    return UInt8((value >> (4 * (7-pos))) & 0x0F)
  }
}

If you run this, you get a text field that asks for a number. As you enter the number, the 8 text fields below it shows the nibble (4-bit) values for the value entered.


I use a ForEach on line 10 to generate the 8 nibble values. In my project's code, I also use an "if" statement to add other elements based on the nibble being displayed. My problem is, that as soon as I add any kind of "if", as shown in line 12, then it stops updating the Text in line 11.


If the "if" statement on line 12 is comented out, then it works.


I can add multiple HStacks, and type the code out as a workaround, but that is not very elegant.


Any idea why the if on line 12 breaks the updating of the UI?

Replies

Even with line 12 commented out, project does not work, neither with XCode 11.3 nor with 11.4.


I get a series of eight '0' in the middle of the view, a 0 on the left of view. And that's it.


OK, did not realize thjat the 0 on left was for input…

That is strange. With Xcode 11.4 and macOS 10.15.4 I am getting different results with the if statement (line 12) commented out.


Below is a screen-shot showing the app running with the line commented out.


Either way, it should work with or without that if statement. If you're result is that it does not work, then the question is still, why?


I have tried your code on Xcode 11.4 and found it works as you described.


I do not know why, but adding one more HStack makes the views update.

    var body: some View {
        let value = Int(inputText) ?? 0
        
        return VStack {
            TextField("Enter Value", text: $inputText)
            HStack {
                ForEach(0..<8, content: { index in
                    HStack {
                        Text("\(self.nibbleFor(value, pos: index))")
                        if index == 3 { }
                    }
                })
            }
        }
    }

Hmm, that's interesting. I can confirm adding it to another HStack fixes the issue.


This looks like a bug, or am I missing something?

WOW thanks for this. Wrapping the code inside my ForEach loop in a VStack fixes my data binding issue discribed here:

https://forums.developer.apple.com/thread/131577

and

https://forums.developer.apple.com/message/415107#415107

I agree this does look like a bug, would be great if Apple could confirm.