-
Notifications
You must be signed in to change notification settings - Fork 90
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Navigation appears to be broken on iOS #12
Comments
Thanks for reporting this. I will have a look. |
Also got this problem, any progress? |
Same problem. Has anyone sorted this out? In my case, it looks like inside the NavLink code..:
... onDisappear() is being called prematurely for my navigation level 3 view (immediately after being shown) |
OK, investigating further, this problem seems to be a (yet another) bug in SwiftUI: I see the code for NavLink + the Router view implements some of the fixes suggested in the forums... but there must be something else since it's not working for me. I will post back when a find a good solution - the empty NavigationLink did not work for me. |
Had the same issue. Tried all the current workarounds as pointed out by @azurlake but unfortunately none of them worked for me. However, I found a workaround for the D-KMP sample. You only need to change a few lines of the iOS code. Not sure if it covers all navigation issues, but up to now it served me fairly well whenever I need multiple nested navigationlinks. The problem is that any change to the appObj, such as changing anything in your model causes swift to redraw everything. NavigationLinks get redrawn as well, causing the .ondisapper event in NavLink to get triggered, and thus all related subsequent screens to disappear. To prevent it, we must check within the .ondisappear event whether the change comes bottom up (i.e. from the main view redraw). If that is the case then just neglect it.
class AppObservableObject: ObservableObject {
let model : DKMPViewModel = DKMPViewModel.Factory().getIosInstance()
var dkmpNav : Navigation {
return self.appState.getNavigation(model: self.model)
}
@Published var appState : AppState
var mainChanged : Bool = false // <- ADD THIS LINE. IT KEEPS TRACK OF ANY NEW REDRAWS BOTTOM-UP, INITIATED BY A SWIFT REDRAW AT THE MAIN LEVEL.
init() {
// "getDefaultAppState" and "onChange" are iOS-only DKMPViewModel's extension functions, defined in shared/iosMain
self.appState = model.getDefaultAppState()
model.onChange { newState in
self.appState = newState
// print("D-KMP-SAMPLE: recomposition Index: "+String(newState.recompositionIndex))
}
}
}
struct MainView: View {
@EnvironmentObject var appObj: AppObservableObject
var body: some View {
let dkmpNav = appObj.dkmpNav
appObj.mainChanged = true // <- ADD THIS LINE. WILL BE SET ON EACH REDRAW
let isActive = Binding<Bool> (
get: {
return selected && appObj.dkmpNav.isInCurrentVerticalBackstack(screenIdentifier: linkFunction())
},
set: { isActive in
appObj.mainChanged = false // <- ADD THIS LINE. IF isActive IS BEING SET, THE MAINCHANGE IS OVER
if isActive {
let screenIdentifier = linkFunction()
appObj.dkmpNav.navigateByScreenIdentifier(screenIdentifier: screenIdentifier)
self.selected = true
}
}
)
NavigationLink(
destination: LazyDestinationView(
appObj.dkmpNav.screenPicker(linkFunction())
.navigationBarTitle(appObj.dkmpNav.getTitle(screenIdentifier: linkFunction()), displayMode: .inline)
.onDisappear {
let screenIdentifier = linkFunction()
print("onDisappear: "+screenIdentifier.URI)
if appObj.dkmpNav.isInCurrentVerticalBackstack(screenIdentifier: screenIdentifier) {
if (!appObj.mainChanged){ // <-- ADD THIS CHECK. ANY SIMPLE REDRAWS WILL NOW NOT CAUSE YOUR NAVIGATION STACK TO COLLAPSE
print("confimed disappear")
self.selected = false
isActive.wrappedValue = false
appObj.dkmpNav.exitScreen(screenIdentifier: screenIdentifier, triggerRecomposition: false)
}
}
}
),
isActive: isActive
) {
content()
} This code also prevents the Level1 navigationlinks to get frozen (selected but not clickable) once returning to level 1 from a deeply nested navigation. Occasionally navigation link does bump in and out if you are in a nested situation and tap on the navigation bar to initiate a different Level 1 route and then go back to the first route. Fortunately it ends up in the correct position. Hope it works for others too. |
This is great news. I can confirm it works perfectly. Now I'm a little bit stuck at a similar problem: how would you create a similar NavLink but with the capability to be fired programmatically? So far, this NavLink triggers isActive set function when the user taps on the visible NavLink, and that looks like it's a requirement so that the view is pushed into the stack. Any help would be appreciated. |
I just published an update. Now the navigation seems fully fixed, leveraging the new iOS 16 navigation under the hood. |
When setting up Navigation deeper then Level 2 on iOS, it stops working. As soon as a Level 3 screen is opened, the Navigation jumps back to Level 1. On Android, this does not happen, the Level 3 screen is displayed correctly.
Steps to reproduce:
NEW file: TestScreenState.kt:
NEW file: TestScreenInit.kt:
ScreenEnum.kt:
NEW file: TestScreen,swift:
ScreenPicker.swift:
CountryDetailScreen.swift:
The text was updated successfully, but these errors were encountered: