skip to Main Content

I have set a .refreshable modifier on one of my views (attached to a VStack). This view has NavigationLinks to other pages, but unexpectedly the refreshable still works in the next pages on the NavigationStack.

i.e. I can still pull to refresh in any page that was linked from the first page where I declared the .refreshable…

I would like this .refreshable to apply only to the first page, and not to the rest of the pages.

How do I do that, and why does it behave like that in the first place?

The code on the first View/page looks like this:

 VStack {
    NavigationStack {
        List {
            //Some code with list elements
        }
    }
}
.refreshable {
    await vm.loadUserStories(getUrl: url)

3

Answers


  1. From the .refreshable documentation:

    Apply this modifier to a view to set the refresh value in the view’s environment to a RefreshAction instance that uses the specified action as its handler.

    So the modifier puts your closure into the SwiftUI environment. That’s why all your pages use it.

    Reading on:

    For example, when you apply this modifier on iOS and iPadOS to a List, the list enables a standard pull-to-refresh gesture that refreshes the list contents.

    So the answer is, put the modifier directly on the List instead of on the NavigationStack. Then only the environment of the List (and its subviews) will contain the RefreshAction, and it won’t be visible to your other pages.

    VStack {
        NavigationStack {
            List {
                //Some code with list elements
            }
            .refreshable {
                await vm.loadUserStories(getUrl: url)
            }
        }
    }
    
    Login or Signup to reply.
  2. It’s better to put the NavigationStack to be the first container not the VStack like this

    struct ContentView: View {
       var body: some View {
        NavigationStack {
            VStack {
                List {
                    NavigationLink(destination: someView) {
                        Text("Hello, world!")
                    }
                    NavigationLink(destination: Text("Hello, world!")) {
                        Text("Hello, world!")
                    }
                    NavigationLink(destination: Text("Hello, world!")) {
                        Text("Hello, world!")
                    }
                    
                    
                }
                .refreshable {
                    print("yes")
                }
            }
            
        }
    }
    
      var someView: some View {
          return VStack {
              List {
                  Text("Hello, world!")
                  Text("Hello, world!")
              }
          }
      }
     
    }
    

    this should work, you can use NavigationView if you you want to support iOS versions less than iOS 16 but it’s deprecated in iOS 16+

    Login or Signup to reply.
  3. 16.4 will fix this bug

    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)

    iOS & iPadOS 16.4 Beta Release Notes

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search