I have two views: List of trips and detail view. There is my coreData entity
There is list if cities:
struct TripView: View {
@EnvironmentObject var viewRouter: ViewRouter
@FetchRequest(entity: Trip.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \Trip.startDate, ascending: true)], predicate: nil, animation: .linear) var trips: FetchedResults<Trip>
@State var tappedTrip = 0
var body: some View {
VStack(spacing: 20) {
ForEach(trips, id: \.self) { trip in
TripRow(trip: trip)
.environmentObject(viewRouter)
}
}
}
struct TripRow: View {
@EnvironmentObject var viewRouter: ViewRouter
var trip: Trip
var body: some View {
...
.fullScreenCover(isPresented: $viewRouter.isShowingDetailTripView) {
DetailTripView(trip: trip)
.environmentObject(viewRouter)
}
.onTapGesture {
viewRouter.isShowingDetailTripView.toggle()
}
And detail view:
struct DetailTripView: View {
var trip: Trip
var body: some View {...}
But when I tap on any city in detail view every time I have the first one
How I can get the corresponding value of Trip in detail view?
Tried to debug but without any results :c
CodePudding user response:
Each of your rows is monitoring $viewRouter.isShowingDetailTripView
for presentation of a fullScreenCover
- so when that boolean value toggles, in theory they could all be responding to it. In practice your first row is doing the job.
To correctly represent your state in the view router, it doesn't only need to know whether to show a full screen trip - it also needs to know which full screen trip to display.
The usual way is to use an Optional object in place of the boolean.
class ViewRouter: ObservableObject {
// ...
@Published var detailTrip: Trip?
}
When this optional value is nil
, the full screen won't display.
In your row, change your action to set this value:
// in TipRow
.onTapGesture {
viewRouter.detailTrip = trip
}
In terms of the modifier to display the full screen, I wouldn't put that in the row itself, but move it up to the list, so that you only have the one check on that value.
// in TipView
VStack {
ForEach(...) {
}
}
.fullScreenCover(item: $viewRouter.detailTrip) { trip in
DetailTripView(trip: trip)
}
This may cause an issue if you want to persist ViewRouter
between sessions for state preservation, as it'll now contain a Trip
object that it doesn't own. But this approach should get you much closer to how you want your UI to work.