转载

iOS页面跳转之Router Swift实现

在app中页面跳转是无法回避的问题, 我们平常在代码中遇到跳转基本都是

let vc = UIViewController()  self.navigationController?.pushViewController(vc, animated: true)

后面出现了storyboard后可以通过连线进行跳转,传参通过

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)

获取到要跳转的对象进行传参, 后来还有了Reference可以跳到不同的storyboard,不得不说这样真的方便,但个人感觉这样同时也有一个缺点就是不明确, 我在追踪的时候不容易跟踪, 自己写的过段时间忘了或者说后来人看你写的代码很难理解

所以写了个简单的路由器, 现在网上也有类似的实现 比如 HHRouter routable-ios 等

现有项目要用Swift, 所以做了个Swift版本的跳转 有以下基本需求

1: 做到write once run anywhere,

2: 页面初始化支持code, xib, storyboard, 传参,

3: 基本页面跳转(push, present), 内部外部网页跳转,推送通知跳转

4: 松耦合

考虑到以上,写了个基本的Routable协议,如果这个ViewController要想支持跳转就必须实现这个协议

协议中的两个方法

一个是初始化, 一个是返回这个ViewController对应的key

public protocol Routable {  /** 类的初始化方法 - params 传参字典 */ static func initWithParams(params: RouterParam?) -> UIViewController /** 每个类跳转对应的key */ static var routableKey:String { get } }

同时在设置了根控制器之后,将此ViewController的key与类名进行对应起来

let router = Router.sharedInstance router.navigationController = nav  router.map(FirstViewController.routableKey, className: FirstViewController.description()) router.map(SecondViewController.routableKey, className: SecondViewController.description()) router.map(WebViewController.routableKey, className: WebViewController.description()) router.map(FirstNavigationController.routableKey, className: FirstNavigationController.description())

传参,由于Swift是强类型的,没办法字典中用了Any做为Value

public typealias RouterParam = [String: Any]

同时为了支持present时的动画效果,添加了RouterOptions来支持一些额外的效果或者要求

public class RouterOptions {     let presentationStyle: UIModalPresentationStyle     let transitionStyle: UIModalTransitionStyle     /** 只有在isModal为true是才会考虑modal下的style */     var isModal = false     /** 只对pushViewController有效 */     var shouldOpenAsRoot = false      public class func rootOptions() -> RouterOptions {         return RouterOptions(presentationStyle: .FullScreen, transitionStyle: .CoverVertical, isModal: false, isRoot: true)     }      public class func modalOptions() -> RouterOptions {         return RouterOptions(presentationStyle: .FullScreen, transitionStyle: .CoverVertical, isModal: true, isRoot: false)     }      public init(presentationStyle: UIModalPresentationStyle, transitionStyle: UIModalTransitionStyle, isModal: Bool) {         self.presentationStyle = presentationStyle         self.transitionStyle = transitionStyle         self.isModal = isModal     }      public init(presentationStyle: UIModalPresentationStyle, transitionStyle: UIModalTransitionStyle, isRoot: Bool) {         self.presentationStyle = presentationStyle         self.transitionStyle = transitionStyle         self.shouldOpenAsRoot = isRoot     }      private init(presentationStyle: UIModalPresentationStyle, transitionStyle: UIModalTransitionStyle, isModal: Bool, isRoot: Bool) {         self.presentationStyle = presentationStyle         self.transitionStyle = transitionStyle         self.isModal = isModal         self.shouldOpenAsRoot = isRoot     } }

调用open进入新界面,可以选择性的是否传入参数,动画效果, present时的options要求, push/present后的回调等

private func open(key: String, params: RouterParam?, options: RouterOptions?, animated: Bool, completion: ((opened: UIViewController?) -> Void)?) {  }

添加了基本的打电话,打开外部网页功能,打开外部app

同时写了基本的使用demo 详细代码见 Router

待优化的地方

1: 传参是否可优化?

2: 更多场景测试

3: 频繁open时是否需要容错,

4: 是否需要抛出Exception

你有什么好的建议也可留言

原文  http://www.ethanwhy.com/2016/07/13/ios-router-swift/
正文到此结束
Loading...