Skip to content

When a route matches multiple handlers, make it FIFO. #115

@Kalzem

Description

@Kalzem

Let's imagine the handlers

navigator.handle("app://services/defaultService") // n°1
navigator.handle("app://services/hidden/<string:service_id>") // n°2
navigator.handle("app://services/<string:service_id>") // n°3

If I pass the route app://services/github, then only handler n°3 will be triggered.
But if I pass the route app://services/defaultService, technically handlers n°1 and n°3 should trigger.

And it's where the problem starts: Because URLNavigator relies on a dictionary to save all the handlers, there is no order guaranteed.

open func handler(for url: URLConvertible, context: Any?) -> URLOpenHandler? {
    // handlerFactories is a dictionary, the keys are not guaranteed order of declaration.
    let urlPatterns = Array(self.handlerFactories.keys) 
    guard let match = self.matcher.match(url, from: urlPatterns) else { return nil }
    guard let handler = self.handlerFactories[match.pattern] else { return nil }
    return { handler(url, match.values, context) }
}

I suggest to implement an OrderedDictionary to save all the handlers and to follow a FIFO logic for the matchers.

Here is an example of an ordered dictionary: https://gist.github.com/BabyAzerty/2efda8bcef7a4286b5dc62770ea5aab5

It wouldn't change any URLNavigator code beside the declaration of the handlers to:

private var handlerFactories = OrderedDictionary<URLPattern, URLOpenHandlerFactory>()

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions