PS 感谢大家的关注,由于我本想开源4个库,除了router, 另外三个分别是native dispatcher, web dispatcher 和 react dispatcher , 所以router 对native dispatcher 有了库依赖,为了共同学习,我把router单独分离成pod,再次感谢大家的关注,欢迎叫router更完善。best regards.

如何优雅的实现界面跳转 之 统跳协议 - DarwinNativeRouter


@author Jou Email Weibo or Github


预热 - 我要解决的问题

首先我还是要推荐Gaosboy的这篇文章解耦神器 —— 统跳协议和Rewrite引擎
文章中,介绍了天猫app,基于文件配置和uri的页面跳转。这大大增加了app端的灵活性, 而这种实现很类似今天的前端或后端开发中的 静态路由 和 动态路由协议。
除了天猫,在很多的客户端架构的文章中,路由解耦的案例并不不少见,如携程移动App架构优化之旅
蘑菇街App的组件化之路
原生路由协议, 其实两年前就有了类似的实现。比如900+Star的HHRouter,而作者是当时还在布丁动画工作的Light。2015年我有幸见到本人,人很nice,并真是全栈。
DarwinNativeRouter 在接口设计上,很大程度上的参考了现有的react路由协议 react router。并且对原生跳转方式保留很大的可扩展性。所以我的初衷 DarwinNativeRouter 是一个足够轻量级的框架。Light & Flexible。

全局路由协议能解决的问题

错中复杂的Controller的跳转依赖

在iOS的世界里,传统的Controller跳转方式, A 跳转 B, 则 A 必须持有 B 的对象。 而在app长大的过程中, 势必会造成 A -> B , B -> C, A -> C D, E, F...
从而产生复杂的依赖链。全局的Router 使 A 不必依赖于 特定的 Controller 便可以实现跳转。

如下面跳转:

We Always Do:

   UIViewController *personal = [UIViewController new];
personal.userId = @"";
[self.navigationController pushViewController:personal animated:YES];
Router Code:
  [[DNRouter router]open:@"./user/10238372/profile"]; 

又比如我们要在navigationController根路径跳转

We Always Do:

   [self.navigationController popToRootViewControllerAnimated:NO];
UIViewController *personal = [UIViewController new];
personal.userId = @"";
[self.navigationController pushViewController:personal animated:YES];
Router Code:
      [[DNRouter router]open:@"/user/10238372/profile"];
推送通知,点击打开指定页面

对于这种需求, 相信,目前最多的实现应该是两种, 一种的传参的Url, 而另一种,是传递int类型,并通过类似switch case对参数值的硬编码,实现跳转逻辑。
我是很反感第二种的跳转方式, 1. int毫无疑义, 只能硬解释。 2. 跳转的页面有限。 当然如果url采用硬编码, 也是跳转有限的。
而有了router,一切不一样。

  1. 从didFinishLaunchingWithOptions 和 didReceiveRemoteNotification捕获payload

  2. 跳用Router

Somethings we may do:

 switch (type) {
case :
//jumping code
break; case :
//jumping code
break;
case :
//jumping code
break;
case :
//jumping code
break; default:
break;
}

Now we need do:

  if([[DNRouter router]canOpen:url.absoluteString]) [[DNRouter router]open:url.absoluteString]; 
app间通讯 及 deeplink

Router 可以轻松handle deeplink。 deeplink 即: 从safari打开app的指定页面。 这方面做得比较好的, 如新浪微博的app, 在点击对应的新浪微博热点 条目时, 就发生了跳转,并跳到了条目详情。
Router, 同样可以被用作 app 间通讯, 和 deeplink 的原理相同。uri的通讯方式,被认为是最简单的app间通讯。 如我们常常使用的微信分享,配置的 scheme 就是用来做跳转和通讯的。

Router Code

 - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString*, id> *)options
{
if([[DNRouter router]canOpen:url.absoluteString])
{
[[DNRouter router]open:url.absoluteString];
return YES;
}
return NO;
}

