Closed karlkaminski closed 2 years ago
Hey @karlkaminski - I just tried it and this seems to be related to the default navigation view style of iOS. If you specifically set the navigationViewStyle to .stack
, it works as expected. I assume that UISplitViewControllers only support three children - could that be right?
Edit: To be a little more precise, this can easily be done by changing the MainCoordinatorView to the following:
struct MainCoodinatorView: View {
@ObservedObject var coordinator: MainCoordinator
var body: some View {
NavigationView {
FirstLevelView(viewModel: coordinator.firstLevelViewModel)
.navigation(item: $coordinator.secondLevelViewModel) { viewModel in
SecondLevelView(viewModel: viewModel)
.navigation(item: $coordinator.thirdLevelViewModel) { viewModel in
ThirdLevelView(viewModel: viewModel)
.navigation(item: $coordinator.fourthLevelViewModel) { viewModel in
FourthLevelView(viewModel: viewModel)
}
}
}
}
.navigationViewStyle(.stack)
}
}
Btw: You will need to wrap your view models with the ObservedObject
property wrapper to make them work properly.
Thank you for you help. Do you have an advice, how I could create an unlimited navigation stack? I try it by myself and come back later if it's ok?
What do you mean by that exactly? Do you mean stacking infinitely many of the same view but with different view models or something like that?
Yes, like I wrote in the first text.
First level is a recipe list like in your example. In the detail view of a recipe is a list with related ingredients. (Eggs...) The user can now touch on a related ingredients item and a new list with recipes with eggs will be shown Now the user can go to a detail recipe and there is again a list and so on.
So it could be an unlimited deep navigation stack.
List of Recipes -> Recipe -> List of Recipes for Eggs -> Recipe -> List of Recipes with Milk -> Recipe ... Or we have articles with a list of related articles in the article: Article1 (ArticleDetailViewModel with articleID = x) -> Article2 (ArticleDetailViewModel with articleID = y) -> Article1 (ArticleDetailViewModel with articleID = z)...
I would personally argue against this due to possible memory issues and non-intuitive UI, but if that would be your goal, then this would be my solution:
class ArticleCoordinator: ObservableObject {
@Published var selectedArticle: ArticleCoordinator?
}
struct ArticleCoordinatorView: View {
@ObservedObject var coordinator: ArticleCoordinator
var body: some View {
Text("hello")
.navigation(item: $coordinator.selectedArticle) {
ArticleCoordinatorView(coordinator: $0)
}
}
}
The NavigationView would then need to be applied around it. If you prefer an array of view models, you can try out how to make that work. I will check, whether I can open source my own implementation of that.
For iOS 16, you could use the NavigationStack
to do exactly that.
class ArticleCoordinator: ObservableObject {
@Published var articles = [ArticleViewModel]()
func selectNewArticle() {
articles.append(.init(coordinator: self))
}
}
struct ArticleCoordinatorView: View {
@ObservedObject var coordinator: ArticleCoordinator
var body: some View {
NavigationStack(path: $coordinator.articles) {
Button("Select new article") {
coordinator.selectNewArticle()
}
.navigationDestination(for: ArticleViewModel.self) {
ArticleView(viewModel: $0)
}
}
}
}
Thank you very much. I think I understand the Coordinator now better with your ArticleCoordinator. Our min iOS is iOS14, but I saw the new NavigationStack and hope, we are waiting not to long to increase the min iOS version.
I am in a project that uses your coordinator pattern.
For a new requirement there must be a deep level hierarchy. E.g.: First level is a recipe list like in your example. In the detail view of a recipe is a list with related ingredients. (Eggs...) The user can now touch on a related ingredients item and a new list with recipes with eggs will be shown Now the user can go to a detail recipe and there is again a list and so on.
So it could be an unlimited deep navigation stack.
After several hours to fulfill the requirement we decided, that a static deep of 4 or 5 levels could be ok.
With your coordinator pattern I have an issue with more than 3 levels.
The fourth level will not be opened, instead the view navigates to the second level.
I created a very small example app. No side effects can occurre. So in my opinion your coordinator can not handle more that tree level of hierarchy. It is a bug or designed?
Example: Coordinator:
CoordinatorView:
Every View:
ViewModel:
The complete code: MultiLevelNavigation.zip