iOS routing done right. Handles both URL recognition and controller displaying with parsed parameters. All in one line, controller stack preserved automatically!

Overview

WAAppRouting

Version License Platform

Developed and Maintained by Ipodishima Founder & CTO at Wasappli Inc. (If you need to develop an app, get in touch with our team!)

So what is this library useful for? Good question. Let's answer by asking an other question. Have you been struggled at some point with the following issues?

  • Well, I need to add some shortcuts to some parts of my apps and it seems crappy to manually allocate the path and select the controllers I need.
  • I'm tired of using the push view controller method.
  • I wish I had some kind of url handling to get to specific parts of my app just as easily as snapping a finger.
  • If it could even handle a controller stack this would just be awesome.
  • I found a library but it's not working with my custom container...
  • I found a great library but the route matching is not working with my requirements...

All this points are answered by WAAppRouting (and more)

Which Uses?

  • For all iOS: enable linking in your app. It is always useful to tell your app to go to home/events/3/register with some magic involved.
  • For iOS 9: supports deeplinks (like Twitter app). Opening this URL Me on twitter would opened directly the app instead of the website.
  • For iOS 9: respond to a search event. By using CoreSpotlight, users can go to your app by opening from a search result like a booking. At this point, you need to consider to goto://bookings/bookingFromSearchID. Please take a look at an implementation of routing using a library which automatically index your CoreData stack WACoreDataSpotlight.
  • For iOS 9 and more specifically new iPhones 6S and 6+S: respond to 3D Touch

Table of Contents

  1. The story
  2. Install and use
  3. Go deeper

#The story

What motivated me

Let's be honest, there are several routing libraries on Github to handle some of the behaviors described. But none of them fit all my requirements. So I wrote this library with some things in mind:

  • Handle a stack of controllers.

This is not ok to open the app on a hotel detail if there is not even a back button, or if the back button sends me back to where I was before opening the app. I just want the app to be opened so that when I hit back, I'm on the hotels list for the hotel city...

  • Do not force you to get this working with my route matcher, or my route handler.

If you want to provide your own, you should be able to do it. This last point is very important to me. I used (and use) too many libraries which are tightly tied to their technologies. Plus, the more they are dependant on their implementation, the less it is testable. This is why you'll see many protocols with a default implementation provided.

  • iOS 9 is coming (or here already when you are reading this). And with iOS 9 comes this great feature called universal links. Well, I wanted something clean to address this new feature.

Inspiration

Historically, I first used HHRouter and implemented my own stack controller management. Then, by rewriting code to support iOS 9, I saw that it was just a bunch of lines with no error management, tightly tied to the controller hierarchy, not very readable, etc.

I decided to drop it and get something more fun. I found DeepLinkKit and used it until I realized it wasn't fitting my stack requirement. So I rewrote a custom route handler to deal with it and finally arrived to the conclusion that 80% of DeepLinkKit was not used anymore. This is when I decided to drop it and write my own.

So you might recognize some concepts of the two libraries, especially in the router handler, even if the implementation has nothing to do with DeepLinkKit.

Install and use

Requirements alongs with the default implementation

  • The implementation I provide uses UINavigationController to handle the stack and can be used on UITabBarController as well.
  • The route matching works on :itemID and uses * as the wildcard character.

Installation

CocoaPods

Use CocoaPods, this is the easiest way to install the router.

pod 'WAAppRouting'

If you want to link WAAppRouting into an iOS app extension (or a shared framework that is linked to an app extension), you'll need to ensure that the WA_APP_EXTENSION flag is set when you compile the framework. To do so using CocoaPods, add this to your Podfile:

post_install do |installer|
  installer.pods_project.targets.each do |target|
    if target.name =~ /WAAppRouting/
      target.build_configurations.each do |config|
        config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= []
        config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'WA_APP_EXTENSION=1'
      end
    end
  end
end

Older versions of cocoapods may require you to use installer.project instead of installer.pods_project, so if you get an error complaining that pods_project does not exist, update your cocoapods gem.

Setup the router: easiest method

Import #import and you are good to start.

