URL routing library for iOS with a simple block-based API



Platforms CocoaPods Compatible Carthage Compatible Build Status Apps

What is it?

JLRoutes is a URL routing library with a simple block-based API. It is designed to make it very easy to handle complex URL schemes in your application with minimal code.


JLRoutes is available for installation using CocoaPods or Carthage (add github "joeldev/JLRoutes" to your Cartfile).


JLRoutes 2.x require iOS 8.0+ or macOS 10.10+. If you need to support iOS 7 or macOS 10.9, please use version 1.6.4 (which is the last 1.x release).


Documentation is available here.

Getting Started

Configure your URL schemes in Info.plist.

*)options { return [JLRoutes routeURL:url]; } ">
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
  JLRoutes *routes = [JLRoutes globalRoutes];

  [routes addRoute:@"/user/view/:userID" handler:^BOOL(NSDictionary *parameters) {
    NSString *userID = parameters[@"userID"]; // defined in the route by specifying ":userID"

    // present UI for viewing user with ID 'userID'

    return YES; // return YES to say we have handled the route

  return YES;

- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *, id> *)options
  return [JLRoutes routeURL:url];

Routes can also be registered with subscripting syntax:

JLRoutes.globalRoutes[@"/user/view/:userID"] = ^BOOL(NSDictionary *parameters) {
  // ...

After adding a route for /user/view/:userID, the following call will cause the handler block to be called with a dictionary containing @"userID": @"joeldev":

NSURL *viewUserURL = [NSURL URLWithString:@"myapp://user/view/joeldev"];
[JLRoutes routeURL:viewUserURL];

The Parameters Dictionary

The parameters dictionary always contains at least the following three keys:

  "JLRouteURL":  "(the NSURL that caused this block to be fired)",
  "JLRoutePattern": "(the actual route pattern string)",
  "JLRouteScheme": "(the route scheme, defaults to JLRoutesGlobalRoutesScheme)"

The JLRouteScheme key refers to the scheme that the matched route lives in. Read more about schemes.

See JLRoutes.h for the list of constants.

Handler Block Chaining

The handler block is expected to return a boolean for if it has handled the route or not. If the block returns NO, JLRoutes will behave as if that route is not a match and it will continue looking for a match. A route is considered to be a match if the pattern string matches and the block returns YES.

It is also important to note that if you pass nil for the handler block, an internal handler block will be created that simply returns YES.

Global Configuration

There are multiple global configuration options available to help customize JLRoutes behavior for a particular use-case. All options only take affect for the next operation.

/// Configures verbose logging. Defaults to NO.
+ (void)setVerboseLoggingEnabled:(BOOL)loggingEnabled;

/// Configures if '+' should be replaced with spaces in parsed values. Defaults to YES.
+ (void)setShouldDecodePlusSymbols:(BOOL)shouldDecode;

/// Configures if URL host is always considered to be a path component. Defaults to NO.
+ (void)setAlwaysTreatsHostAsPathComponent:(BOOL)treatsHostAsPathComponent;

/// Configures the default class to use when creating route definitions. Defaults to JLRRouteDefinition.
+ (void)setDefaultRouteDefinitionClass:(Class)routeDefinitionClass;

These are all configured at the JLRoutes class level:

[JLRoutes setAlwaysTreatsHostAsPathComponent:YES];

More Complex Example

[[JLRoutes globalRoutes] addRoute:@"/:object/:action/:primaryKey" handler:^BOOL(NSDictionary *parameters) {
  NSString *object = parameters[@"object"];
  NSString *action = parameters[@"action"];
  NSString *primaryKey = parameters[@"primaryKey"];
  // stuff
  return YES;

This route would match things like /user/view/joeldev or /post/edit/123. Let's say you called /post/edit/123 with some URL params as well:

NSURL *editPost = [NSURL URLWithString:@"myapp://post/edit/123?debug=true&foo=bar"];
[JLRoutes routeURL:editPost];

The parameters dictionary that the handler block receives would contain the following key/value pairs:

  "object": "post",
  "action": "edit",
  "primaryKey": "123",
  "debug": "true",
  "foo": "bar",
  "JLRouteURL": "myapp://post/edit/123?debug=true&foo=bar",
  "JLRoutePattern": "/:object/:action/:primaryKey",
  "JLRouteScheme": "JLRoutesGlobalRoutesScheme"


JLRoutes supports setting up routes within a specific URL scheme. Routes that are set up within a scheme can only be matched by URLs that use a matching URL scheme. By default, all routes go into the global scheme.

[[JLRoutes globalRoutes] addRoute:@"/foo" handler:^BOOL(NSDictionary *parameters) {
  // This block is called if the scheme is not 'thing' or 'stuff' (see below)
  return YES;

[[JLRoutes routesForScheme:@"thing"] addRoute:@"/foo" handler:^BOOL(NSDictionary *parameters) {
  // This block is called for thing://foo
  return YES;

[[JLRoutes routesForScheme:@"stuff"] addRoute:@"/foo" handler:^BOOL(NSDictionary *parameters) {
  // This block is called for stuff://foo
  return YES;

This example shows that you can declare the same routes in different schemes and handle them with different callbacks on a per-scheme basis.

Continuing with this example, if you were to add the following route:

[[JLRoutes globalRoutes] addRoute:@"/global" handler:^BOOL(NSDictionary *parameters) {
  return YES;

and then try to route the URL thing://global, it would not match because that route has not been declared within the thing scheme but has instead been declared within the global scheme (which we'll assume is how the developer wants it). However, you can easily change this behavior by setting the following property to YES:

[JLRoutes routesForScheme:@"thing"].shouldFallbackToGlobalRoutes = YES;

This tells JLRoutes that if a URL cannot be routed within the thing scheme (aka, it starts with thing: but no appropriate route can be found), try to recover by looking for a matching route in the global routes scheme as well. After setting that property to YES, the URL thing://global would be routed to the /global handler block.


JLRoutes supports setting up routes that will match an arbitrary number of path components at the end of the routed URL. An array containing the additional path components will be added to the parameters dictionary with the key JLRouteWildcardComponentsKey.

For example, the following route would be triggered for any URL that started with /wildcard/, but would be rejected by the handler if the next component wasn't joker.

0 && [pathComponents[0] isEqualToString:@"joker"]) { // the route matched; do stuff return YES; } // not interested unless 'joker' is in it return NO; }]; ">
[[JLRoutes globalRoutes] addRoute:@"/wildcard/*" handler:^BOOL(NSDictionary *parameters) {
  NSArray *pathComponents = parameters[JLRouteWildcardComponentsKey];
  if (pathComponents.count > 0 && [pathComponents[0] isEqualToString:@"joker"]) {
    // the route matched; do stuff
    return YES;

  // not interested unless 'joker' is in it
  return NO;

Optional Routes

JLRoutes supports setting up routes with optional parameters. At the route registration moment, JLRoute will register multiple routes with all combinations of the route with the optional parameters and without the optional parameters. For example, for the route /the(/foo/:a)(/bar/:b), it will register the following routes:

  • /the/foo/:a/bar/:b
  • /the/foo/:a
  • /the/bar/:b
  • /the

Querying Routes

There are multiple ways to query routes for programmatic uses (such as powering a debug UI). There's a method to get the full set of routes across all schemes and another to get just the specific list of routes for a given scheme. One note, you'll have to import JLRRouteDefinition.h as it is forward-declared.

/// All registered routes, keyed by scheme
+ (NSDictionary <NSString *, NSArray 
    *> *)allRoutes;

   /// Return all registered routes in the receiving scheme namespace.
- (

Handler Block Helper

JLRRouteHandler is a helper class for creating handler blocks intended to be passed to an addRoute: call.

This is specifically useful for cases in which you want a separate object or class to be the handler for a deeplink route. An example might be a view controller that you want to instantiate and present in response to a deeplink being opened.

In order to take advantage of this helper, your target class must conform to the JLRRouteHandlerTarget protocol. For example:

@interface MyTargetViewController : UIViewController 

   @property (



- (
  self = [

  _parameters = [parameters 
     // hold on to do something with later on

     return self;

- (
     // do something interesting with self.parameters, initialize views, etc...


To hook this up via JLRRouteHandler, you could do something like this:

id handlerBlock = [JLRRouteHandler handlerBlockForTargetClass:[MyTargetViewController class] completion:^BOOL (MyTargetViewController *viewController) {
  // Push the created view controller onto the nav controller
  [self.navigationController pushViewController:viewController animated:YES];
  return YES;

[[JLRoutes globalRoutes] addRoute:@"/some/route" handler:handlerBlock];

There's also a JLRRouteHandler convenience method for easily routing to an existing instance of an object vs creating a new instance. For example:

MyTargetViewController *rootController = ...; // some object that exists and conforms to JLRRouteHandlerTarget.
id handlerBlock = [JLRRouteHandler handlerBlockForWeakTarget:rootController];

[[JLRoutes globalRoutes] addRoute:@"/some/route" handler:handlerBlock];

When the route is matched, it will call a method on the target object:

- (BOOL)handleRouteWithParameters:(NSDictionary<NSString *, id> *)parameters;

These two mechanisms (weak target and class target) provide a few other ways to organize deep link handlers without writing boilerplate code for each handler or otherwise having to solve that for each app that integrates JLRoutes.

Custom Route Parsing

It is possible to control how routes are parsed by subclassing JLRRouteDefinition and using the addRoute: method to add instances of your custom subclass.

// Custom route defintion that always matches
@interface AlwaysMatchRouteDefinition : JLRRouteDefinition

@implementation AlwaysMatchRouteDefinition

- (JLRRouteResponse *)routeResponseForRequest:(JLRRouteRequest *)request
  // This method is called when JLRoutes is trying to determine if we are a match for the given request object.

  // Create the parameters dictionary
  NSDictionary *variables = [self routeVariablesForRequest:request];
  NSDictionary *matchParams = [self matchParametersForRequest:request routeVariables:variables];

  // Return a valid match!
  return [JLRRouteResponse validMatchResponseWithParameters:matchParams];


This route can now be created an added:

id handlerBlock = ... // assume exists
AlwaysMatchRouteDefinition *alwaysMatch = [[AlwaysMatchRouteDefinition alloc] initWithPattern:@"/foo" priority:0 handlerBlock:handlerBlock];
[[JLRoutes globalRoutes] addRoute:alwaysMatch];

Alternatively, if you've written a custom route definition and want JLRoutes to always use it when adding a route (using one of the addRoute: methods that takes in raw parameters), use +setDefaultRouteDefinitionClass: to configure it as the routing definition class:

[JLRoutes setDefaultRouteDefinitionClass:[MyCustomRouteDefinition class]];


BSD 3-clause. See the LICENSE file for details.

  • myapp://web/:URLString doesn't work

    myapp://web/:URLString doesn't work

    I defiend myapp://web/:URLString URLString will be URLencoded before, it would be myapp://web/http%3A%2F%2Fbaidu.com but it's broken in pathComponents parsing. The encoded url would be split. See your code, pathComponents would be web, http:, baidu.com

    JLRoutes.m line:370
        // break the URL down into path components and filter out any leading/trailing slashes from it
        NSArray *pathComponents = [(URL.pathComponents ?: @[]) filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"NOT SELF like '/'"]];
        if ([URL.host rangeOfString:@"."].location == NSNotFound) {
            // For backward compatibility, handle scheme://path/to/ressource as if path was part of the
            // path if it doesn't look like a domain name (no dot in it)
            pathComponents = [@[URL.host] arrayByAddingObjectsFromArray:pathComponents];

    Do you have an official way in your mind of this ?

    opened by aelam 13
  • Typed parameters

    Typed parameters

    Currently all parsed params come in as strings. While that's useful a lot of the time, there are still probably some cases where the developer has to convert it to, for example, a number.

    In the interest of helping people not have to write that extra bit of code, I'd like to find some nice way to encode types in the route pattern string.

    Instead of: /post/view/:postID

    It could be (this format is by no means final and only meant to illustrate the concept): /post/view/:[postID:number]

    JLRoutes would see that postID is declared as a number and just give you an NSNumber for that key instead of an NSString.

    There is probably some set list of types where this makes any sense at all whatsoever.

    opened by joeldev 9
  • Ability to query routes

    Ability to query routes

    It would be nice if you could query JLRoutes for all the currently registered routes, and then generate, for example, a testing UI that provides easy links to all the routes in the app.

    opened by ZevEisenberg 8
  • JLRoutes 2.0.3 doesn't support host as parameter

    JLRoutes 2.0.3 doesn't support host as parameter

    Is it possible to switch between the possibility to keep the host as parameter? This because this minor release affects all the app are using it with this behaviour. I can suggest a pull request if you want.

    opened by danielebogo 7
  • URL.host is added as path component and prevents route matching

    URL.host is added as path component and prevents route matching

    I have this route setup:

    [JLRoutes addRoute:@"/playeractivation" handler:^BOOL(NSDictionary *parameters) {...}

    The incoming URL (universal links) is this: https://websitename.rs/[email protected]&code=123142

    Everything goes until line 518 in JLRoutes.m :

        if (URL.host.length > 0 && ![URL.host isEqualToString:@"localhost"]) {
            // For backward compatibility, handle scheme://path/to/ressource as if path was part of the
            // path if it doesn't look like a domain name (no dot in it)
            pathComponents = [@[URL.host] arrayByAddingObjectsFromArray:pathComponents];

    This piece of code picks up the websitename.rs and adds it to the existing playeractivation (which is the only path component). Thus, when it later gets in line 173, to this:

        BOOL componentCountEqual = patternComponents.count == components.count;
        BOOL patternContainsWildcard = [patternComponents containsObject:@"*"];
        if (componentCountEqual || patternContainsWildcard) {

    That first boolean is NO, because components has two elements and patternComponents has only one (which is correct).

    What's the purpose of that block above?

    The comment says:

            // For backward compatibility, handle scheme://path/to/ressource as if path was part of the
            // path if it doesn't look like a domain name (no dot in it)

    but it never actually checks for the existence of the . in the URL.host, it just blindly adds it.

    opened by radianttap 7
  • JLRoutes 2.0.2 doesn't support multiple hosts

    JLRoutes 2.0.2 doesn't support multiple hosts

    In JLRRouteRequest:

    NSURLComponents *components = [NSURLComponents componentsWithString:[self.URL absoluteString]];
    if (components.host.length > 0 && ![components.host isEqualToString:@"localhost"]) {
        // convert the host to "/" so that the host is considered a path component
        NSString *host = [components.percentEncodedHost copy];
        components.host = @"/";
        components.percentEncodedPath = [host stringByAppendingPathComponent:(components.percentEncodedPath ?: @"")];

    This doesn't allow for a support of a variety of hosts. For example, I've tested with:

    https://www.mydomain.com/path/3 and https://www.mydomain-test.com/path/3 and these resolve to paths that are www.mydomain.com/path/3 and mydomain-test.com/path/3, which means if I add a route for /path/:pathid nothing matches, since it's trying to match on a path that includes the domain as well.

    I haven't seen a workaround for this, but needing to support multiple hosts, this is a breaking change after updating from 1.6.3.

    I don't want to submit a PR in case there's a reason for this change, so would like to know why the path is overridden to include the host?

    opened by runmad 6
  • Fixed a crash caused by variable empty & wildcard still allowing it.

    Fixed a crash caused by variable empty & wildcard still allowing it.

    There was a crash due to NSRange exception Let's say a route something/:variable/detail/:variable2/* has been added. Then, you try to open the app with myapp://something/variable/detail/ This used to crash because of a Out of Range because the wildcard was protecting the :variable2 from being empty.

    Now, the variable2 will be en empty string and added in the URLComponents. This might not be the most elegant way to fix it but it works. I'm open to discuss it if there's a more elegant fix.

    opened by aimak 6
  • Optionals not appending following items

    Optionals not appending following items

    When attempting to register the route ”/(rest/)(app/):object/:id”, it does not produce the routes I would expect which would be

    "<JLRRouteDefinition 0x600000650c80> - /rest/app/:object/:id (priority: 0)",
    "<JLRRouteDefinition 0x60000064e130> - /app/:object/:id (priority: 0)",
    "<JLRRouteDefinition 0x60000064ebb0> - /rest/:object/:id (priority: 0)",
    "<JLRRouteDefinition 0x6000006501d0> - /:object/:id (priority: 0)"

    Instead, I am getting routes like

    "<JLRRouteDefinition 0x600000650c80> - /rest/app/ (priority: 0)",
    "<JLRRouteDefinition 0x60000064e130> - /app/ (priority: 0)",
    "<JLRRouteDefinition 0x60000064ebb0> - /rest/ (priority: 0)",
    "<JLRRouteDefinition 0x6000006501d0> - / (priority: 0)"

    I tried a few different combinations with moving the / around.

    “/(rest)(app)/:object/:id”       // I don’t care about the combination of rest and app, so this combination is fine

    But they all produce similar results.

    Is this expected? I can obviously just register each route separately but would prefer to condense the code if possible.

    BTW, running JLRoutes 2.0.5

    opened by gcrevell 4
  • Route aliasing

    Route aliasing

    In order to gracefully handle backwards compatibility, it would be great if you could add a route alias during the transitioning period between route changes.

    So if in an old version the profile deeplinking route was /profile/:username and in a later version is /user/:username, one would have to have to support both routes in the transitioning period until the old route can be deprecated. This means that you would have to have the exact same handler for two different routes:

    [JLRoutes addRoute:@"/profile/:username" handler:^BOOL(NSDictionary *parameters) {
        // Show profile
        return YES;
    [JLRoutes addRoute:@"/user/:username" handler:^BOOL(NSDictionary *parameters) {
        // Show profile
        return YES;

    Instead it would be nice to be able to do something like:

    [JLRoutes addAlias:@"/profile/:username" forRoute:@"/user/:username"];

    resulting in the /user/:username handler being invoked for the /profile/:username route.

    I know that one could just factor this functionality out into an external method, but it would be a much appreciated feature nonetheless.

    opened by philipengberg 4
  • Percent encoding: here's a test case with a couple failures

    Percent encoding: here's a test case with a couple failures

    I'm having problems with quoting slash (/) and plus (+). I looked at the code a bit; the problem seems to be pathComponents doing some unquoting. I think this is why Apple have now introduced NSURLComponents, but that doesn't help if you want to be compatible with older versions. Here's a test case you can drop into your test .m file to demonstrate:

    - (void)testPercentEncoding {
         from http://en.wikipedia.org/wiki/Percent-encoding
         !   #   $   &   '   (   )   *   +   ,   /   :   ;   =   ?   @   [   ]
         %21 %23    %24 %26 %27 %28 %29 %2A %2B %2C %2F %3A %3B %3D %3F %40 %5B %5D
        [self route:@"tests://user/view/joel%21levin"];
        JLValidateParameter(@{@"userID": @"joel!levin"});
        [self route:@"tests://user/view/joel%23levin"];
        JLValidateParameter(@{@"userID": @"joel#levin"});
        [self route:@"tests://user/view/joel%24levin"];
        JLValidateParameter(@{@"userID": @"joel$levin"});
        [self route:@"tests://user/view/joel%26levin"];
        JLValidateParameter(@{@"userID": @"joel&levin"});
        [self route:@"tests://user/view/joel%27levin"];
        JLValidateParameter(@{@"userID": @"joel'levin"});
        [self route:@"tests://user/view/joel%28levin"];
        JLValidateParameter(@{@"userID": @"joel(levin"});
        [self route:@"tests://user/view/joel%29levin"];
        JLValidateParameter(@{@"userID": @"joel)levin"});
        [self route:@"tests://user/view/joel%2Alevin"];
        JLValidateParameter(@{@"userID": @"joel*levin"});
         Fails: tries to match 'joel levin' with 'joel+levin'
        [self route:@"tests://user/view/joel%2Blevin"];
        JLValidateParameter(@{@"userID": @"joel+levin"});
        [self route:@"tests://user/view/joel%2Clevin"];
        JLValidateParameter(@{@"userID": @"joel,levin"});
         Fails: tries to match (null) with 'joel/levin'
        [self route:@"tests://user/view/joel%2Flevin"];
        JLValidateParameter(@{@"userID": @"joel/levin"});
        [self route:@"tests://user/view/joel%3Alevin"];
        JLValidateParameter(@{@"userID": @"joel:levin"});
        [self route:@"tests://user/view/joel%3Blevin"];
        JLValidateParameter(@{@"userID": @"joel;levin"});
        [self route:@"tests://user/view/joel%3Dlevin"];
        JLValidateParameter(@{@"userID": @"joel=levin"});
        [self route:@"tests://user/view/joel%3Flevin"];
        JLValidateParameter(@{@"userID": @"joel?levin"});
        [self route:@"tests://user/view/joel%40levin"];
        JLValidateParameter(@{@"userID": @"joel@levin"});
        [self route:@"tests://user/view/joel%5Blevin"];
        JLValidateParameter(@{@"userID": @"joel[levin"});
        [self route:@"tests://user/view/joel%5Dlevin"];
        JLValidateParameter(@{@"userID": @"joel]levin"});
    opened by DressTheMonkey 4
  • Add a New Tag for CocoaPods

    Add a New Tag for CocoaPods

    Hi Joel,

    I would like to use the new features of JLRoutes, but CocoaPods' version of JLRoutes is 3 months older than the current version. I would like to avoid pointing my Podfile to a specific commit.

    Can you add a new tag for the latest stable commit JLRoutes?

    Thanks, Trung

    opened by trungtran 4
  • Ambivalent behaviour of wildcard pattern

    Ambivalent behaviour of wildcard pattern

    When I tried to route a specific pattern Im facing ambiguous behaviour which conflicts with wildcard pattern

    I tried these patterns;

    case 1: /*/tz/tm/paid
    case 2: /*/tz/tm/checked

    it is interpreting as wildcard pattern " /* ".

    log is showing :

    key : "JLRoutePattern"
    value : /*

    When just tested by changing the wildcard pattern to // it is working.

    key : "JLRoutePattern"
    value : /*/tz/tm/checked

    Sample urls:

    1. https://www.mysite.com/tz/tm/checked
    2. https://www.mysite.com/tz/tm/paid

    how can we achieve this by giving support to both these patterns

    case 1: /*/tz/tm/paid
    case 2: /*/tz/tm/checked

    Can someone from the contributors can help or share the insights. Thanks in advance.

    opened by shreCoder 0
  • Version 2.1 is no longer compatible with Carthage

    Version 2.1 is no longer compatible with Carthage

    On checking out version 2.1 and attempting to build my app I am seeing multiple errors regarding the imported header files.

    /<module-includes>:1:1: Umbrella header for module 'JLRoutes' does not include header 'JLRRouteRequest.h' /<module-includes>:1:1: Umbrella header for module 'JLRoutes' does not include header 'JLRRouteResponse.h' /<module-includes>:1:1: Umbrella header for module 'JLRoutes' does not include header 'JLRRouteHandler.h' /<module-includes>:1:1: Umbrella header for module 'JLRoutes' does not include header 'JLRRouteDefinition.h'

    opened by matthewdovey 0
  • Routing table?

    Routing table?

    “Routes typically route packets based on a routing table (an optimal path table stored to various destinations);”. So, I think that routing only needs to be registered once through the routing table.

    opened by HaiTeng-Wang 0
  • Multithreaded is not safe

    Multithreaded is not safe

    static NSMutableDictionary *JLRGlobal_routeControllersMap = nil;

    • (void)unregisterRouteScheme:(NSString *)scheme { [JLRGlobal_routeControllersMap removeObjectForKey:scheme]; }

    • (void)unregisterAllRouteSchemes { [JLRGlobal_routeControllersMap removeAllObjects]; }

    Multithreaded is not safe.

    You can refer to


    opened by codesourse 0
  • 2.1.1(Aug 10, 2021)

  • 2.1(Dec 28, 2017)

    Release Notes

    JLRoutes 2.1 has the following new features and improvements:


    • It is now possible to change the default route definition class using +[JLRoutes setDefaultRouteDefinitionClass:]
    • Much more of the JLRRouteDefinition API is exposed in the header and intended to be overridden in subclasses (see README for more details).
    • A new class, JLRRouteHandler, has been added to provide helper methods for creating route handler blocks that are routed to classes or object instances (see README for more details).


    • The initializer for JLRRouteDefinition no longer requires a scheme parameter to be provided
    • JLRRouteResponse now holds on to the final parameters passed to the handler block, via a parameters property
    • JLRRouteResponse and JLRRouteDefinition now conform to NSCopying
    • Many miscellaneous API improvements
    • Significant code cleanup
    Source code(tar.gz)
    Source code(zip)
  • 2.0.6(Dec 28, 2017)

  • 2.0.5(Apr 13, 2017)

  • 2.0.4(Apr 9, 2017)

  • 2.0.3(Apr 6, 2017)

    Release Notes

    • Fixed a regression where domain names were not properly excluded from the logic that prepends the URL host to the path components (#88).
    • Added a few new methods for querying routes (#49):
    + (NSDictionary <NSString *, NSArray <JLRRouteDefinition *> *> *)allRoutes;
    - (NSArray <JLRRouteDefinition *> *)routes;
    • Added a new method for registering a route by instance, allowing for subclasses/customization:
    - (void)addRoute:(JLRRouteDefinition *)routeDefinition;
    • Turned on some stricter warning settings, including warnings as errors.
    • Started improving documentation, more to come on this front.
    Source code(tar.gz)
    Source code(zip)
  • 2.0.2(Mar 23, 2017)

    Release Notes

    • Query param evaluation now also takes into account the global shouldDecodePlusSymbols option. Previously it was only applied to parsed route parameters. (#87)
    Source code(tar.gz)
    Source code(zip)
  • 2.0.1(Nov 8, 2016)

    Release Notes

    • JLRoutes now explicitly requires iOS 8.0 or macOS 10.10 and higher, due to use of NSURLComponents queryItems. (#83)
      • If you require iOS 7 support, please continue to use version 1.6.4.
    • Fixed issues related to looping over the mutable routes array without copying it. (#81)
    Source code(tar.gz)
    Source code(zip)
  • 2.0(Oct 11, 2016)

    Release Notes

    • URL parsing has been entirely rewritten and now relies heavily on NSURLComponents
    • Split apart functionality into internal classes to make the code easier to read and maintain
    • Numerous misc bug fixes and improvements over the 1.x codebase
    Source code(tar.gz)
    Source code(zip)
  • 1.6.4(Oct 10, 2016)

    Notable Changes

    • Optional route parsing has been rewritten

    Important Note: This will be the last release of the current parsing logic and architecture. The next release will feature completely rewritten route parsing (using NSURLComponents) and a greatly improved internal architecture.

    Source code(tar.gz)
    Source code(zip)
  • 1.6.3(Oct 2, 2016)

    Notable Changes

    • Massive code cleanup in both JLRoutes.m and the unit test .m.
    • Deprecated a bunch of class-method APIs that I don't want to support anymore. All depreciated APIs can be easily replaced by calling the same method on the +globalRoutes instance instead.
    • Fixed a bug where unmatchedURLHandler would get called when evaluating canRouteURL:.


    • @Zeeker
    Source code(tar.gz)
    Source code(zip)
  • 1.6.2(Sep 13, 2016)

  • 1.6.1(Sep 13, 2016)

  • 1.6(Apr 6, 2016)

    Notable Changes

    • JLRoutes now requires iOS 7.0+ or OS X 10.9+
    • Added support for fragment routing
    • Removed use of a deprecated NSString method


    • @wlisac
    • @inacioferrarini
    Source code(tar.gz)
    Source code(zip)
  • 1.5.5(Feb 16, 2016)

    Notable Changes

    • Improved Swift compatibility by adding nullability annotations
    • Upgraded unit testing bundle format to remove a deprecation warning
    Source code(tar.gz)
    Source code(zip)
  • 1.5.4(Feb 3, 2016)

    Notable Changes

    • Fixed a crash
    • Improved optional parameters support
    • Improved support for iOS 9 Universal Links


    • @hoppenichu
    • @ravelantunes
    • Paul (unknown username)
    Source code(tar.gz)
    Source code(zip)
  • 1.5.3(Sep 17, 2015)

    Notable Changes

    • New target for building as an iOS framework
    • It is now possible to register multiple routes with a single handler block


    • @zats
    • @philipengberg
    Source code(tar.gz)
    Source code(zip)
  • 1.5.2(Mar 2, 2015)

    Notable Changes

    • Fixed analyzer warnings
    • Fixed a bug with adding non-zero priority routes


    • @jessedc
    • @jcampbell05
    • @ZevEisenberg
    Source code(tar.gz)
    Source code(zip)
  • 1.5.1(May 2, 2014)


    • Updated project settings for Xcode 5.1
    • Unit tests now use the XCTest macros
    • Warning fixes for -Wimplicit-atomic-properties, -Wsign-conversion, -Wreceiver-is-weak, and -Wformat-nonliteral.


    • @jessedc
    • @kav
    Source code(tar.gz)
    Source code(zip)
  • 1.5(Mar 9, 2014)


    • 64-bit support
    • JLRoutes now functions when created via alloc/init or new
    • Added methods for removing routes and entire namespaces
    • Many crashes and routing issues related to wildcards have been fixed
    • There is a new global setting that allows disabling the '+' => ' ' decoding in values
    • Removed the binary releases. Sorry to anyone that may have been using them!
    • Documentation, warning fixes, and other misc changes


    • @jakemarsh
    • @speednoisemovement
    • @nolanw
    • @martijnthe
    • @DressTheMonkey
    • @andreagiavatto
    Source code(tar.gz)
    Source code(zip)
Joel Levin
Engineering management at Square
Joel Levin
Crossroad is an URL router focused on handling Custom URL Scheme

Crossroad is an URL router focused on handling Custom URL Scheme. Using this, you can route multiple URL schemes and fetch arguments and parameters easily.

Kohki Miki 331 May 23, 2021
Easy and maintainable app navigation with path based routing for SwiftUI.

Easy and maintainable app navigation with path based routing for SwiftUI.

Freek Zijlmans 278 Jun 7, 2021
An App-specific Simple Routing Library

TrieRouter An App-specific Simple Routing Library Usage let r = Router() r.addRoute("tbx://index") { _ in print("root") } r.addRoute("tbx://intTes

TBXark 2 Mar 3, 2022
A splendid route-matching, block-based way to handle your deep links.

DeepLink Kit Overview DeepLink Kit is a splendid route-matching, block-based way to handle your deep links. Rather than decide how to format your URLs

Button 3.4k Dec 30, 2022
RoutingKit - Routing library With Swift

RoutingKit Usage struct MessageBody: Body { typealias Response = String

HZ.Liu 3 Jan 8, 2022
A framework for easily testing Push Notifications and Routing in XCUITests

Mussel ?? ?? A framework for easily testing Push Notifications, Universal Links and Routing in XCUITests. As of Xcode 11.4, users are able to test Pus

Compass 65 Dec 28, 2022
Native, declarative routing for SwiftUI applications.

SwiftfulRouting ?? Native, declarative routing for SwiftUI applications Setup time: 1 minute Sample project: https://github.com/SwiftfulThinking/Swift

Nick Sarno 13 Dec 24, 2022
Monarch Router is a Declarative URL- and state-based router written in Swift.

Monarch Router is a declarative routing handler that is capable of managing complex View Controllers hierarchy transitions automatically, decoupling View Controllers from each other via Coordinator and Presenters. It fits right in with Redux style state flow and reactive frameworks.

Eliah Snakin 31 May 19, 2021
SwiftRouter - A URL Router for iOS, written in Swift

SwiftRouter A URL Router for iOS, written in Swift, inspired by HHRouter and JLRoutes. Installation SwiftRouter Version Swift Version Note Before 1.0.

Chester Liu 259 Apr 16, 2021
An easier way to handle third-party URL schemes in iOS apps.

IntentKit ========= IntentKit is an easier way to handle third-party URL schemes in iOS apps. Linking to third-party apps is essentially broken on iOS

null 1.8k Dec 24, 2022
URLScheme router than supports auto creation of UIViewControllers for associated url parameters to allow creation of navigation stacks

IKRouter What does it do? Once you have made your UIViewControllers conform to Routable you can register them with the parameters that they represent

Ian Keen 94 Feb 28, 2022
Eugene Kazaev 713 Dec 25, 2022
RxFlow is a navigation framework for iOS applications based on a Reactive Flow Coordinator pattern

About Navigation concerns RxFlow aims to Installation The key principles How to use RxFlow Tools and dependencies GitHub Actions Frameworks Platform L

RxSwift Community 1.5k May 26, 2021
Marshroute is an iOS Library for making your Routers simple but extremely powerful

Marshroute Contents Overview Detailes Tuning the transition animation 3d touch support PeekAndPopUtility Peek and pop state observing Demo Requirement

avito.tech 215 Jan 4, 2023
DZURLRoute is an Objective-C implementation that supports standard-based URLs for local page jumps.

DZURLRoute Example To run the example project, clone the repo, and run pod install from the Example directory first. Requirements s.dependency 'DZVie

yishuiliunian 72 Aug 23, 2022
Helm - A graph-based SwiftUI router

Helm is a declarative, graph-based routing library for SwiftUI. It fully describ

Valentin Radu 99 Dec 5, 2022
🛣 Simple Navigation for iOS

Router Reason - Get Started - Installation Why Because classic App Navigation introduces tight coupling between ViewControllers. Complex Apps navigati

Fresh 457 Jan 4, 2023
A simple, powerful and elegant implementation of the coordinator template in Swift for UIKit

A simple, powerful and elegant implementation of the coordinator template in Swift for UIKit Installation Swift Package Manager https://github.com/bar

Aleksei Artemev 22 Oct 16, 2022
An open source library for building deep-linkable SwiftUI applications with composition, testing and ergonomics in mind

Composable Navigator An open source library for building deep-linkable SwiftUI applications with composition, testing and ergonomics in mind Vanilla S

Bahn-X 538 Dec 8, 2022