PartialSheet icon indicating copy to clipboard operation
PartialSheet copied to clipboard

The sheet disappears when the view is refreshed.

Open qinzhe opened this issue 2 years ago • 1 comments

The following code, when the button in the sheet is clicked, the sheet will disappear. If the @EnvironmentObject in PartialSheetTestView is removed, the sheet behaves normally.

` import SwiftUI import PartialSheet

@main struct PartialSheet_ExampleApp: App { @StateObject var model = PartialSheetTestModel() var body: some Scene { WindowGroup { PartialSheetTestView() .environmentObject(model) } } }

struct PartialSheetTestView: View { @EnvironmentObject var model: PartialSheetTestModel //this line @State var sheet = false var body: some View { VStack { Spacer() PSButton(isPresenting: $sheet) { Text("show sheet") } .partialSheet(isPresented: $sheet) { CountSheetView() } Spacer() } .attachPartialSheetToRoot() } }

struct CountSheetView: View { @EnvironmentObject var model: PartialSheetTestModel var body: some View { VStack { Button { model.count += 1 } label: { Text("+ 1") } } .frame(height: 120) } }

class PartialSheetTestModel: ObservableObject { @Published var count: Int = 0 } `

qinzhe avatar Apr 22 '22 01:04 qinzhe

The issue here is where you've chosen to use attachPartialSheetToRoot(). When PartialSheetTestModel publishes new updates (via the count property in your example), any view that listens to its updates will re-render by running body. If PartialSheetTestView watches PartialSheetTestModel for updates, that means that it will re-run attachPartialSheetToRoot() and that will reset the internal state of the partial sheet.

The high level idea to fix this would be to use attachPartialSheetToRoot() in a place that won't re-run while your sheet is displayed -- ideally close to the view root. In your specific example, one solution might be to introduce an intermediary view to inject your StateObject so that you can attach the partial sheet at a level that isn't changing when it does. Might be a bunch of workarounds based on your use-case though

@main
struct PartialSheet_ExampleApp: App {
    var body: some Scene {
        WindowGroup {
          InjectionView()
            .attachPartialSheetToRoot()
        }
    }
}

struct InjectionView: View {
    @StateObject var model = PartialSheetTestModel()

    var body: some View {
        PartialSheetTestView()
            .environmentObject(model)
    }
}

maciesielka avatar May 10 '22 13:05 maciesielka