You also need to configure a URL scheme (I won't go into detail about this - there is plenty of documentation out there)

A navigation controller is a good start:

UINavigationController *navigationController = [[UINavigationController alloc] init];

You'll need first to allocate a route matcher. You can use the default I wrote or create your own:

// Create the default router
self.router = [WAAppRouter defaultRouter];

Register you path using the syntax:

  • url_path_component{ClassName}
  • url_path_component1{ClassName1}/url_path_component2{ClassName2}

Optionaly, you can trigger the modal presentation using ! character. For example: url_path_component{ClassName}/modal{ModalClass}! would result when calling appscheme://url_path_component/modal to ModalClass instance presented modally after placing ClassName in the navigation controller stack.

// Register the path
[self.router.registrar
 registerAppRoutePath:
 @"list{WAListViewController}/:itemID{WAListDetailViewController}/extra{WAListDetailExtraViewController}"
 presentingController:navigationController];

Add a block handler if needed

// Register some blocks
[self.router.registrar registerBlockRouteHandler:^(WAAppLink *appLink) {
    // Do something every time we are in list/something
}
                            			forRoute:@"list/*"];

Finally set the navigation controller as the root controller:

self.window.rootViewController = navigationController;

You can now use it and open the app with:

[self application:(UIApplication *)self openURL:[NSURL URLWithString:@"appscheme://list"] sourceApplication:nil annotation:nil];

Don't forget to use the router!

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
    return [self.router handleURL:url];
}

Each controller you use should implement WAAppRouterTargetControllerProtocol (it is a good idea to have a base view controller) So implement this method and voilà:

- (void)reloadFromAppLinkRefresh {
    // You can do something with self.appLink
    // But more important: with self.appLinkRoutingParameters which has merged route|query|default parameters
    NSString *articleTitle = self.appLinkRoutingParameters[@"article_title"];
}

Setup the router: more control methods

Start with the easiest method but replace the "create paths" by creating entities entities

{ NSMutableDictionary *defaultParameters = [NSMutableDictionary new]; defaultParameters[@"defaultParam"] = @1; defaultParameters[@"defaultParam2"] = @"Default parameter 2"; return defaultParameters; } allowedParameters:nil]; ">
// Create the entities
WAAppRouteEntity *list1Entity =
[WAAppRouteEntity routeEntityWithName:@"list"
                                 path:@"list"
                sourceControllerClass:nil
                targetControllerClass:[WAListViewController class]
                 presentingController:navigationController
             prefersModalPresentation:NO
             defaultParametersBuilder:nil
                    allowedParameters:nil];

WAAppRouteEntity *list1DetailEntity =
[WAAppRouteEntity routeEntityWithName:@"listDetail"
                                 path:@"list/:itemID"
                sourceControllerClass:[WAListViewController class]
                targetControllerClass:[WAListDetailViewController class]
                 presentingController:navigationController
             prefersModalPresentation:NO
             defaultParametersBuilder:^id
    {
                 
                 
   NSMutableDictionary *defaultParameters = [
   NSMutableDictionary 
   new];
                 defaultParameters[
   @"defaultParam"]  = @
   1;
                 defaultParameters[
   @"defaultParam2"] = 
   @"Default parameter 2";
                 
   return defaultParameters;
             }
                    
   allowedParameters:
   nil];
  

Add the entities to the registrar

// Register the entities
[self.router.registrar registerAppRouteEntity:list1Entity];
[self.router.registrar registerAppRouteEntity:list1DetailEntity];

Samples

Four samples are available:

  • SimpleExample: This is a sample which handle a list, it's detail and an extra. This could be seen as an article lists, its detail and comments.
  • SimpleExampleParameters: This sample is the same as SimpleExample but is using the WAAppLinkParameters (the one more thing of this library).
  • MoreComplexExample: This sample demonstrates how to deal with a tab bar controller + how to handle modals.
  • PPRevealSample: This sample acts as a demonstration that with a little bit of effort, custom container can fit into the routing library?

Documentation

The code is heavily documented, you should find all your answers. Otherwise, open an issue and I'll respond as quickly as possible.

Go deeper

Pre-configure all controllers with objects.

