3

I've got a ZStack in SwiftUI filled with some components delivered by a ForEach, as follows:

ForEach(0..<arr.count) { i in
  ZStack {
    ...
  }

  // I use i later in this code
  ...
}

The program runs perfectly like this.

But I want to add padding to the ZStack only if i == 0, so I tried adding this modifier to the ZStack: .padding(.top, i == 0 ? 70 : 0)

When I try to build it with this modifier it fails, but doesn't even say "build failed." It takes about 5 minutes attempting to build (when it usually takes 5 seconds) then decides to crash. Can anyone explain why this is happening and how I can get this conditional padding without breaking my program?

Nicolas Gimelli
  • 695
  • 7
  • 19
  • Too much type checking. Try wrapping the results (70 and 0) in CGFloat() individually you might be able to get it working. The more spots of code where the compiler has to guess the type the slower it gets ternary operations in a body are notorious slowdowns because the body is trying to guess so much so often. The other option is to move the code to a subview and maybe even a view model to get the calculations out of the body. Stay away from index use too. – lorem ipsum Feb 17 '22 at 19:52
  • Not directly related to your question, but keep in mind that using `ForEach` with a range and an array like this is not recommended and can potentially cause runtime crashes. Look into `.enumerated()` if you want a relatively-simple drop-in replacement that is safer. – jnpdx Feb 17 '22 at 20:36
  • @jnpdx how can I get access to the index if I need it without the range? – Nicolas Gimelli Feb 17 '22 at 21:03
  • Check out `.enumerated()` – jnpdx Feb 17 '22 at 21:04

2 Answers2

2

Try this:

ForEach(0..<arr.count) { i in
  ZStack {
    ...
  }
  .padding(.top, getPadding(i))

  // I use i later in this code
  ...
}
func getPadding(_ i: Int) -> CGFloat {
        if i == 0 {
                return CGFloat(70)
        }
            
        return CGFloat(0)
}
fballjeff
  • 302
  • 3
  • 9
0
func setPadding(_ statement: String) -> CGFloat {
if statement == " Put your statement " {
        return CGFloat(your requirement padding)
} else {
return CGFloat("According to your requirement padding")
}