Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '<SwiftUI.UIKitNavigationController: 0x10282e200> is pushing the same view controller instance #144
-
If I navigate to a second view (sometimes stop at the first view), it will crash if I tap the back button to the first view and navigate to any other second view.
Code
import SwiftUI
import SwiftUINavigation
class HomeDetailModel: ObservableObject {
init(destination: Destination? = nil, isLogin: Bool = false) {
self.destination = destination
self.isLogin = isLogin
}
enum Destination {
case invitation
case setting
case bindPhone(ProfileDetailModel)
case profile(ProfileDetailModel)
}
@Published var destination: Destination?
@Published var isLogin: Bool
func didReceiveUserInfo() {
destination = nil
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self.destination = .invitation
}
}
@MainActor
func profileButtonTapped() {
destination = .profile(ProfileDetailModel())
}
@MainActor
func skipButtonTapped() async {
isLogin = true // TODO: change from overlay to full screen cover
try? await Task.sleep(for: .seconds(0.3))
destination = .bindPhone(ProfileDetailModel())
}
@MainActor
func bindPhoneButtonTapped() async {
print(1)
try? await Task.sleep(for: .seconds(0.3))
print(2)
destination = .profile(ProfileDetailModel(destination: .setting))
print(3)
}
}
extension HomeDetailModel: @unchecked Sendable { }
import SwiftUI
import SwiftUINavigation
struct HomeView: View {
@ObservedObject var model: HomeDetailModel
var body: some View {
NavigationStack {
ScrollView(.vertical, showsIndicators: false) {
allCardsView()
Spacer(minLength: .ideal(70) * CGFloat(model.memberCards.count))
}
.navigationDestination(
unwrapping: $model.destination,
case: /HomeDetailModel.Destination.profile)
{ $model in
ProfileView(model: model)
}
.sheet(unwrapping: $model.destination, case: /HomeDetailModel.Destination.bindPhone) { _ in
BindPhoneView() {
Task {
await model.bindPhoneButtonTapped()
}
}
.presentationDetents([.height(.ideal(415))])
.presentationDragIndicator(.visible)
}
}
.overlay {
if !model.isLogin {
NavigationStack {
LoginView(model: model)
}
}
}
}
}
import SwiftUI
struct BindPhoneView: View {
@Environment(\.dismiss) var dismiss
var onTap: () -> Void
var body: some View {
Button {
dismiss()
onTap()
} label: {
ButtonLabel(title: "Bind", width: 106)
}
}
} Sum upWhen I am in BindPhoneView, I first tap the button to dismiss the sheet and use the closure to call Demo |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 3 replies
-
Hi @nick-maker, the code you posted above does not compile. It is missing However, even without running the code I can tell you that 99.9% of the time this is just a limitation of vanilla SwiftUI navigation. Our tools do not really add much on top of what SwiftUI gives us. It's just some simple binding transformation helpers. So I feel confident saying that you would be able to reproduce this problem even without using our library. |
Beta Was this translation helpful? Give feedback.
Hi @nick-maker, thanks for the project. That helps a lot to see what is going on.
Unfortunately you are just doing something too advanced for SwiftUI to handle. By doing this:
…all in one line you are simultaneously dismissing a sheet and pushing two views onto the navigation stack. SwiftUI is just not capable of doing things like that (at least not with
navigationDestination
), even in vanilla SwiftUI without using our library.If you want to keep your domain modeled exactly as you have it now, then one potential fix is to space out the
destination
mutations a bit. You can firstnil
out thedestination
…