You might want to pass values to the controllers when they are allocated. For example in a project I'm involved in, we have an image cache that the controllers needs to display images. This image cache is allocated by the App delegate (to avoid singletons and get more testable code). For doing this, you need to add a block implementation to the route handler:

    [routeHandler setControllerPreConfigurationBlock:^(UIViewController *controller, WAAppRouteEntity *routeEntity, WAAppLink *appLink) {
        if ([controller isKindOfClass:[WABaseViewController class]]) {
            ((WABaseViewController *)controller).imageCache = imageCache;
        }
    }];

Forbid specific entities to be shown

You can ask not to handle some routes at runtime by setting this block (for example you might not want to display some controllers if not logged in):

    [routeHandler setShouldHandleAppLinkBlock:^BOOL(WAAppRouteEntity *entity) {
        // Could return NO if not logged in for example
        return YES;
    }];

Wildcard URL

You can have wildcard urls like list/*/extra meaning that for any value instead of the *, the entity or the block would be executed. Avoid using it with entities but rather with block. An url in form of list/* will match both list/path and list/path/extra

Here is an example of an alert triggered each time we are after list/

[registrar registerBlockRouteHandler:^(WAAppLink *appLink) {
        [RZNotificationView showNotificationOn:RZNotificationContextAboveStatusBar
                                       message:[NSString stringWithFormat:@"You are dealing with item ID %@", appLink[@"articleID"]]
                                          icon:RZNotificationIconInfo
                                        anchor:RZNotificationAnchorNone
                                      position:RZNotificationPositionTop
                                         color:RZNotificationColorYellow
                                    assetColor:RZNotificationContentColorDark
                                     textColor:RZNotificationContentColorDark
                                withCompletion:^(BOOL touched) {
                                    
                                }];
    }
                                forRoute:@"list/*"];

Customize router behavior

As said, I hate libraries you cannot customize without forking and diverging from the original source. That said, you can customize the router in two ways: custom route matcher and custom route handler.

Custom route matcher

My implementation deals with basics. Meaning that it won't support key=value1, value2 for the query for example. It is also case sentitive. If you have your own URL configuration like list/$itemID implementing a new route matcher is a good idea!

To start, read the WAAppRouteMatcherProtocol class. You have two methods you need to implement: matchesURL: fromPathPattern: and parametersFromURL: withPathPattern:. As you can see in my implementation, I'm using WARoutePattern to match the URL. It's kind of inspired by SocKit (for the naming convention).

Then, you can easily create the router with:

// Allocate your route matcher
MyRouteMatcher *routeMatcher = [MyRouteMatcher new];

// Create the Registrar
WAAppRouteRegistrar *registrar  = [WAAppRouteRegistrar registrarWithRouteMatcher:routeMatcher];

// Create the route handler
WAAppRouteHandler *routeHandler = [WAAppRouteHandler routeHandlerWithRouteRegistrar:registrar];

// Create the router
WAAppRouter *router = [WAAppRouter routerWithRegistrar:registrar
                                          routeHandler:routeHandler];

Custom route handler

If for example, you don't want to handle a stack, or use something else than a UINavigationController, then consider creating your own route handler. Start by adopting WAAppRouteHandlerProtocol protocol. And then read WAAppRouteHandler to get inspiration.

iOS 9 support

I still need to run some tests, but the idea is to have a router for the classic url scheme, and another one for universal links.

3D Touch

By implementing 3D Touch, you can have users opening your app directly on some actions like new tweet, search for tweets, get direction, ... All you have to do is follow the documentation for UIApplicationShortcutItem here and then:

- (void)application:(UIApplication * _Nonnull)application
performActionForShortcutItem:(UIApplicationShortcutItem * _Nonnull)shortcutItem
  completionHandler:(void (^ _Nonnull)(BOOL succeeded))completionHandler {
    if ([shortcutItem.type isEqualToString:@"newTweet"]) {
        // goto://home/newTweet
    }
}

Search

Using WACoreDataSpotlight for example (the samples uses WAppRouting), you can respond to open app from search item events.

- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler {
    NSManagedObject *object = [self.mainIndexer objectFromUserActivity:userActivity];
    
    if ([object isKindOfClass:[Company class]]) {
        [AppLink goTo:@"companies/%@", ((Company *)object).name];
    }

    return YES;
} 

Special configuration consideration

Custom container controller

You should definitively take a look at the PPRevealSample project to get an idea of how to get this working. I'm also here to help if needed. Basic idea is try to allocate all the navigation controllers you need and pass them as the presenting controller. Then, this would behave like a tab bar (see it's category). If not, then you are in the PPRevealSideViewController context where the navigation controller gets allocated on the fly. The idea is to pass the container as the presentingController property and implement the WAAppRoutingContainerPresentationProtocol protocol (you need the optional method as well).

Modal with navigation controller

You cannot (yet) present a modal controller and then push a detail one. Like presenting a login view but pushed onto the signup controller.

Reuse controllers at different locations

Because the stack retrieval is implemented as dealing with controller class unicity, you cannot have two or more WAAppRouteEntity with the same target class when the source controller class is not nil. If you need to reuse the controller at differents places, consider creating simple subclasses of a main controller which handles all the behavior.

The one more thing: avoid having parameters keys hardcoded

###Purpose There is a one more thing to this library which is WAAppLinkParameters class. The idea behind is to avoid hardcoding the values. The behavior is based on an implementation of WAAppRouterParametersProtocol protocol, which means that you can provide your own or subclass WAAppLinkParameters which provides default behavior and all protocol methods implementation. Let's have a look to an example you can find on SimpleExampleParameters sample project.

Example

First, create a subclass:

@interface ArticleAppLinkParameters : WAAppLinkParameters

@property (nonatomic, strong) NSNumber *articleID;
@property (nonatomic, strong) NSString *articleTitle;
@property (nonatomic, strong) NSNumber *displayType;

@end

You can see here three objects which should be mapped to the url keys You need to override the mappingKeyProperty getter to provide a mapping url_key: object_property:

- (NSDictionary *)mappingKeyProperty {
    return @{
             @"articleID": @"articleID",
             @"article_title": @"articleTitle",
             @"display_type": @"displayType"
             };
}

There is a category I wrote on UIViewController which configures the object with merging for you. So, you can now get the value directly with:

self.label.text = [NSString stringWithFormat:@"ArticleID: %@", ((ArticleAppLinkParameters *)self.appLinkRoutingParameters).articleID];`

You can copy the parameters, and set values for a future use:

ArticleAppLinkParameters *params = [(ArticleAppLinkParameters *)self.appLinkRoutingParameters copy];
params.articleTitle = [NSString stringWithFormat:@"My super article %ld", (long)indexPath.row];

Grab the query with a white list:

NSString *query = [params queryStringWithWhiteList:@[@"articleID", @"articleTitle", @"displayType"];

Advantages

  • Update at any time the key on URLs without touching your code.
  • Avoid regressions when you add new parameters in the URL.
  • Easily build queries for moving from one controller to another.
  • Provide default values to a controller initialization. All your configuration is done in one place.

Notes

  • Only NSString and NSNumber parameters are supported at this time (no NSDate for example)
  • This could seems to be a pain in the ass to implement rather than using the parameters directly. True but keep in mind I thought about this one in a large project with big maintenance and evolutions plan involved.

#Contributing : Problems, Suggestions, Pull Requests?

Please open a new Issue here if you run into a problem specific to WAAppRouting.

For new features pull requests are encouraged and greatly appreciated! Please try to maintain consistency with the existing code style. If you're considering taking on significant changes or additions to the project, please ask me before by opening a new Issue to have a chance for a merge.

#That's all folks !

  • If your are happy don't hesitate to send me a tweet @ipodishima!
  • Distributed under MIT licence.
  • Follow Wasappli on facebook
Comments
  • question about the url pattern path1/path2/path3

    question about the url pattern path1/path2/path3

    i saw the sample example with params demo . there is a code line like [self.router.registrar registerAppRoutePath:@"list{WAListViewController}/:articleID{WAListDetailViewController}/extra{WAListDetailExtraViewController}" but i tried goto("list/3") crashed why ? although i didn't have kind of requirement like path1/path2 , i still wonder what is the purpose of design for path1/path2/path3...

    opened by ivanyang1984 6
  • Handle viewControllers loaded from storyboard

    Handle viewControllers loaded from storyboard

    Hello,

    The routeHandler does it's job very well, but the only problem I can see is that it does always instantiate view controllers with alloc, init.

    When you have storyboards, you have to instantiate your view controllers through an instance of the storyboard, in order to have proper initialisation of IBOutlets, IBAction and all other custom configuration stuff done in the storyboard. In my case, WAAppRouting doesn't work with most of my view controllers, but I don't want to implement another routeHandler because everything else does fit to my use-case.

    I suggest to add an optional method in the routeTargetControllerProtocol where you can allow the controller to instantiate itself, from storyboard, xib, etc. If the method is not present, we do the classic alloc, init.

    I already have an implementation working, I could submit a PR if you like.

    Thanks.

    opened by enfoiro 4
  • App extension compatible

    App extension compatible

    This removes the call to [UIApplication sharedApplication] in WAAppRouteHandler.m, since that method is off-limits to iOS app extensions.

    WAAppRouteHandler's designated initializer has been altered to accept a rootViewController:(UIViewController *) parameter, which it uses instead of pulling the rootViewController from the application's UIWindow.

    • [WAAppRouter defaultRouter] has been changed to + [WAAppRouter defaultRouterWithRootViewController:(UIViewController)]

    With these changes, it is possible to link WAAppRouting into a shared framework that is linked to both an application and an iOS app extension.

    A downside of passing in the rootViewController is that changes to the UIWindow's rootViewController property that are made after initializing WAAppRouter won't be picked up. It might be worth making the rootViewController property publicly visible, so that it can be updated if you change the rootViewController for the window.

    opened by yusefnapora 4
  • transfer Object Param

    transfer Object Param

    AViewController container an tableview, the datasource is an Array Of AModel, When click one cell enter BViewController, i wan't transfer the AModel Object to BViewController,How could i do? thanks

    opened by jackyzonewen 3
  • More flexible RouteRegistrar ?

    More flexible RouteRegistrar ?

    Hello,

    It seems that you must assign UIViewController for each and every path component. It is ok when you control how URL is constructed, but I am working to handle existing Web links and they are quite cumbersome.

    For example: scheme://domain/#map/7b157902?a=b&c=d

    where 7b157902 is actually a param, so it actually means scheme://domain/#map?guid=7b157902&a=b&c=d

    I am trying to register with:

    [registrar registerAppRoutePath:@"#map{MapViewController}/*" presentingController: nvc];

    But I get error: Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'You need to have the class enclosed between {ClassName} on *'

    [registrar registerAppRoutePath:@"#map/:guid{MapViewController}" presentingController: nvc];

    result in: Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'You need to have the class enclosed between {ClassName} on #map'

    I am going to subclass WAAppRouteRegistrar, but is there any better way to resolve it ? Also I did not find documentation for :param notation. Is it only for numeric values ?

    opened by deem0n 3
  • Changing rootViewController

    Changing rootViewController

    Hi,

    I'm building an app with two root controllers, one is for anonymous user, and the other is for users with an account. Are there way to replace the window.rootViewController , or change the root in the main navigationController?

    Thanks

    opened by juancruzmdq 2
  • can you please support this?

    can you please support this?

    i now have a requirement that i have a tab bar , each bat item has its own navigation controller. now i tried to register the same path such as home/orderlList/:orderId and myPage/orderList/:orderId , but failed. it said that i cannot have two entities with the same targetcontroller class.

    i think it's quite reasonable when i have dynamic home with target url as home/orderList/:orderId and i still have an origin orderDetail entry as myPage/orderList/:orderId .

    i have tried to comment the nsassert , but seems got disorder of stack management.

    opened by ivanyang1984 2
  • how can i register my domain?

    how can i register my domain?

    If i have an url like http://www.ls.com/shopItemList.htm the shopItemList.htm would like to mount to LSSShopItemListViewController how can i do the register? now i write the code like below

    [self.router.registrar registerAppRoutePath:@"shopItemList{LSSShopItemListViewController}"
                               presentingController:[self.navigationControllerDic objectForKey:@"LSShopNavigationController"]]
    

    it matches failed. then i drilled into your code, there was a separation operation will separate the m.ls.com and shopItemList then you tried to company the count of path components like

    // If the count is not the same and there is no wildcard, no way this can match
        // Same if the route has less components than the pattern
        if (
            ([routePathComponents count] != [self.patternPathComponents count] && !self.patternHasWildcard)
            ||
            ([routePathComponents count] < [self.patternPathComponents count])
            ) {
            return NO;
        }
    
    opened by ivanyang1984 2
  • iOS 7 compatibility

    iOS 7 compatibility

    Hello,

    You are using one method string from NSURLComponents here introduced in iOS 8.0. It leads to an unrecognised selector in iOS 7.0.

    The matchesURL tries to match an url with a pattern twice, once with a scheme, and once without if the first one does not match.

    I can't think of an example where we do need to match an url with its scheme. I suggest that we only try to match urls without schemes.

    If you agree with this, I could submit a PR.

    opened by enfoiro 2
  • WAAppRouterParametersProtocol wrong optional

    WAAppRouterParametersProtocol wrong optional "- (NSDictionary*) mappingPropertyKey"

    In the WAAppRouterParametersProtocol there is an optional method declared - (NSDictionary*) mappingPropertyKey I think it got switch around, because the assert in WAAppLinkParameters looks for the override of the mappingKeyProperty property.

    I don't know which one is switched, but the protocol and the assert should be the same, no?

    opened by Orgmir 2
  • App extension flag

    App extension flag

    @ipodishima here's a much simpler app-extension compatibility PR that uses a WA_APP_EXTENSION flag to avoid calling [UIApplication sharedApplication].

    Thanks for the sweet library, btw. Not being able to define a stack of view controllers was my main frustration with existing routing libs also. You saved me from having to write all this from scratch :)

    opened by yusefnapora 2
  • Send objects as parameters in goTo

    Send objects as parameters in goTo

    Hi, Can I send an instance of an object as parameters when I go to an specific url?, for example when I call

    [(AppDelegate *)[[UIApplication sharedApplication] delegate] goTo:@"morecomplexexample://list2/%@/modal", self.appLinkRoutingParameters[@"itemID"]];

    Thanks

    opened by juancruzmdq 1
  • can't register url with a deep path. please have a look!

    can't register url with a deep path. please have a look!

    Here is the entities i printed:

    "home/shopItemList" = "WAAppRouteEntity description:<WAAppRouteEntity: 0x7f9a9c073000>\nname: home/shopItemList\npath: home/shopItemList\nsourceControllerClass: LSSellerHomeViewController\ntargetControllerClass: LsShopListVC\npresentingController: <LSHomeNavigationController: 0x7f9a9c067850>\npreferModalPresentation: 0\nallowedParameters: (null)\n";
    "home/shopItemList/shop" = "WAAppRouteEntity description:<WAAppRouteEntity: 0x7f9a9c104900>\nname: home/shopItemList/shop\npath: home/shopItemList/shop\nsourceControllerClass: LsShopListVC\ntargetControllerClass: StoreInfoController\npresentingController: <LSHomeNavigationController: 0x7f9a9c067850>\npreferModalPresentation: 0\nallowedParameters: (null)\n";
    "home/shopItemList/shop/chat" = "WAAppRouteEntity description:<WAAppRouteEntity: 0x7f9a9c104fb0>\nname: home/shopItemList/shop/chat\npath: home/shopItemList/shop/chat\nsourceControllerClass: StoreInfoController\ntargetControllerClass: ChatViewController\npresentingController: <LSHomeNavigationController: 0x7f9a9c067850>\npreferModalPresentation: 0\nallowedParameters: (null)\n";
    

    i can register home/shopItemList/shop and home/shopItemList/shop/chat because i have an im entry in shop page.

    when i click to go chatting, it was crashed on here: WAAssert(!foundedEntity || foundedEntity && !entity.sourceControllerClass, ([NSString stringWithFormat:@"Error: you cannot have two entities with the same target class (%@) if the source is not nil. Cannot resolve the path.", NSStringFromClass(entity.targetControllerClass)]));

    if i forced to remove this assert , when i click go back it will directly go back to shopItemList instead of shop. then i think that was a bug or that operation was not currently supported.

    please kindly advise it.

    opened by ivanyang1984 1
  • how can i recognize the page leave?

    how can i recognize the page leave?

    how can i recognize the page leave? i now have a requirement like if the page shows , there is a notification appears from top. then i need the notification hide when the pages leave , because i assume i made every notification view for each page.

    opened by ivanyang1984 2
Releases(0.0.5)
  • 0.0.5(Nov 13, 2015)

  • 0.0.4(Sep 26, 2015)

    Fixes

    • If you provide an entity with a path you already registered using registerAppRouteEntity: on WAAppRouteRegistrar, then the registrar will ignore that entity.
    • Fixed an issue when passing a class on registration which does not exists. The assertion description was wrong.
    • Fixed an issue when reusing a navigation controller to place an entity with no previous one. It was simply pushing on stack, expected behavior is to reset the stack and place the controller.
    • Fixed an issue with URL and path escaping when you got for example "name": "Ben & Jerry". & is now correctly escaped using CFURLCreateStringByAddingPercentEscapes
    • Fixed an issue when presenting a modal controller over a modal controller. For example for this path: (...)/redeem{RedeemVC}!/signup{SignupVC}!.
    • Fixed a memory leak on WAAppLinkParameters
    • Fixing README
    • Added some documentation about iOS 9:
      • Search (CoreSpotlight) using WACoreDataSpotlight which automatically index CoreData
      • 3D Touch released with iPhone 6S and iPhone 6+S

    Evolutions

    • WAAppLinkParameters now supports NSCoding. This is useful for state preservation and restoration!
    • Added an optional method on WAAppRouterTargetControllerProtocol to tell the controllers that the next controller has been presented or reloaded. - (void)waappRoutingDidDisplayController:(UIViewController *)controller withAppLink:(WAAppLink *)appLink;
    Source code(tar.gz)
    Source code(zip)
Owner
null
URL routing library for iOS with a simple block-based API

JLRoutes 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 scheme

Joel Levin 5.6k Jan 6, 2023
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
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
RoutingKit - Routing library With Swift

RoutingKit Usage struct MessageBody: Body { typealias Response = String

HZ.Liu 3 Jan 8, 2022
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
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
🍞 [Beta] A view controller that can unwind like presentation and navigation.

FluidPresentation - no more handling presented or pushed in view controller A view controller that supports the interactive dismissal by edge pan gest

Muukii 19 Dec 22, 2021
A custom modal transition that presents a controller with an expanding effect while sliding out the presenter remnants.

DAExpandAnimation A custom modal transition that presents a controller with an expanding effect while sliding out the presenter remnants. Screenshot I

Denis Avdeev 578 Nov 29, 2022
Interface-oriented router for discovering modules, and injecting dependencies with protocol in Objective-C and Swift.

ZIKRouter An interface-oriented router for managing modules and injecting dependencies with protocol. The view router can perform all navigation types

Zuik 631 Dec 26, 2022
🎯Linker Lightweight way to handle internal and external deeplinks in Swift for iOS

Linker Lightweight way to handle internal and external deeplinks in Swift for iOS. Installation Dependency Managers CocoaPods CocoaPods is a dependenc

Maksim Kurpa 128 May 20, 2021
Eugene Kazaev 713 Dec 25, 2022
Appz 📱 Launch external apps, and deeplink, with ease using Swift!

Appz ?? Deeplinking to external applications made easy Highlights Web Fallback Support: In case the app can't open the external application, it will f

Kitz 1.1k May 5, 2021
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
A bidirectional Vapor router with more type safety and less fuss.

vapor-routing A routing library for Vapor with a focus on type safety, composition, and URL generation. Motivation Getting started Documentation Licen

Point-Free 68 Jan 7, 2023
A bidirectional router with more type safety and less fuss.

swift-url-routing A bidirectional URL router with more type safety and less fuss. This library is built with Parsing. Motivation Getting started Docum

Point-Free 242 Jan 4, 2023