The use of componentization is for decoupling, where multiple modules interact with each other through protocols. The component that parses the protocol, finds the destination controller, or returns an object to the caller is the routing component. This article shows you how to implement a routing component using 50 lines of core code.

This article contains the following:

Componentalization and Routing Implementation of Routing Routing Registration implementation of routing usage Implementation of clients using some small ideas to provide a Demo can be found at YTRouterDemo here and here

Componentization and routing before have seen a lot of articles about routing management, routing, processing, often with componentization appeared, at first I don’t know why the routing and componentization appear together, then the company used in the project of the routing component (he is also a component, precisely, an intermediary or broker), just suddenly want to understand, so that’s it. The use of componentization is for decoupling, where multiple modules interact with each other through protocols. The component that parses the protocol, finds the destination controller, or returns an object to the caller is the routing component.

The responsibilities of the routing component are:

The simplest way to use an interface is to pass a path to a routing component to initiate a call. The routing component will forward the specific processing to the registrant. In theory, it can do anything. Including page jump, popup prompt, return a value to the caller, etc. The following will be based on the above analysis to implement a simple routing component, the corresponding code can be found in YTRouterDemo here

The realization of route The realization of route includes two parts: the realization of route registration and the realization of route use

Implementation of route registration Implementation sequence diagram:

Initializes a YTRouterActionObject that holds the path and the corresponding blok. The path is split into multiple pathItems using the “/” character. Each pathItem is stored in the location of a Dictionary. The subRouterMapWithPath is used to deeply traverse the Dictionary and find the corresponding location. Save the YTRouterActionObject in the location found in the previous step. The code corresponding to the above steps is as follows:

- (void)registerPath:(NSString *)path actionBlock:(RouterActionBlock)actionBlock {
    YTRouterActionObject *actionObject = [YTRouterActionObject new];
    actionObject.path = path;
    actionObject.actionBlock = actionBlock;
    NSMutableDictionary *subRouter = [self subRouterMapWithPath:path];
    subRouter[YTRouterActionObjectKey] = actionObject;
}

- (NSMutableDictionary *)subRouterMapWithPath:(NSString *)path {
    NSArray *components = [path componentsSeparatedByString:@"/"];
    NSMutableDictionary *subRouter = self.routerMap;
    for (NSString *component in components) {
        if (component.length == 0) {
            continue;
        }
        if(! subRouter[component]) { subRouter[component] = [NSMutableDictionary new]; } subRouter = subRouter[component]; }return subRouter;
}
Copy the code

The final configuration of several routes registered in Demo is as follows. For example, the route configuration corresponding to home/ Messagelist is saved in <YTRouterActionObject: 0x6040000365e0>

Printing description of self->_routerMap:
{
    home =     {
        "_" = "<YTRouterActionObject: 0x60c00003b040>";
        messagelist =         {
            "_" = "<YTRouterActionObject: 0x6040000365e0>";
            detail =             {
                "_" = "<YTRouterActionObject: 0x600000038ec0>";
            };
            getmessage =             {
                "_" = "<YTRouterActionObject: 0x600000038e80>";
            };
        };
    };
}
Copy the code

Routing usage implementation Timing diagram of routing usage implementation:

From registration of a match is found in the configuration of YTRouterActionObject actionBlock execution YTRouterActionObject object, is passed a YTRouterActionCallbackObject object, Need if the caller is the return value, you can use YTRouterActionCallbackObject actionCallbackBlock pass a return value of an object, the actionBlock is and implementation of business registration The steps above the corresponding code is as follows:

- (BOOL) runWithActionCallbackObject: (actionCallbackObject YTRouterActionCallbackObject *) {/ / determine whether support schemeif(! [self canAcceptScheme:actionCallbackObject.uri.scheme]) {returnNO; YTRouterActionObject * ActionObject = [self actionObjectWithPath:actionCallbackObject.uri.path]; // Execute the corresponding Block registered with Path! actionObject.actionBlock ? : actionObject.actionBlock(actionCallbackObject);return YES;
}

- (YTRouterActionObject *)actionObjectWithPath:(NSString *)path {
    NSMutableDictionary *subRouter = [self subRouterMapWithPath:path];
    return subRouter[YTRouterActionObjectKey];
}
Copy the code

The use of the client above talked about the core of the implementation of the route registration and the implementation of the use of the route, the total code has not 50 lines, so it is very simple, the next will talk about the use of the client steps, including

The time for the caller to use the client registrar registration needs to be relatively easy to find, considering the convenience of integration, choose to handle the route registration in the load method, as shown in the following code, add several test routes, divided into two cases to illustrate the use

1, do not need to return a value The following registered “home/messagelist” a page is jump routing, actionBlock parameters is a YTRouterActionCallbackObject object, Can from YTRouterActionCallbackObject object or to parameters, about how to pass values, is below the caller to use the client here. Then in the actionBlock process the initialization of the destination page, parameter setting and other steps, and then perform the page jump.

2, need to return a value The following registered “home/messagelist/getmessage” is providing a return value of routing, also can get parameters from YTRouterActionCallbackObject object, Another actionCallbackBlock YTRouterActionCallbackObject objects and attributes are designed to handle return parameter to the caller, the following code simply returns a string, in a more specific business scenario, there will be set interface calls, database query, such as tasks, The result is returned.

@implementation ModuleAUriRegister

+ (void)load {
    [[YTRouterManager sharedRouterManager] registerPath:@"home/messagelist" actionBlock:^(YTRouterActionCallbackObject *callbackObject) {
        MessageListViewController *messageListVC = [MessageListViewController new];
        NSString *title = callbackObject.uri.params[@"title"];
        messageListVC.title = title;
        [[UIViewController yt_currentViewControlloer].navigationController pushViewController:messageListVC animated:YES];;
    }];
    [[YTRouterManager sharedRouterManager] registerPath:@"home/" actionBlock:^(YTRouterActionCallbackObject *callbackObject) {
        
    }];
    [[YTRouterManager sharedRouterManager] registerPath:@"home/messagelist/detail" actionBlock:^(YTRouterActionCallbackObject *callbackObject) {
        
    }];
    [[YTRouterManager sharedRouterManager] registerPath:@"home/messagelist/getmessage"ActionBlock: ^ (YTRouterActionCallbackObject * callbackObject) {/ / content correction! callbackObject.actionCallbackBlock ? : callbackObject.actionCallbackBlock(@"message content text demo");
    }];
}

@end
Copy the code

The client caller uses a simple path jump call using the runWithPath method of the YTRouterManager singleton object, passing a registered PATH parameter to complete the jump.

[self addActionWithTitle:@"Router page redirect" detailText:@"home/messagelist" callback:^{
    [[YTRouterManager sharedRouterManager] runWithPath:@"home/messagelist"];
}];
Copy the code

Use the runWithURLString method of the YTRouterManager singleton object to pass a complete URL containing scheme/ PATH, or arguments only if there are arguments. Such as “YTRouter: / / home/messagelist” and “YTRouter: / / home/messagelist? Title =Hello Message”, the routing component will parse out the scheme, Path, and params inside, and perform scheme filtering, Path query, YTRouterActionObject processing, and parameter transfer processing.

[self addActionWithTitle:@"Router calls using URL" detailText:@"YTRouter://home/messagelist" callback:^{
    [[YTRouterManager sharedRouterManager] runWithURLString:@"YTRouter://home/messagelist"];
}];

[self addActionWithTitle:@"Router is called using a URL with parameters" detailText:@"YTRouter://home/messagelist? title=Hello Message" callback:^{
    [[YTRouterManager sharedRouterManager] runWithURLString:@"YTRouter://home/messagelist? title=Hello Message"];
}];
Copy the code

The effect is shown below:

[self addActionWithTitle:@"Router get return value" detailText:@"home/messagelist/getmessage" callback:^{
    __block id message = nil;
    YTRouterActionCallbackObject *actionCallbackObject = [YTRouterActionCallbackObject new];
    actionCallbackObject.uri = [[YTUri alloc] initWithPath:@"home/messagelist/getmessage"];
    actionCallbackObject.actionCallbackBlock = ^(id result) {
        message = result;
    };
    [[YTRouterManager sharedRouterManager] runWithActionCallbackObject:actionCallbackObject];
    
    NSLog(@"message = %@", message);
}];
Copy the code

A few ideas: Registering a path in the load method has some impact on performance. If this becomes a performance bottleneck, consider initializing this part of the code in the object method. For example, the main module sends messages to each module, and then handles registering the YTRouterActionObject in each module. Consider parsing the path parameter to components for caching. This is a space-for-time strategy to improve lookup efficiency by using dictionaries instead of arrays to save The RouterActionObject

The original address my.oschina.net/FEEDFACF/bl…

Xiaobian here recommended a group: 691040931, which has a large number of books and interview materials, many iOS developers are in the exchange of technology