Jay Patel
Jay Patel

Reputation: 2740

How to disable refreshable in nested view which is presented as sheet/fullscreenCover in SwiftUI?

I am using .refreshable to List in Home Screen. When user clicks on any cell item from the List, presenting DetailsView by sheet/fullscreenCover. But, .refreshable is still attached with DetailsView.

How to disable refreshable in nested view (DetailsView) which is presented from Home Screen?

HomeView.swift

struct HomeView: View {
    @State private var showDetailsView: Bool = false

    var body: some View {
        NavigationView {
            List(0..<29) { _ in
                Text("Hello, world!")
                    .padding()
                    .onTapGesture {
                        showDetailsView = true
                    }
                    //.sheet or .fullScreenCover
                    .fullScreenCover(isPresented: $showDetailsView) {
                        DetailsView()
                    }
            }
            .refreshable {
                print("refreshing...")
            }
            .navigationTitle("Home")
        }
    }
}

DetailsView.swift

struct DetailsView: View {
    @Environment(\.presentationMode) var presentationMode

    var body: some View {
        NavigationView {
            List(0..<29) { _ in
                Text("DetailsView...")
                    .padding()
                }
                .navigationTitle("DetailsView")
                .navigationBarItems(
                    leading:
                        Button(action: {
                            presentationMode.wrappedValue.dismiss()
                        }) {
                            Text("Close")
                        }
                )
            }
        }
    }
}

Upvotes: 4

Views: 1366

Answers (2)

Max Kraev
Max Kraev

Reputation: 770

Kudos to my insanely clever colleague. He's just on another level of understanding stuff.

.environment(\EnvironmentValues.refresh as! WritableKeyPath<EnvironmentValues, RefreshAction?>, nil)

This will disable pull to refresh for all subviews. And you are still able to make another one if needed. Of course, quite an ugly solution, but it seems like the only one working, for now, besides moving all of the navigation modifiers outside of subviews, which is often undesirable.

UPD:

This is fixed in iOS 16.4, see the release notes

Fixed: Refreshable modifiers applied to lists will no longer also apply to lists or scroll views within the content of that list. Re-apply a refreshable modifier to the content of the list if this is desired behavior. (102052575)

Upvotes: 4

Asperi
Asperi

Reputation: 258345

Move fullScreenCover modifier out of NavigationView (on home), and probably in real app it will be needed to use variant with item fullScreenCover(item:) instead to pass selection.

var body: some View {
    NavigationView {
        List(0..<29) { _ in
            Text("Hello, world!")
                .padding()
                .onTapGesture {
                    showDetailsView = true
                }
                //.sheet or .fullScreenCover
        }
        .refreshable {
            print("refreshing...")
        }
        .navigationTitle("Home")
    }
    .fullScreenCover(isPresented: $showDetailsView) {   // << here !!
      DetailsView()
    }
}

Tested with Xcode 13.3 / iOS 15.4

Upvotes: 1

Related Questions