rundfunk47 / stinsen

Coordinators in SwiftUI. Simple, powerful and elegant.
MIT License
907 stars 95 forks source link

No children, cannot dismiss?! #15

Closed dlvovich closed 3 years ago

dlvovich commented 3 years ago

Hello, in my app I have very simple coordinator, inited from SceneDelegate. When I try to dismiss modal window "CitySelectView" by router?.dismiss() I got "fatalError("no children, cannot dismiss?!")"

What have I done wrong?

final class WallsListCoordinator: NavigationCoordinatable {
    var navigationStack: NavigationStack = NavigationStack()

    enum Route: NavigationRoute {
        case openCalculator(id: Int?)
        case openCatalogue
        case openCitySelect
    }

    func resolveRoute(route: Route) -> Transition {
        switch route {
        case .openCalculator(let id):
            return .push(
                AnyView(
                    Resolver.resolve(CalculatorFormView.self, args: id)
                )
            )
        case .openCatalogue:
            return .push(
                AnyCoordinatable(
                    CatalogueCoordinator()
                )
            )

        case .openCitySelect:
            return .modal(
                AnyView(
                    NavigationView {
                        Resolver.resolve(CitySelectView.self)
                    }
                )
            )
        }
    }
rundfunk47 commented 3 years ago

Hi! Excuse me, the documentation may be lacking here. To dismiss a single view, use pop(). dismiss() dismisses the whole coordinator. Does this solve your problem? :)

dlvovich commented 3 years ago

Yes, this problem solved. I thought what pop() is to go back in navigation stack and dismiss() to close modal view.

But I have another case. I also have CatalogueCoordinator pushed in my coordinator. I used in it's view router.dismiss() and got the same problem "fatalError("no children, cannot dismiss?!")".

rundfunk47 commented 3 years ago

Hmm. How do you retrieve the router? Using RouterStore or EnvironmentObject? And which version of Stinsen are you using?

dlvovich commented 3 years ago

Stinsen 1.1.0 I tried RouterStore and EnvironmentObject with the same result. I also found that I can dismiss view from coordinator with standard SwiftUI approach self.presentationMode.wrappedValue.dismiss(), but not with router. Nevertheless, all routes from coordinator work fine. Here is the code of coordinator, it's very simple.

final class CatalogueCoordinator: NavigationCoordinatable {
    var navigationStack: NavigationStack = NavigationStack()

    enum Route: NavigationRoute {
        case openDetail(id: Int?)
    }

    func resolveRoute(route: Route) -> Transition {
        switch route {
        case .openDetail(let id):
            return .push(
                AnyView(
                    Resolver.resolve(CatalogueDetailView.self, args: id)
                )
            )
        }
    }

    @ViewBuilder func start() -> some View {
        Resolver.resolve(CatalogueView.self)
    }
}
rundfunk47 commented 3 years ago

Hmm. That should work, I don't see anything that looks wrong based on that code alone... Can you please check the StinsenApp example project and see if you do anything different from that? Or maybe share you project so I can have a better look? :)

dlvovich commented 3 years ago

@rundfunk47 Hi. Yes, I can share code with you. But it's on gitlab. Do you have an account there?

dlvovich commented 3 years ago

@rundfunk47 I found this error in your sample app. Just replace first coordinator with NavigationCoordinatable

For example: In StinsenApp

struct StinsenApp: App {
    var body: some Scene {
        WindowGroup {
            CoordinatorView(
                ProjectsCoordinator() // <-- Replaced
            )
        }
    }
}

Then "Create project", app open new modal coordinator. Then "OK" -> "Fatal error: no children, cannot dismiss?!"

rundfunk47 commented 3 years ago

Hi! Could you please check out https://github.com/rundfunk47/stinsen/pull/20 and see if it solves your issue?

dlvovich commented 3 years ago

@rundfunk47 Yes, it works fine now. The error is gone. Big thanks!