Router

方案比较, 新项目, 想法

Posted by poos on October 16, 2019

组件化方案

因为 Router 在本质上也是将一个个 feature 隔离提供,所以也算是组件化方案里的一环了。

组件化方案

Router 应当有的功能

将 Router 泛化之后,几乎所有独立的功能可以使用 Router 来操作,例如页面跳转,action sheet,login等,甚至 App 之间相互调用 等

  • 不同 feature 跳转
  • 支持 Deep Link 等
  • 页面跳转支持多种跳转方式,push,present,custom 等
  • 开放 Protocol, 支持生命周期控制

示例

先从最基本的 Code 写起来,最后再展示封装后使用方式.

你就会发现 delegate 的生命周期的设计,这也是为了一些特殊方案的预设。虽然在同一个项目里面的话使用频率不会很高,但是如果划分 framework,在不同的 workspace 工作的时候,它的作用就体现出来了。

delegate 在 iOS Foundation, UIKit, WebKit 等一些地方有非常多的使用,这里也有参考的一些思想。

利用 Protocol 和 Enum 定义基本属性

例如跳转可以使用这样的方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
enum NavigationType {
  case push(from: UIViewController, to: UIViewController, animated: Bool)
  case present(from: UIViewController, to: UIViewController, animated: Bool, completion: (()->Void)?)
  case custom(from: UIViewController, to: UIViewController)
}

//info can include vision
enum ActionType {
  case share(info: [AnyHashable : Any])
  case sheet(info: [AnyHashable : Any])
  case laluchApp(info: [AnyHashable : Any])
}

enum xxxxType {}

在跳转添加 delegate 等

1
2
3
4
5
6
protocol RouterLifeCycle {
  func prepare(_)
  func willRouter(_) -> Bool
  func didRouter(_)
  func didError(_, ErrorClosure)
}

从 notification 拿来的 Deeplink 信息

1
2
3
4
5
struct Deeplink {
  var destinationKey: String
  var type: String
  var userInfo: [AnyHashable : Any]
}

RouterManager

应当实现 Router 并且实现生命周期方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
class RouterDB {
  var map: [AnyHashable : Any]

  ...


  func navigate(...) {   }

  func action(...) {   }

  func module(...) {   }

  ...
}


struct Router {

  var delegate: RouterLifeCycle?

  var type: NavigationType?

  conveniences init(...)


  func navigate(_ type: NavigationType) {
    delegate?.prepare()

    guard let delegate = self.delegate, delegate.willRouter() else {
      delegate?.didError(Error(<xxx>))
      return
    }
    switch type {

    }

    delegate.didRouter()
  }


  func action(_ action: ActionType) { ... }
}

使用

链式语法的Event Track

简单的 router:

1
2
3
4
static let AppRouter = Router.default

AppRouter.navigate(.push(from: VC1, to: VC2))
AppRouter.action(.sheet(...))

有生命周期的 router:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class A {
   lazy var router = Router(delegate: self)


   func someAction() {
     AppRouter.navigate(.push(from: VC1, to: VC2))
     AppRouter.action(.sheet(...))
   }
}

/*
//Apple - Operation - Api - Example

isCancelled - read-only

isAsynchronous - read-only

isExecuting - read-only

isFinished - read-only

isReady - read-only

dependencies - read-only

queuePriority - readable and writable

completionBlock - readable and writable
*/

extension A: RouterLifeCycle {
  func prepare(_)
  func willRouter(_) -> Bool
  func didRouter(_)
  func didError(_, ErrorClosure)
}

当然,如果使用了 RX,也可以将 delegate 的各个函数封装使用,会更方便

组合使用

如果你的 Router 划分的足够节点化,那么有可能对 Router 的层级进行划分,通过多个节点的组合,可以实现一个大的 router ~ 这也是 Router 的意义之一吧~

最后

本文只是一个轻量级的基础框架,因为业务之初往往是比较简单的。框架的作用就是在业务变得复杂时候,可以用最小的修改去适应~