Skip to content

Latest commit

 

History

History
180 lines (129 loc) · 6.12 KB

File metadata and controls

180 lines (129 loc) · 6.12 KB

qroute QRoute

QRoute /'kyoo•root/ - n - Declarative walking router for UI navigation.

Reference Documentation

The essential pieces required in order to implement QRoute in an application.


QRoute

The basic element of any route plan. Each "route" is a data structure that represents a contextual view or "scene" presented by the application. It can include child routes and run-time dependencies.


QRoutable CustomRoutable

This protocol is to be implemented by the view controller (or presenter, etc) for a given route. While one is not provided for you, the included ExampleApp contains several view controller examples.

  • routeResolver: QRouteResolving (Required)
  • routeInput: QRouteInput (Required)

QRouteDriving QRouteDriver

Drives path navigation and resolver events. The QRouteDriver class (and suitable testing "mock") is provided for you.


driveParent()

driveParent(from: QRoutable,
            input: QRoutableInput,
            animated: Bool,
            completion: QRoutableCompletion?)

Commands the QRouteDriver to navigate to the immediate logical parent from QRoutable.


driveSub()

driveSub(QRouteId,
         from: QRoutable,
         input: QRoutableInput,
         animated: Bool,
         completion: QRoutableCompletion?)

Commands the QRouteDriver to navigate to any route in the hierarchy, regardless of location, as if it were an immediate logical descendant from the current route. (Essentially a subroutine version of driveTo.) Pass any dependency requirements via the input parameter.

NOTE: This works by cloning the target route (and its children) and then binding the clone's parent to the current route. Once you navigate back, the cloned sub-tree will no longer exist. This allows you to do many fun and dangerous things. For instance, you can stack the same series of routables indefinitely like in a menu-driven app, or drive global modals. But you can also create routes that would be irrational if you're not careful.


driveTo()

driveTo(QRouteId,
        from: QRoutable,
        input: QRoutableInput,
        animated: Bool,
        completion: QRoutableCompletion?)

Commands the QRouteDriver to navigate to any other route in the hierarchy, regardless of location. Calling this method will cause the driver to follow the nearest path to the destination route, raising the navigation events along the way to your custom QRouteResolving resolvers. Pass any dependency requirements via the input parameter.


QRouteResolving QRouteResolver

The resolver is where you implement the actual navigation within your application by responding to navigation events triggered by the QRouteDriver. Navigation events are always scheduled on the main thread.

Generally, you should just use the provided QRouteResolver which supports composition, and likely suitable for most needs. You can create a subclass if necessary, but using composition is generally a better way to go and therefore encouraged. (I mean this is a declarative router, after all.)

The Example App contains several resolver examples that you can use as a starting template.

  • route: QRoute (Required)

resolveRouteToChild() (Required)

resolveRouteToChild(QRoute,
                    from: QRoutable,
                    input: QRoutableInput,
                    animated: Bool,
                    completion: QRoutableCompletion)

The resolver is expected to perform the required steps to navigate to one of its immediate logical descendants matching the given QRoute. If the navigation is successful, the resolver must invoke the QRoutableCompletion block before exiting. Not invoking the completion handler will abort and cancel any remaining routing steps.


resolveRouteToParent() (Required)

resolveRouteToParent(from: QRoutable,
                     input: QRoutableInput,
                     animated: Bool,
                     completion: QRoutableCompletion)

The resolver is expected to perform the required steps to navigate to its immediate logical parent. If the navigation is successful, the resolver must invoke the QRoutableCompletion block before exiting. Not invoking the completion handler will abort and cancel any remaining routing steps.


resolveRouteToSelf() (Optional)

resolveRouteToSelf(from: QRoutable,
                   input: QRoutableInput,
                   animated: Bool,
                   completion: QRoutableCompletion)

The default implementation ignores the result, but does merge input dependencies and calls the completion handler passing the current routable, which should be sufficient most of the time. This event will be invoked in response to a driveTo event, whenever the targetId matches the source. †

You might choose to opt-in to this behavior in situations where you want/need to directly invoke a "refresh" or "re-route" on the current routable, or in cases where the target Id is uncertain.

If you choose to implement this, then the resolver is expected to perform the required steps to navigate to itself, in whatever which way that may be interpreted. If the navigation is successful, the resolver must invoke the QRoutableCompletion block before exiting.

While performing a driveSub() against self, the driver will invoke resolveRouteToChild() instead.


mergeInputDependencies() (Optional)

mergeInputDependencies(target: QRoutable,
                       input: QRoutableInput)

The default implementation merges only those values defined as one of the target route's dependencies. However, this is not called by default, so your custom resolver must invoke it when necessary.


QRoutableInput

[String:Any]

If a given route has declared any dependencies, you can use the contents of the input parameter to satisfy them.


QRoutableCompletion

(QRoutable?)->()

Once any given navigation step completes, call the completion handler, passing the destination routable.