skip to Main Content

I am working on SwiftUI ForEach. Below image shows what I want to achieve. For this purpose I need next two elements of array in single iteration, so that I can show two card in single go. I search on a lot but did find any way to jump index swiftUI ForEach.

Need to show two cards in single iteration

ScreenShot

Here is my code in which I have added the element same array for both card which needs to be in sequence.

struct ContentView: View {

var body: some View {

    ScrollView(.vertical, showsIndicators: false) {
        VStack(spacing: 0) {
            // I need jump of 2 indexes
            ForEach(videos) { video in
                //need to show the next two elements of the videos array
                HStack {
                    videoCardView(video: video)
                    Spacer()
                    //video + 1
                    videoCardView(video: video)
                }
                .padding([.leading, .trailing], 30)
                .padding([.top, .bottom], 10)
            }
        }
    }
    .background(Color(ColorName.appBlack.rawValue))
   }
}

Any better suggestion how to build this view.

3

Answers


  1. While LazyVGrid is probably the best solution for what you want to accomplish, it doesn’t actually answer your question.

    To "jump" an index is usually referred to as "stepping" in many programming languages, and in Swift it’s called "striding".

    You can stride (jump) an array by 2 like this:

    ForEach(Array(stride(from: 0, to: array.count, by: 2)), id: .self) { index in
        // ...
    }
    

    You can learn more by taking a look at the Strideable protocol.

    Login or Signup to reply.
  2. ForEach isn’t a for loop, many make that mistake. You need to supply identifiable data to it which should give you the clue to get your data into a suitable format first. You could process the array into another array containing a struct that has an id and holds the first and second video and pass that to the View that does the ForEach. View structs are lightweight make as many as you need.

    You could also make a computed var but that wouldn’t be as efficient as a separate View because you might unnecessary recompute if something different changes.

    Login or Signup to reply.
  3. Foreach is constrained compared to a ‘for’ loop. One way to fool ForEach into behaving differently is to create a shadow array for ForEach to loop through.
    My purpose was slightly different than yours, but the workaround below seems like it could solve your challenge as well.

    import SwiftUI
    let images = ["house", "gear", "car"]
    struct ContentView: View {
        var body: some View {
            VStack {
                let looper = createCounterArray()
                ForEach (looper, id:.self) { no in
                    Image(systemName: images[no])
                        .imageScale(.large)
                        .foregroundColor(.accentColor)
                    Text("Hello, world!")
                }
                .padding()
            }
        }
    }
    
    //
    // return an array of the simulated loop data.
    //
    
    func createCounterArray() -> [Int] {
       // create the data needed
        return Array(arrayLiteral: 0,1,1,2)
    }
    
    
    struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
            ContentView()
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search