组件化

iOS底层系列30 -- 组件化

2022-03-08  本文已影响0人  YanZi_33

URL--Scheme路由

- (void)viewDidLoad {
    [super viewDidLoad];
//    self.title = @"First";
    self.view.backgroundColor = [UIColor cyanColor];
    [self addBtn];
    NSString *urlString = @"https://www.baidu.com/link?url=dAATY&eqid=81692b77c2ac&pwd=123456";
    NSURL *url = [NSURL URLWithString:urlString];
    
    NSLog(@"scheme = %@",url.scheme);
    NSLog(@"host = %@",url.host);
    NSLog(@"path = %@",url.path);
    NSLog(@"query = %@",url.query);
    NSLog(@"absoluteURL = %@",url.absoluteURL);
}
image.png
JLRoutes的源码分析
第一步:注册页面路由URL
+ (instancetype)routesForScheme:(NSString *)scheme
{
    JLRoutes *routesController = nil;
    
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        routeControllersMap = [[NSMutableDictionary alloc] init];
    });
    
    NSLog(@"%@",routeControllersMap[scheme]);
    if (!routeControllersMap[scheme]) {
        routesController = [[self alloc] init];
        routesController.scheme = scheme;
        routeControllersMap[scheme] = routesController;
    }
    
    routesController = routeControllersMap[scheme];
    
    return routesController;
}
image.png
- (void)addRoute:(NSString *)routePattern priority:(NSUInteger)priority handler:(BOOL (^)(NSDictionary<NSString *, id> *parameters))handlerBlock
{
    NSArray <NSString *> *optionalRoutePatterns = [JLRParsingUtilities expandOptionalRoutePatternsForPattern:routePattern];
    JLRRouteDefinition *route = [[JLRRouteDefinition alloc] initWithScheme:self.scheme pattern:routePattern priority:priority handlerBlock:handlerBlock];
    
    if (optionalRoutePatterns.count > 0) {
        // there are optional params, parse and add them
        for (NSString *pattern in optionalRoutePatterns) {
            [self _verboseLog:@"Automatically created optional route: %@", route];
            JLRRouteDefinition *optionalRoute = [[JLRRouteDefinition alloc] initWithScheme:self.scheme pattern:pattern priority:priority handlerBlock:handlerBlock];
            [self _registerRoute:optionalRoute];
        }
        return;
    }
    
    [self _registerRoute:route];
}
image.png
第二步:触发事件,传入页面路由,跳转到指定页面
- (BOOL)_routeURL:(NSURL *)URL withParameters:(NSDictionary *)parameters executeRouteBlock:(BOOL)executeRouteBlock{
    if (!URL) {
        return NO;
    }
    [self _verboseLog:@"Trying to route URL %@", URL];
    
    BOOL didRoute = NO;
    JLRRouteRequest *request = [[JLRRouteRequest alloc] initWithURL:URL alwaysTreatsHostAsPathComponent:alwaysTreatsHostAsPathComponent];
    
    for (JLRRouteDefinition *route in [self.mutableRoutes copy]) {
        // check each route for a matching response
        JLRRouteResponse *response = [route routeResponseForRequest:request decodePlusSymbols:shouldDecodePlusSymbols];
        if (!response.isMatch) {
            continue;
        }
        [self _verboseLog:@"Successfully matched %@", route];
        if (!executeRouteBlock) {
            return YES;
        }
        NSMutableDictionary *finalParameters = [NSMutableDictionary dictionary];
        [finalParameters addEntriesFromDictionary:response.parameters];
        [finalParameters addEntriesFromDictionary:parameters];
        [self _verboseLog:@"Final parameters are %@", finalParameters];
        
        //回调handler
        didRoute = [route callHandlerBlockWithParameters:finalParameters];
        
        //匹配 成功 终止循环
        if (didRoute) {
            // if it was routed successfully, we're done
            break;
        }
    }
    if (!didRoute) {
        [self _verboseLog:@"Could not find a matching route"];
    }
    if (!didRoute && self.shouldFallbackToGlobalRoutes && ![self _isGlobalRoutesController]) {
        [self _verboseLog:@"Falling back to global routes..."];
        didRoute = [[JLRoutes globalRoutes] _routeURL:URL withParameters:parameters executeRouteBlock:executeRouteBlock];
    }
    if (!didRoute && executeRouteBlock && self.unmatchedURLHandler) {
        [self _verboseLog:@"Falling back to the unmatched URL handler"];
        self.unmatchedURLHandler(self, URL, parameters);
    }
    return didRoute;
}
image.png
[[JLRoutes routesForScheme:"RouteOne"] addRoute:@"/push/:controller"handler:^BOOL(NSDictionary<NSString *,id> * _Nonnull parameters) {
    //根据触发事件 传入的页面路由 创建指定的页面控制器
    Class class = NSClassFromString(parameters[@"controller"]);
    UIViewController *nextVC = [[class alloc] init];
    //将页面路由中的参数 传递给页面控制器,实现了页面传参
    [self paramToVc:nextVC param:parameters];
    //获取当前导航控制器
    UIViewController *currentVc = [self currentViewController];
    [currentVc.navigationController pushViewController:nextVC animated:YES];       
    return YES;
}];
//传参数
-(void)paramToVc:(UIViewController *)v param:(NSDictionary<NSString *,NSString *> *)parameters{
    //runtime将参数传递至需要跳转的控制器
    unsigned int outCount = 0;
    objc_property_t * properties = class_copyPropertyList(v.class , &outCount);
    for (int i = 0; i < outCount; i++) {
        objc_property_t property = properties[i];
        NSString *key = [NSString stringWithUTF8String:property_getName(property)];
        NSString *param = parameters[key];
        if (param != nil) {
            [v setValue:param forKey:key];
        }
    }
}
- (UIViewController *)currentViewController{
    UIViewController * currVC = nil;
    UIViewController * Rootvc = self.window.rootViewController ;
    do {
        if ([Rootvc isKindOfClass:[UINavigationController class]]) {
            UINavigationController * nav = (UINavigationController *)Rootvc;
            UIViewController * v = [nav.viewControllers lastObject];
            currVC = v;
            Rootvc = v.presentedViewController;
            continue;
        }else if([Rootvc isKindOfClass:[UITabBarController class]]){
            UITabBarController * tabVC = (UITabBarController *)Rootvc;
            currVC = tabVC;
            Rootvc = [tabVC.viewControllers objectAtIndex:tabVC.selectedIndex];
            continue;
        }
    } while (Rootvc!=nil);
    
    return currVC;
}

