Home > OS >  Sheetview with zipped arrays
Sheetview with zipped arrays

Time:02-07

Problem: I the sheet view only opens the first item in the arrays. I've looked and found a few similar answers, but they don't deal with zipping arrays together. They mostly have one array. Here is one example. I've also tried to extract the item to a string, and then use the string instead of the item.0, or item.1.

If anyone has any suggestions, it would help a lot.

Main Code:

  ScheduledAirplanes = ["1", "2", "3", "4"]
  ScheduledInstructors = ["5", "6", "7", "8"]
  ScheduledstartTime = ["9", "10", "11", "12"]
  ScheduledDate = ["1/2", "1/3", "1/4", "1/5"]
  @State private var showingSheet = false
  var arraysForLoop : [(String,String,String,String)] {
    let result = zip(ScheduledAirplanes,zip(ScheduledInstructors,zip(ScheduledstartTime,ScheduledDate)))
    return result.map { ($0.0, $0.1.0, $0.1.1.0, $0.1.1.1) }
  }
                  ForEach(arraysForLoop, id: \.0) { item in
                    VStack {
                      Group {
                        Text("Time")
                        VStack {
                          Text(item.3)
                            .font(.caption)
                            .foregroundColor(.gray)
                          Text(item.2)
                            .font(.caption)
                            .foregroundColor(.gray)
                        }
                        .padding([.leading, .trailing])
                        Divider()
                          .padding([.leading, .trailing])
                        Text("Flight")
                        Text(item.0)
                          .font(.caption)
                          .foregroundColor(.gray)
                        Text("Instructor")
                        Text(item.1)
                          .font(.caption)
                          .foregroundColor(.gray)
                      }
                    }
                    .onTapGesture {
                      showingSheet.toggle()
                    }
                    .sheet(isPresented: $showingSheet) {
                      FlightInfo(Airplane: "\(item.0)", Instructor: "\(item.1)")
                    }
                    .frame(width: 110, height: 140)
                    .overlay {
                      RoundedRectangle(cornerRadius: 10)
                        .stroke(.gray.opacity(0.3), lineWidth: 1)
                    }
                    Spacer()
                  }

Here is the FlightView code:

struct FlightInfo: View {
    
    @Environment(\.dismiss) var dismiss
    @State var Airplane: String
    @State var Instructor: String
    
    var body: some View {
        VStack {
            HStack {
                Text("Flight Info")
                    .font(.title)
                    .fontWeight(.bold)
                Spacer()
                Button("Cancel") {
                    dismiss()
                }
                
            }
            .padding()
            VStack {
                Text("\(Airplane)")
                    .font(.caption)
                    .fontWeight(.medium)
                    .foregroundColor(.gray)
                Text("\(Instructor)")
                    .font(.caption)
                    .fontWeight(.medium)
                    .foregroundColor(.gray)
            }
            Spacer(minLength: 0)
            Button(action: {
                dismiss()
            }) {
                Text("Done")
            }
            .foregroundColor(.white)
            .frame(width: 120, height: 45)
            .background(Color("Blue"))
            .cornerRadius(30)
            .padding(.bottom)
        }
    }
}

CodePudding user response:

I would strongly suggest that you rethink modeling your data by having a set of different String arrays that all correspond together by index. Instead, modeling your data with something like this would be much more friendly to work with in SwiftUI:

struct Model {
    var scheduleAirplane : String
    var scheduledInstructor: String
    var scheduledStartTime: String
    var scheduledDate: String
}

extension Model : Identifiable {
    var id : String { scheduleAirplane }
}

If for some reason you're stuck with the separate arrays, you can still take advantage of the more friendly models by doing something like I have below. Note that I've kept your zip code and used to to create the models. The other important difference is that I'm using sheet(item:) and passing a reference to the correct item. That gets handled by a single sheet modifier that takes a reference to the item.

struct ContentView: View {
    var scheduledAirplanes = ["1", "2", "3", "4"]
    var scheduledInstructors = ["5", "6", "7", "8"]
    var scheduledStartTime = ["9", "10", "11", "12"]
    var scheduledDate = ["1/2", "1/3", "1/4", "1/5"]
    @State private var sheetItem : Model?
    
    var arraysForLoop : [Model] {
        let result = zip(scheduledAirplanes,zip(scheduledInstructors,zip(scheduledStartTime,scheduledDate)))
        return result.map { Model(scheduleAirplane: $0.0, scheduledInstructor: $0.1.0, scheduledStartTime: $0.1.1.0, scheduledDate: $0.1.1.1) }
    }
    
    var body: some View {
        ForEach(arraysForLoop) { item in
            VStack {
                Group {
                    Text("Time")
                    VStack {
                        Text(item.scheduledDate)
                            .font(.caption)
                            .foregroundColor(.gray)
                        Text(item.scheduledStartTime)
                            .font(.caption)
                            .foregroundColor(.gray)
                    }
                    .padding([.leading, .trailing])
                    Divider()
                        .padding([.leading, .trailing])
                    Text("Flight")
                    Text(item.scheduleAirplane)
                        .font(.caption)
                        .foregroundColor(.gray)
                    Text("Instructor")
                    Text(item.scheduledInstructor)
                        .font(.caption)
                        .foregroundColor(.gray)
                }
            }
            .onTapGesture {
                sheetItem = item
            }
            .frame(width: 110, height: 140)
            .overlay {
                RoundedRectangle(cornerRadius: 10)
                    .stroke(.gray.opacity(0.3), lineWidth: 1)
            }
            Spacer()
        }.sheet(item: $sheetItem) { item in
            FlightInfo(Airplane: "\(item.scheduleAirplane)", Instructor: "\(item.scheduledInstructor)")
        }
    }
}

Note that if you took the first suggestion and coalesced the arrays into models first, the beginning of the View would just look like this:

struct ContentView: View {
    var models = [Model]
    @State private var sheetItem : Model?
    
    var body: some View {
        ForEach(models) { item in
        //etc
  •  Tags:  
  • Related