I'm working on a SwiftUI application that follows a navigation pattern similar to Instagram, with a TabView at the root and complex navigation paths starting from different tabs. I've set up my navigation based on a method described in a blog post about creating a better TabView in SwiftUI, but I'm running into issues with more complex navigation flows.
The Problem:
My app has two main navigation flows starting from FeedsView and ProfileView, both of which are part of the TabView. The navigation flow is as follows:
FeedsView -> FeedDetailsView -> EditFeedView
ProfileView -> FeedDetailsView -> EditFeedView
However, when navigating from ProfileView, the navigation to EditFeedView doesn't work as expected. Here's the simplified DetailsView code:
struct DetailsView: View {
var body: some View {
VStack {
Text("Details")
NavigationLink(value: FeedNavDestination.edit) {
Text("Open Edit screen")
}
}
.padding()
.navigationTitle("Details")
.navigationBarTitleDisplayMode(.inline)
}
}
FeedNavDestination.edit doesn't trigger navigation when coming from ProfileView.
Here's an overview of my TabView setup:
struct ContentView: View {
@StateObject var appState = AppState()
var body: some View {
ScrollViewReader { proxy in
TabView(selection: createTabViewBinding(scrollViewProxy: proxy)) {
FeedView()
.tag(ContentViewTab.home)
.tabItem {
Label("Home", systemImage: "house.fill")
}
SearchView()
.tag(ContentViewTab.settings)
.tabItem {
Label("Search", systemImage: "magnifyingglass")
}
ProfileView()
.tag(ContentViewTab.profile)
.tabItem {
Label("Profile", systemImage: "person")
}
}
}
.environmentObject(appState)
}
private func createTabViewBinding(scrollViewProxy: ScrollViewProxy) -> Binding<ContentViewTab> {
Binding<ContentViewTab>(
get: { appState.selectedTab },
set: { selectedTab in
if selectedTab == appState.selectedTab {
switch selectedTab {
case .home:
if appState.feedNavigation.isEmpty {
} else {
withAnimation {
appState.feedNavigation = []
}
}
case .settings:
if appState.searchNavigation.isEmpty {
} else {
withAnimation {
appState.searchNavigation = []
}
}
case .profile:
print("profile")
}
}
appState.selectedTab = selectedTab
}
)
}
}
And the navigation model:
class AppState: ObservableObject {
@Published var selectedTab: ContentViewTab = .home
@Published var feedNavigation: [FeedNavDestination] = []
@Published var searchNavigation: [SearchNavDestination] = []
@Published var profileNavigation: [ProfileNavDestination] = []
}
enum AppNavDestination {
case homeDetails
case searchDetails
case edit
// Add other destinations as needed
}
enum ContentViewTab {
case home
case profile
case settings
}
enum FeedNavDestination {
case details
case edit
}
enum SearchNavDestination {
case details
case edit
}
enum ProfileNavDestination {
case settings
}
Additional Issue:
Navigating to SearchView from any other tab results in non-functional navigation links because it contains a NavigationStack, similar to the other views. Questions:
How can I ensure that navigation to EditFeedView works correctly from both FeedsView and ProfileView?
How can I address the issue where navigation stops working when switching tabs that contain their own NavigationStack?
I'm looking for guidance or solutions to these navigation challenges in a SwiftUI app with a structure similar to Instagram's navigation pattern. Any suggestions or insights would be greatly appreciated.