iOS 模块化之JLRoute路由示例

JLRoutes是一个调用极少代码 , 可以很方便的处理不同URL schemes以及解析它们的参数,并通过回调block来处理URL对应的操作 , 可以用于处理复杂跳转逻辑的三方库.

1.在日常开发中 , push , present 出现在整个程序的各个地方 , 如果你想快速理清一个项目的整体逻辑 , 非常麻烦 . 大多数情况 , 你得找到代码目录 ,根据层级结构分出关系 , 然后找到对应的push位置 , 寻找下一级页面 , 如果本身项目的目录就非常乱 , 那么如果要了解一个项目的整体跳转逻辑 , 非常的难.

即便可以将 UIViewController-Swizzled 库集成到项目中 ,然后一页一页点击查询 , 但也是比较痛苦的.

如果 , 是把整个项目的跳转逻辑都给抽取出来 , 单独放在一个类 , 模块化管理 , 那么思路就会清晰很多 , 甚至可以用XMind根据代码画出整个项目的树状图

2.如果所处公司存在多个app , app之间互相推荐 , 互相跳转是再正常不过的需求,就类似于QQ , 微信三方分享跳转等 .如果用Appdelegate原生方法进行拦截 , 所做的事至少得是判断Scheme是否匹配 , 想办法进入需要跳到的界面 , 如果要涉及传参 , 就更加麻烦.

3. 如果用户是从PC端识别二维码,或者通过链接想要进入app指定页面

基于 JLRoute 实现的模块化示例,包括链接跳转原生页面、WebView页面和ReactNative页面

模块化已经成为调剂庞大项目结构的一剂良药,对项目的开发、维护和后续的扩展的好处已经不言而喻。

要求

  1. iOS 8.0+
  2. Xcode 7.0+

安装方法

安装

在 iOS, 你需要在 Podfile 中添加.

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '9.0'
use_frameworks!

pod 'JLRoutes', '~> 2.0.1'

# 'node_modules'目录一般位于根目录中
# 但是如果你的结构不同,那你就要根据实际路径修改下面的`:path`
pod 'React', :path => './node_modules/react-native', :subspecs => [
  'Core',
  'RCTText',
  'RCTNetwork',
  'RCTWebSocket', # 这个模块是用于调试功能的
  # 在这里继续添加你所需要的模块
]
# 如果你的RN版本 >= 0.42.0,请加入下面这行
pod "Yoga", :path => "./node_modules/react-native/ReactCommon/yoga"

启动 ReactNative 环境

1.修改项目ModuleARNPageViewController.m IP 跳转地址

2.进入项目所在目录,运行

npm start

JLRoutes的工作流程和原理

单一的Scheme注册过程:

1.调用注册方法(用户注册routePattern,默认优先级0)

代码如下:

- (void)addRoute:(NSString *)routePattern handler:(BOOL (^__nullable)(NSDictionary<NSString *, id> *parameters))handlerBlock;

2.路由解析(这些解析跟我们设置路由的规则有直接关系)

(1)判断接口URL是否设置可选性URL并将对应的URL封装成JLRRouteDefinition对象

(2)将JLRRouteDefinition对象装载进一个可变数组,内存保留了所有的对象!!

(JLRRouteDefinition对象包括有路径,参数解析,block等信息)

单一的Scheme调用过程:

1.调用URL

+ (BOOL)routeURL:(NSURL *)URL

2.解析URL,将参数,路由信息封装成JLRRouteRequest对象

代码如下:

- (instancetype)initWithURL:(NSURL *)URL alwaysTreatsHostAsPathComponent:(BOOL)alwaysTreatsHostAsPathComponent

3.给JLrouteRequest对象和路由数组里的JLRRouteDefinition对象作比对,并且返回JLRRouteResponse 对象抽出参数和URL在数组里

代码如下:

JLRRouteResponse *response = [route routeResponseForRequest:request decodePlusSymbols:shouldDecodePlusSymbols];