一致的行为处理, Hybrid & React Native

有了Router, 你可以使这些跳转 有一致的行为。

DarwinNativeRouter 特性

静态路由 /user

 [DNRouter routerWithName:@"profile" path:@"/user"
navigationController:(UINavigationController *)self.window.rootViewController
controller:^__kindof UIViewController *{ UIViewController *controller = [[UIStoryboard storyboardWithName:@"Main" bundle:nil]instantiateViewControllerWithIdentifier:@"kMainBoard"];
return controller; } action:^(__kindof UIViewController *controller) { [DNDispatcher dispatcher].defaultNavigationController.animation(NO).pushViewController(controller);
// 希望大家注意下动画的设置,若animation设为YES, 容易造成animation system的混乱,需要保证最后一个push的前的所有controller的动画为NO. }];
动态路由 /user/:id
 [DNRouter routerWithName:@"profile" path:@"/user/:id"
navigationController:(UINavigationController *)self.window.rootViewController
controller:^__kindof UIViewController *{ UIViewController *controller = [[UIStoryboard storyboardWithName:@"Main" bundle:nil]instantiateViewControllerWithIdentifier:@"kMainBoard"];
return controller; } action:^(__kindof UIViewController *controller) { [DNDispatcher dispatcher].defaultNavigationController.animation(NO).pushViewController(controller);
// 希望大家注意下动画的设置,若animation设为YES, 容易造成animation system的混乱,需要保证最后一个push的前的所有controller的动画为NO.
}];
更方便的跳转,名称跳转 name jumping
  [[DNRouter router]redirect:@"profile"]; 
相对路径跳转
//跟路径
[[DNRouter router]open:@"/user"]; //当前路径
[[DNRouter router]open:@"./user"]; //上一级
[[DNRouter router]open:@"../user"];

易扩展, 自定义跳转 action

[DNRouter routerWithName:@"profile" path:@"/user/:id"
navigationController:(UINavigationController *)self.window.rootViewController
controller:^__kindof UIViewController *{ UIViewController *controller = [[UIStoryboard storyboardWithName:@"Main" bundle:nil]instantiateViewControllerWithIdentifier:@"kMainBoard"];
return controller; } action:^(__kindof UIViewController *controller) { [DNDispatcher dispatcher].defaultNavigationController.animation(YES).pushViewController(controller); }];

默认行为,及 异常处理,index & 404

// index page
[DNRouter defaultRouterWithController:^__kindof UIViewController *{ } action:^(__kindof UIViewController *controller) { }]; // 404 page
[DNRouter notFoundRouterWithController:^__kindof UIViewController *{ } action:^(__kindof UIViewController *controller) { }];

后言

DarwinNativeRouter 现在还没有到1.0版本,还有很多可以想象的东西,欢迎让他更加完善,和提pr。
DarwinNativeRouter's Github

@author Jou Email Weibo or Github

如何优雅的实现界面跳转 之 统跳协议 - DarwinNativeRouter的更多相关文章

  1. 页面解耦—— 统跳协议和Rewrite引擎

    原文: http://pingguohe.net/2015/11/24/Navigator-and-Rewrite.html 解耦神器 —— 统跳协议和Rewrite引擎 Nov 24, 2015 • ...

  2. ASP.Net MVC跳转,分为form的submit提交跳转和ajax跳转

    1,用jquery ajax跳转的话,需要在前台用window.location("跳转网址")来跳转,在success后使用 2,用原声的form的submit来跳转,如下图 3 ...

  3. [HTML]js实现页面跳转,页面A跳到另一个页面B.以及页面传值(中文)

    要实现从一个页面A跳到另一个页面B,js实现就在A的js代码加跳转代码 JS跳转大概有以下几种方式: 第一种:(跳转到b.html)<script language="javascri ...

  4. JSP中客户端跳转与服务器端跳转的区别

    转载自:https://www.cnblogs.com/memewry/archive/2012/08/21/2649988.html 客户端跳转时用HttPservletResopse对象的send ...

  5. react跳转url,跳转外链,新页面打开页面

    react中实现在js中内部跳转路由,有两种方法. 方法一: import PropTypes from 'prop-types'; export default class Header exten ...

  6. 剑指offer例题——跳台阶、变态跳台阶

    题目:一只青蛙一次可以跳上1级台阶,也可以跳上2级.求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果). 思路: n<=0时,有0种跳法 n=1时,只有一种跳法 n=2时,有 ...

  7. [Java]Get与Post,客户端跳转与服务器端跳转

    http://www.thinksaas.cn/group/topic/133101/ 虽然说get 与post 问题很老套了,但是作为web 开发人员来说对于这个的理解确实很有必要,其实说到get  ...

  8. 7、斐波那契数列、跳台阶、变态跳台阶、矩形覆盖------------>剑指offer系列

    题目:斐波那契数列 大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0). f(n) = f(n-1) + f(n-2) 基本思路 这道题在剑指offe ...

  9. Web开发中的服务器跳转与客户端跳转

    两者比较如下: 跳转类型  客户端请求次数 服务端响应次数 URL变化 站外跳转 作用域 服务器跳转 1 1 无 否 pageContext.request.session.application 客 ...

