Mobile Development 13 min read

TheRouter-iOS: A Lightweight Routing Middleware for Mobile Apps

TheRouter-iOS is a lightweight, annotation‑driven routing middleware that brings Java‑style dependency injection, hard‑code elimination, dynamic redirection, interceptors, and flexible navigation to iOS, offering a unified solution for complex mobile architectures and seamless integration with Android and web components.

Huolala Tech
Huolala Tech
Huolala Tech
TheRouter-iOS: A Lightweight Routing Middleware for Mobile Apps

TheRouter-iOS Lightweight Routing Middleware

TheRouter is a lightweight routing middleware created by Huolala that simultaneously supports Android and iOS . It introduces annotation capabilities to iOS, greatly improving the developer experience by moving away from traditional target‑action or protocol patterns and aligning with backend and Android routing concepts.

1. Why TheRouter

As application complexity grows, developers shift from simple MVC to MVP, MVVM, and other layered architectures. Decoupling layers and UI components while maintaining high cohesion and low coupling becomes challenging. Existing iOS middleware varies in implementation, making migration difficult and preventing a unified communication component across iOS, Android, H5, and Universal Links. TheRouter‑iOS addresses these gaps.

TheRouter provides four core features:

Dependency injection: similar to Java annotations, register routes by annotating VC classes or methods.

Hard‑code elimination: a built‑in script converts registered paths into static string constants.

Dynamic capabilities: supports adding redirects, interceptors, and backend‑driven dynamic routes.

Page navigation: supports standard VC or Storyboard push/present navigation.

2. Implementation Principles

2.1 Module Description

<ol>
<li><code>├── Classes</code></li>
<li><code>│   ├── TheRouter+Annotation.h</code></li>
<li><code>│   ├── TheRouter+Annotation.m</code></li>
<li><code>│   └── TheRouter.h</code></li>
<li><code>└── Resources</code></li>
<li><code>    └── scan.py   // annotation scanning and hard‑code processing script (referenced only, not compiled)</code></li>
</ol>

2.2 Storage Structure

Each route is stored as a KeyPath and later looked up efficiently via valueForKeyPath.

Example storage for test://abc.com/login:

@{
    @"test":@{
        @"abc-com":@{
            @"login":@{
                @"_handler":block, // open callback
                @"_placeholder":array, // placeholder info
                @"_interceptor":block, // interceptor callback
                @"_redirectUrl":string, // redirect link
            }
        }
    }
}

When opening a route, the flow is:

2.3 Annotation‑Based Dependency Injection

The concept originates from the BeeHive library, which uses __attribute__((used, section("__DATA,"#sectname))) to embed mappings into the Mach‑O file. TheRouter instead writes mappings to a pre‑generated plist, keeping the binary size small.

Annotation macros:

/// VC annotators, equivalent to call registController:clazzName storyBoard:nil path:routerPath
#define TheRouterController(routerPath,clazzName)

/// Storyboard VC annotators, equivalent to call registController:clazzName storyBoard:sbName path:routerPath
#define TheRouterStoryboardController(routerPath,sbName,clazzName)

/// Method annotator, equivalent to calling registSelector:selName targetClass:clazzName path:routerPath
#define TheRouterSelector(routerPath,selName,clazzName)

Three annotation types:

TheRouterController – VC type (routerPath, clazzName)

TheRouterStoryboardController – Storyboard VC type (routerPath, sbName, clazzName)

TheRouterSelector – Event type (routerPath, selName, clazzName)

VC Type / Storyboard VC Type

Annotated VCs are instantiated automatically, and parameters are assigned via KVC. Navigation commands (push, present, etc.) are inferred from the current navigation controller.

Event Type

Methods annotated as events must accept a single parameter of type TheRouterInfo, which contains all routing information such as parameters and callback blocks. The method may return a value that becomes the result of openURLString or openPath, or it may invoke the asynchronous openCompleteHandler on the TheRouterInfo object.

The overall annotation discovery and registration flow:

2.4 Path Hard‑Code Handling

Registered route Path strings are transformed into static constants stored in a dedicated header file (similar to R.swift), reducing hard‑coded strings throughout the codebase.

Future versions will support adding documentation comments to routes and writing them into the header file for easy reference.

Overall process diagram:

3. Usage Introduction

3.1 CocoaPods Integration

pod 'TheRouter'

3.2 Annotation Usage

Step 1 : Create TheRouterAnnotation.plist in the main bundle.

Step 2 : Add an Aggregate target to the project.

Step 3 : Add the scanning script to the new target.

Script parameters (example):

python3 $SRCROOT/../TheRouter/Resources/scan.py   # script path
$SRCROOT/                                 # scan directory (usually project root)
$SRCROOT/TheRouter/                       # directory for generated header files
$SRCROOT/TheRouter/TheRouterAnnotation.plist   # annotation plist path

Step 4 : Register the host at app launch and add annotations to target VCs or service methods.

[TheRouter.shared registPathAnnotationsWithHost:@"hd://com.therouter.test"];

Register a VC route:

TheRouterController(test/vc,TestViewController)
@interface TestViewController : UIViewController
@end

Register an event route:

#import "TestService.h"
#import "TheRouter_Mappings.h"
#import <TheRouter/TheRouter+Annotation.h>

@implementation TestService
TheRouterSelector(test/jump, jumpToTestVC, TestService)
+ (id)jumpToTestVC:(TheRouterInfo *)routerInfo {
    UIViewController *vc = [TheRouter.shared openVCPath:kRouterPathTestVcVC cmd:TheRouterOpenCMDPush withParams:@{"title":@"123"} handler:^(NSString *tag, NSDictionary *_Nullable result) {
        routerInfo.openCompleteHandler ? routerInfo.openCompleteHandler(tag, result) : nil;
    }];
    return vc;
}
@end

Step 5 : After building, the target writes annotation data to TheRouterAnnotation.plist and generates TheRouter_Mappings.h, which should be added to the corresponding module.

3.3 Interceptors and Redirects

Interceptor: Can be set for full paths or wildcards. Return YES to allow the route, NO to block it. Asynchronous handling is possible by returning NO and later invoking continueHandle.

// Intercept any URL under hd://com.therouter.test/*
[TheRouter.shared registInterceptorForURLString:@"hd://com.therouter.test/*" handler:^BOOL(TheRouterInfo *router, id (^continueHandle)(void)) {
    NSLog(@"will execute router %@", router.URLString);
    return YES;
}];

Redirect: Map an old path to a new one, useful for migrations or quick fixes.

[TheRouter.shared registRedirect:@"hd://test.com/test" to:@"hd://test.com/test/vc"];

3.4 Executing Router Events

Routes support both synchronous and asynchronous returns. Example of opening a VC with parameters and a completion handler:

UIViewController *vc = [TheRouter.shared openVCPath:kRouterPathTestVcVC cmd:TheRouterOpenCMDPush withParams:@{"title":@"123"} handler:^(NSString *tag, NSDictionary *_Nullable result) {
    routerInfo.openCompleteHandler ? routerInfo.openCompleteHandler(tag, result) : nil;
}];

4. Conclusion

TheRouter is currently one of the most feature‑complete, lightweight routing solutions for iOS, combining the strengths of existing communication components while eliminating most of their drawbacks. Its annotation‑based registration removes manual route registration pain points, and it offers dynamic redirect and interceptor capabilities that can be driven by backend services for graceful degradation or dynamic navigation.

Contributions are welcome via GitHub issues and pull requests.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Mobile DevelopmentiOSmiddlewareroutingannotationdependency-injection
Huolala Tech
Written by

Huolala Tech

Technology reshapes logistics

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.