4.调用JLRRouteResponse 对象里面的回调方法

[route callHandlerBlockWithParameters:finalParameters];

JLRoutes的URL注册规则:

1.普通注册

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
}];

URL里,分号表示这个是参数

另外一种注册方式,下标注册法

JLRoutes.globalRoutes[@"/route/:param"] = ^BOOL(NSDictionary *parameters) {
// ...
};

如何按照以上的方式注册,在任何时刻(包括在其它的APP)你都可以调用这个URL。

NSURL *viewUserURL = [NSURL URLWithString:@"myapp://user/view/joeldev"];
[[UIApplication sharedApplication] openURL:viewUserURL];

在这个例子中,在parmameters字典里面的userID会传给block,它是一个键值对。”userID”: “joeldev”。给UI层或者任何需要它的地方用的。

字典参数:

字典参数总包括至少一下3个键:

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

处理Block

你会发现,每个注册的block都会返回一个YES。这个值,如果你返回NO,JLRoutes会跳过这个匹配,然后继续去匹配其它的。

如果你的block设置成nil,它会默认返回YES。

2.复杂注册

[[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;
}];

这个地址会被匹配很多URL,如/user/view/joeldev or /post/edit/123。这些URL上的是参数。

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

这时,pramater字典就会是以下这样的(传参)

{
"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"
}

3.Scheme(有没有多态的感觉)

JLRoutes支持用指定的URL scheme来创建路由。相同的scheme才能被匹配。默认地,所有的URL会设置进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;
}];
如果你调用的使用,是这样调用的

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

它只会调用global scheme的对应的URL。不会调用ting scheme里面对应的URL。

当然,你可以设置,如果指定的scheme没有这个URL,去查询global scheme 有没有。你需要设置一个属性。

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

3.通配符的设置URL的方式

通配符为:*

通配符符后面所有的URL上的参数都会以一个数组保存在parameters字典里面的JLRouteWildcardComponentsKey对应的value里。

例如,如果你注册URL如下:

[[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 the joker's in it
return NO;
}];

如果调用的URL开始是/wildcard,这个路由就可能被触发!!如果第一个参数是joker,就被触发,如果不是,就被拒绝触发。。。

4.选择性路由

如果路由地址设置样式有括号,如:/the(/foo/:a)(/bar/:b),其实它代表的URL有如下:

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

5.查询 Routes

下面的方式,你可以查看Routes里所有注册的URL Routes。

/// All registered routes, keyed by scheme
+ (NSDictionary <NSString *, NSArray <JLRRouteDefinition *> *> *)allRoutes;
/// Return all registered routes in the receiving scheme namespace.
- (NSArray <JLRRouteDefinition *> *)routes;