随机推荐

  1. <Chapter 2>2-2-2.开发Java应用(Developing a Java App)

    App Engine的Java网络应用使用了Java Servlet标准接口来和应用服务器交互.一个应用由一个或多个servlet类组成,每个都扩展了(extend)servlet基类.使用一个叫做部 ...

  2. [AngularJS学习笔记] 基础学习01

    2016-06-06开始学习AngularJS AngularJS是会extend HTML的 ng-directives 先学习了四个 ng-app:定义AngularJS Application的 ...

  3. APACHE如何里一个站点绑定多个域名?用ServerAlias

    APACHE2如何里一个站点绑定多个域名?用ServerAlias以前很笨,要使多个域名指向同一站点总是这样写: <VirtualHost *:80>ServerAdmin i@kuigg ...

  4. Spark SQL概念学习系列之为什么使用 Spark SQL?(二)

    简单地说,Shark 的下一代技术 是Spark SQL. 由于 Shark 底层依赖于 Hive,这个架构的优势是对传统 Hive 用户可以将 Shark 无缝集成进现有系统运行查询负载. 但是也看 ...

  5. mysql注册服务

    http://www.2cto.com/database/201301/185456.html ____________________________________________________ ...

  6. JavaScript——对this指针的新理解

    一直以来对this的理解只在可以用,会用,却没有去深究其本质.这次,借着<JavaScript The Good Parts>,作了一次深刻的理解.(所有调试都可以在控制台中看到,浏览器F ...

  7. Delphi异形窗口之PNG

    //1.单元内容 unit UnitAlienForm; interface uses Windows, Forms, Classes, Graphics; //从文件加载PNG procedure ...

  8. 【三支火把】---CDS5516舵机调试以及自己的感想!

    我依然坚持,任何一次自己的心有感触都要及时的记录下来,这样你的努力才是真正的努力. 这两天一直在用STM32调试CDS5516舵机,其实很简单,但是却花了将近两天的时间,过程之曲折我就不说了,先总结一 ...

  9. 学习php 韩顺平 数据类型 三元运算,字符串运算类型运算

    数据类型 整型:int 4个字节长度 1个字节8个bit 所以最大的整型数值是2的31次方 第一位是的0,1 表示正负,0表示正数,1表示负数 小数(float)分 精度计算  从左边开始算第一个不为 ...

  10. ASP.NET forms凭据设置和跳转的几种方法

    string user = "userName"; //默认的第1种,超时时间是在web.cofig中forms设置的timeout,单位是分钟,生成的cookie和凭证超时时间一 ...