Target-Action -- CTMediator

image.png
@implementation CTMediator (TAGoodsDetail)

- (UIViewController *)goodsDetailViewControllerWithGoodsId:(NSString *)goodsId goodsName:(NSString *)goodsName{
    NSMutableDictionary *params = [[NSMutableDictionary alloc] init];
    params[@"goodsId"] = goodsId;
    params[@"goodsName"] = goodsName;
    //核心 利用消息发送的原理 去调用TAGoodsDetail类的GoodsDetailViewController方法
    return [self performTarget:@"TAGoodsDetail" action:@"GoodsDetailViewController" params:params shouldCacheTarget:NO];
}
@end
#import "Target_TAGoodsDetail.h"
#import "TAGoodsDetailViewController.h"

@implementation Target_TAGoodsDetail

- (UIViewController *)Action_GoodsDetailViewController:(NSDictionary *)params{
    TAGoodsDetailViewController *goodsDetailVC = [[TAGoodsDetailViewController alloc] init];
    goodsDetailVC.goodsId = params[@"goodsId"];
    goodsDetailVC.goodsName = params[@"goodsName"];
    return goodsDetailVC;
}
@end
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    NSDictionary *goodsItem = self.dataSource[indexPath.row];
    UIViewController *goodsDetailVC = [[CTMediator sharedInstance] goodsDetailViewControllerWithGoodsId:goodsItem[@"goodsId"] goodsName:goodsItem[@"goodsName"]];
    
    if (goodsDetailVC) {
        [self.navigationController pushViewController:goodsDetailVC animated:YES];
    }
}

Protocol -- Class -- BeeHive

Module注册
以BHAnnotation中的宏定义注册Module
#define BeeHiveMod(name) \
class BeeHive; char * k##name##_mod BeeHiveDATA(BeehiveMods) = ""#name"";
#define BeeHiveDATA(sectname) __attribute((used, section("__DATA,"#sectname" ")))
__attribute__((constructor)) void initProphet() {
    _dyld_register_func_for_add_image(dyld_callback);
}
image.png image.png
Services注册
以BHAnnotation中的宏定义注册
#define BeeHiveService(servicename,impl) \
class BeeHive; char * k##servicename##_service BeeHiveDATA(BeehiveServices) = "{ \""#servicename"\" : \""#impl"\"}";
image.png image.png image.png
Service服务的调用
Snip20220310_14.png

参考文章

上一篇 下一篇

猜你喜欢

热点阅读