frzi / swiftui-router

Path-based routing in SwiftUI
MIT License
900 stars 43 forks source link

Flexible nested navigation #42

Closed mbarashkov closed 2 years ago

mbarashkov commented 2 years ago

Imagine the following navigation pattern:

/screen1/:id1 /screen1/:id1/:childId1 /screen1/:id1/:childId1/subchildId1 ...

And I want all these paths to be routed to a single screen (it's like going down a filesystem). I've tried doing screen1/ - this catches all these navigations but doesn't give me parameters screen1//:id - doesn't work :id - doesn't work for nested navigations either

Hence I'm taking a temporary solution of forking the library and making RouteInformation.matchedPath public to analyze it in code (which is not the best way to solve this, of course).

What do you think would be the proper way to support this (fairly common I guess) scenario? Thanks!

frzi commented 2 years ago

This is actually something matchedPath should help with in the future. However it's currently an internal property due to lack of testing. I have not yet tested whether it always returns what I want 😄

You can achieve similar behaviour without needing access to it the property:

struct FileExplorerRoot: View {
    @EnvironmentObject private var navigator: Navigator

    var body: some View {
        Route { route in
            let pathComponents = String(navigator.path[route.path.endIndex...]).split(separator: "/")
            FileExplorer(path: pathComponents)
        }
    }
}

Note this only works if FileExplorerRoot is somewhere inside another Route. If it's not and it's directly inside the Router instead, you can just use let pathComponents = navigator.path.split(separator: "/") instead 😄

Regardless, there's probably not a better way than using .split(separator: "/") on the path. It's your best bet at the moment.

The view should also always re-render when the path changes.

mbarashkov commented 2 years ago

Thank you for the explanation!