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