自定义路由解析 如果你想自己定制一个路由编辑,你可以继承JLRouteDefinition并且用 addRoute:方法去添加你自定义类的对象。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • iOS路由(MGJRouter)的实现

    背景 最开始想做路由,是因为当时app中有大量与H5之间的交互,原生和H5的跳转操作比较多比较频繁,新增一个跳转又涉及到改代码发版本,为了统一iOS.安卓和H5的跳转,引入了路由. 作用 后来发现路由,还可很多作用.Router就像是个调度中心,各个模块通过路由调度其他模块,模块之间不需要相互引用,调度方式更加统一,更加自由,能够实现解耦的作用,同时也为之后的组件化开发提供了基础. 路由选择 目前github优秀的路由设计已经有很多,如JLRoutes,MGJRouter,CTMediator.

  • iOS使用核心的50行代码撸一个路由组件

    使用组件化是为了解耦处理,多个模块之间通过协议进行交互.而负责解析协议,找到目的控制器,或者是返回对象给调用者的这个组件就是路由组件.本文讲解如何使用核心的50行代码实现一个路由组件. 组件化和路由 路由的实现 路由注册实现 路由使用实现 客户端的使用 一些小想法 组件化和路由 之前看过挺多的关于路由管理.路由处理的文章,常常会和组件化出现在一起,一开始不知道为何路由和组件化出现在一起,后来公司的项目中使用了路由组件(他本身也是一个组件,确切的说是一个中间人或者中介者),才突然想明白了,原来如此

  • iOS开发之拦截URL转换成本地路由模块URLRewrite详解

    本文主要给大家介绍了关于iOS拦截URL转换成本地路由模块URLRewrite的相关内容,分享出来供各位iOS开发者们参考学习,下面话不多说了,来一起看看详细的介绍: 需求场景 做过电商App的可能都遇到过这样的需求,在商场首页,各种各样动态的跳转,跳转商品详情.秒杀列表.品牌列表.搜索结果.分类结果页面等等等等.同一个位置,可能今天跳这个商品,明天跳转那个商品,运营配的就是一个web端的URL. 拦截webView里面的URL. 需求分析 拦截各种各样的URL,跳转到指定的原生页面. URL的

  • iOS撸一个简单路由Router的实现代码

    平常开发中用户点击头像, 进入个人主页,这看似平常的操作, 背后极有可能会牵扯到多个模块. 再如: 视频模块的播放页, 有与视频相关的音乐,点击这些音乐,需要跳转到音乐模块的播放页, 这样视频与音乐模块之间,不可避免的会产生依赖或耦合. 这个问题让人脑壳疼,相信很多朋友都这样做过,写一些代理或通知, 不停的传递事件: 有时干脆直接导入另一个模块. 因为我在公司独立开发, 顾及少一点,可以拿公司项目做实践,在尝试组件化的过程中, 了解到了路由, 对于解决上述问题, 有极大的帮助.因此我想总结并与大

  • 如何在iOS上使用MVVM进行路由详解

    前言 我已经在几个项目中使用MVVM了一段时间,我真的很喜欢它的简单性.特别是,如果你像许多人一样从MVC迁移,你只需要在你的架构中增加一层ViewModel.如果您发现太多层级造成的复杂,这确实使事情变得更容易. 这是一个良好的开端,但这种简单并不总是好的.在MVVM中,您将业务逻辑移出视图控制器(VC),然后意识到它仍然很胖.视图模型(VM)现在具有业务逻辑,但是展示数据(格式化)或路由如何?他们仍然被困在VC中,我们需要将它们移出. #示例流程 假设我们正在实现登陆页面,如下所示. ##路

  • Vue+axios 实现http拦截及路由拦截实例

    现如今,每个前端对于Vue都不会陌生,Vue框架是如今最流行的前端框架之一,其势头直追react.最近我用vue做了一个项目,下面便是我从中取得的一点收获. 基于现在用vue+webpack搭建项目的文档已经有很多了,我就不再累述了. 技术栈 vue2.0 vue-router axios 拦截器 首先我们要明白设置拦截器的目的是什么,当我们需要统一处理http请求和响应时我们通过设置拦截器处理方便很多. 这个项目我引入了element ui框架,所以我是结合element中loading和me

  • iOS 模块化之JLRoute路由示例

    JLRoutes是一个调用极少代码 , 可以很方便的处理不同URL schemes以及解析它们的参数,并通过回调block来处理URL对应的操作 , 可以用于处理复杂跳转逻辑的三方库. 1.在日常开发中 , push , present 出现在整个程序的各个地方 , 如果你想快速理清一个项目的整体逻辑 , 非常麻烦 . 大多数情况 , 你得找到代码目录 ,根据层级结构分出关系 , 然后找到对应的push位置 , 寻找下一级页面 , 如果本身项目的目录就非常乱 , 那么如果要了解一个项目的整体跳转

  • IOS展开三级列表效果示例

    效果图如下: #import <UIKit/UIKit.h> @interface AppDelegate : UIResponder <UIApplicationDelegate> @property (strong, nonatomic) UIWindow *window; @end #import "AppDelegate.h" #import "RootViewController.h" @interface AppDelegate

  • 基于gin的golang web开发:路由示例详解

    Gin是一个用Golang编写的HTTP网络框架.它的特点是类似于Martini的API,性能更好.在golang web开发领域是一个非常热门的web框架. 启动一个Gin web服务器 使用下面的命令安装Gin go get -u github.com/gin-gonic/gin 在代码里添加依赖 import "github.com/gin-gonic/gin" 快速启动一个Gin服务器的代码如下 package main import "github.com/gin-

  • iOS开发之UIMenuController使用示例详解

    目录 简介 接口介绍 使用探索 如何创建并显示 UIMenuController 实现 Item 点击事件 菜单 Item 太多??? UIResponderStandardEditActions 协议 添加自定义菜单 箭头的方向 实际使用 总结 简介 UIMenuController 是一个菜单编辑界面,在很多地方都能用到,通常用于剪切.复制.粘贴.选择.全选和删除命令等,也可以自定义想要的操作,它长这样: 接口介绍 open class UIMenuController : NSObject

  • iOS封装倒计时按钮HLCountDownButton示例详解

    目录 引言 演示图 可选自定义属性 3种样式选择 回调说明 全局样式设置 引言 在开发中经常会用到倒计时的按钮,常用在发送短信验证码中.最差的写法是把代码写在ViewController中.这样的话如果项目中存在多个倒计时按钮,代码就十分臃肿了.所以封装一个倒计时按钮就迫在眉睫了.传送门HLCountDownButton,欢迎帮忙点点小星星 支持过xib.storyboard自定义样式 支持切换前后台计时准确 多种样式切换 支持CocoaPods导入pod "HLCountDownButton&

  • iOS模块化开发浅析

    背景:由于目前所在公司的iOS项目的依赖管理是比较原始的状态,但是APP功能又是越来越复杂的,这就带来的很多问题,比如开发时编译时间过长.模块间耦合严重.模块依赖混乱等.最近又听说这个项目中的部分功能可能需要独立出一个新APP,本着"Don't repeat yourself"的原则,我们试着抽离出原项目中的各个模块,并在新的APP中集成这些模块. 最近算是初步完成了新APP的模块化,也算是从中总结了一些经验拿出来分享一下.同时也完成了一个模块化框架TinyPart欢迎star. 模块

  • iOS中正则表达式的运用示例代码

    前言 有时我们需要在一大段长文本中过滤出我们需要的字段,或者检验该文本是否符合要求(该文本是否是邮箱,链接,电话号码或身份证),这时候就需要用到正则表达式了,iOS中也加入了相关的类来支持正则表达式的使用.本文详细介绍了关于iOS正则表达式运用的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 一.NSRegularExpression 1. 正则表达式的创建 + (nullable NSRegularExpression *)regularExpressionWith

  • iOS消息发送和转发示例详解

    前言 Objective-C 是一门动态语言,它将很多静态语言在编译和链接时期做的事情,放到了运行时来处理.之所以能具备这种特性,离不开 Runtime 这个库.Runtime 很好的解决了如何在运行时期找到调用方法这样的问题.下面话不多说了,来一起学习学习吧. 消息发送 在 Objective-C 中,方法调用称为向对象发送消息: // MyClass 类 @interface MyClass: NSObject - (void)printLog; @end @implementation M

  • 利用Spring Cloud Zuul实现动态路由示例代码

    前言 本文主要给大家介绍了关于Spring Cloud Zuul实现动态路由的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. Zuul 是提供动态路由,监控,弹性,安全等的边缘服务.Zuul 相当于是设备和 Netflix 流应用的 Web 网站后端所有请求的前门. Zuul 可以适当的对多个 Amazon Auto Scaling Groups 进行路由请求. 首先新建maven项目,加入如下依赖 <dependencyManagement> <depend

随机推荐