Multiple sheets

Hey, everyone! Now I'm trying to do a simple app where I have a list of titles. I have two actions: tap the button "plus" to add new title and tap the row to edit the title. Each time I call "sheet". I use extra var to handle multiple sheets. So, I use "activeSheet" which changes when I tap the row and when I tap add button:

Code Block
@State var activeSheet = 0
  @State var isPresented = false
  @State var filmID: UUID = UUID()
   
  var body: some View {
    NavigationView {
      List {
        ForEach (modelData) { watch in
          Row(film: watch)
            .onTapGesture {
              filmID = watch.id!
              activeSheet = 1
              isPresented = true
            }
        }
      .sheet(isPresented: $isPresented) {
        if (activeSheet == 1) {
          DetailNotWatchedView(filmID: $filmID, isPresentedDetailView: $isPresented)
        }
        else if (activeSheet == 2) {
          AddingNotWatchedView(isPresented: $isPresented)
        }
      }
      .navigationBarTitle("To watch")
      .navigationBarItems(trailing:
                  Button(action: {
                    activeSheet = 2
                    isPresented = true },
                      label: { Image(systemName: "plus.circle").imageScale(.large) }))
      .listStyle(PlainListStyle())
    }


The problem is that when I tap add button before tapping the row I go to DetailNotWatchedView instead of AddingNotWatchedView. I suppose when I tap add button activeSheet must change to 2. But if I tap the row before I tap the add button everything works OK. I can't understand how to fix it.
Answered by OOPer in 648817022
The current implementation of SwiftUI has some flaw in using @State variables inside closures passed to sheet.

One workaround is splitting the content of the sheet into another view:
Code Block
struct ContentView: View {
var modelData: [Model] = [Model(), Model()] //Added to test
@State var activeSheet = 0
@State var isPresented = false
@State var filmID: UUID = UUID()
var body: some View {
NavigationView {
List {
ForEach (modelData) { watch in
Row(film: watch)
.onTapGesture {
filmID = watch.id!
activeSheet = 1
isPresented = true
}
}
.sheet(isPresented: $isPresented) {
MySheets(activeSheet: $activeSheet, filmID: $filmID, isPresented: $isPresented)
}
.navigationBarTitle("To watch")
.navigationBarItems(trailing:
Button(action: {
activeSheet = 2
isPresented = true },
label: { Image(systemName: "plus.circle").imageScale(.large) }))
.listStyle(PlainListStyle())
}}
}
}
struct MySheets: View {
@Binding var activeSheet: Int
@Binding var filmID: UUID
@Binding var isPresented: Bool
var body: some View {
if activeSheet == 1 {
DetailNotWatchedView(filmID: $filmID, isPresentedDetailView: $isPresented)
} else if activeSheet == 2 {
AddingNotWatchedView(isPresented: $isPresented)
}
}
}


Accepted Answer
The current implementation of SwiftUI has some flaw in using @State variables inside closures passed to sheet.

One workaround is splitting the content of the sheet into another view:
Code Block
struct ContentView: View {
var modelData: [Model] = [Model(), Model()] //Added to test
@State var activeSheet = 0
@State var isPresented = false
@State var filmID: UUID = UUID()
var body: some View {
NavigationView {
List {
ForEach (modelData) { watch in
Row(film: watch)
.onTapGesture {
filmID = watch.id!
activeSheet = 1
isPresented = true
}
}
.sheet(isPresented: $isPresented) {
MySheets(activeSheet: $activeSheet, filmID: $filmID, isPresented: $isPresented)
}
.navigationBarTitle("To watch")
.navigationBarItems(trailing:
Button(action: {
activeSheet = 2
isPresented = true },
label: { Image(systemName: "plus.circle").imageScale(.large) }))
.listStyle(PlainListStyle())
}}
}
}
struct MySheets: View {
@Binding var activeSheet: Int
@Binding var filmID: UUID
@Binding var isPresented: Bool
var body: some View {
if activeSheet == 1 {
DetailNotWatchedView(filmID: $filmID, isPresentedDetailView: $isPresented)
} else if activeSheet == 2 {
AddingNotWatchedView(isPresented: $isPresented)
}
}
}


It's amazing! Thank you so much!
Multiple sheets
 
 
Q