Skip to content
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

Modal View Controller #10

Open
bobspryn opened this issue Feb 24, 2016 · 5 comments
Open

Modal View Controller #10

bobspryn opened this issue Feb 24, 2016 · 5 comments

Comments

@bobspryn
Copy link

Still wrapping my head around this, but I'm a little unclear how presented view controllers would fit into this yet. I started toying with it, creating a generic modal presenter:

func modalPresenter(presenter: UIViewController) -> UIRouterDelegate {

    return RouterDelegate(
        getPresenter: { presenter },
        setChild: { child in presenter.presentViewController(child, animated: true, completion: nil)},
        setChildren: { _ in })
}

and a specific presenter for my test case:

func presentmePresenter(store: AppStore) -> UIRouterDelegate {
    let viewController = MockViewController(MockViewModel(
        store: store,
        backgroundColor: (64, 255, 64),
        title: "Present Me",
        callToActionTitle: "Go to '/welcome/present'",
        callToActionRoute: "welcome/present"))
    return modalPresenter(viewController)
}

But I'm unclear how I would incorporate this into the AppCoordinator yet, since a child of the stack router where it would be presented from, will be found and pushed into the nav controller.

Wouldn't work:

func createRouter(store: AppStore) -> Router<UIViewController> {

    return Router(tabBarPresenter()).junction([

        Router(navigationPresenter("Welcome")).stack([
            Router(welcomePresenter(store)).route("welcome", children: [
                Router(registrationPresenter(store)).route("welcome/register", children: [
                    Router(step2Presenter(store)).route("welcome/register/step2"),
                    ]),
                Router(loginPresenter(store)).route("welcome/login"),
                Router(presentmePresenter(store)).route("welcome/present"),
                ])
            ]),

        Router(aboutPresenter(store)).route("about"),

        ])
}

Almost like there needs to be a container presenter, that basically doesn't do anything itself, but passes through to presenters below it.

One critique is I think the RouterDelegate/Presenter terminology being used somewhat interchangeably (at least as far as variable naming) is a bit confusing.

@bobspryn
Copy link
Author

Actually my usage of modalPresenter doesn't make sense anyway. It would need reference to the (view controller) presenter.

@agentk
Copy link
Member

agentk commented Feb 24, 2016

Wow. I really underestimated the complexity of modals in a route coordinator.

When I was writing it, I was picturing handling modals similarly to react router where each modal would need to be declared as a child of the view that would call it. That would be very careless of me.

It probably makes more sense to pass the modal to the view controller that needs to present it.

Router(tabBarPresenter()).junction([

    Router(navigationPresenter("Welcome")).stack([
        Router(welcomePresenter(store)).route("welcome", children: [
            Router(registrationPresenter(store)).route("welcome/register", children: [
                Router(step2Presenter(store)).route("welcome/register/step2"),
                ]),
            Router(loginPresenter(store)).route("welcome/login"),
            ]),

        // Sibling of the primary "welcome" route
        Router(presentmePresenter(store)).route("welcome(/|/.+/)present"),
        ]),

    Router(aboutPresenter(store)).route("about"),
    ])

The route of "welcome(/|/.+/)present" would then match the modal at any point under welcome, such as "welcome/register/step2/present" and removing it could either be done by storing the previous path in state or removing "/present" from the end of path.

The receiving presenter (navigationPresenter or tabBarPresenter) would then need to be enhanced to present and pop modals separately to changing the stack.

I'll try and add some modals to the demo on the weekend.


Also, if you had to pick a name to standardise on would it be RouterDelegate or Presenter? (I had named it RouterDelegate simply because I didn't realise it was actually the presenter at the time.)

@bobspryn
Copy link
Author

Presenter seems maybe to be the more proper term? It's not really a delegate in the traditional cocoa sense anyway, so perhaps shy away from that name. And Present is an action, which is what it's responsibility is in your system. Then the view controller that it owns should maybe be a noun of some kind.

Yeah I tried the sibling method at first and then realized that wasn't going to fly as is. :) I started trying to create a container type router that doesn't actually have a presenter, but passes through to the first child it finds that handles a route. That way your navigation controller wouldn't have to also have presenting/dismissing capability. But then you would sort of want to present the VC from the nav VC, so I'm not quite sure how that works. Modals almost screw up the whole tree metaphor since they are nodes that are sometimes on the tree, sometimes not, or could potentially be presented from any spot on the tree. (Perhaps they are on the tree, just not "showing").

@samritchie
Copy link

@agentk did you get anywhere with modals? Would love to know what the best approach is here.

@mittenimraum
Copy link

+1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants