iOS Router — 续


上一篇提到 Router 的事情,又继续了激烈的讨论,有四个问题。

  1. topViewController 实现太粗糙,假设我有一个 controllerA。 内部显示上下两个子 controllerB 和 C(比如 B 是某种自定义的 topbar), C 要跳转到 D,但 B 不动,这个时候你会用 A 去跳转,导致 B 被覆盖。
  2. 另外,假如我们实现了一个 video player controller, 不同的地方调用他,显示的 size 不一样,比如列表页播放,则是一个 small size,详情页展示,则是全屏,这种情况,video player controller 自身如何得知自己“被”显示时,应该是什么 size
  3. 还有第三点,假设 B 是需要被打开的 controller,他需要的参数是 ENUM(或者 NSOption) 类型(定义在 B 中),A 如果通过 URL Router 的形式(不引用 B 的头文件),优雅的打开 B?
  4. 第四点,假设 A 打开 B,打开 B 后 A 还要常驻(不释放,并监听 B 的一些事件) 这种情况 URL Router 如何把 A 注册为 B 的 Observer。(B 的事件只是局部事件,并不适合走 NotificationCenter)

topViewController 的 child 转场

topViewController 实现太粗糙,假设我有一个 controllerA。 内部显示上下两个子 controllerB 和 C(比如 B 是某种自定义的 topbar), C 要跳转到 D,但 B 不动,这个时候你会用 A 去跳转,导致 B 被覆盖。

在考虑这个问题之前,我赶紧看了一下我的 topViewController 的实现。

func topViewController(base: UIViewController? = UIApplication.sharedApplication().keyWindow?.rootViewController) -> UIViewController? {
if let nav = base as? UINavigationController {
return topViewController(nav.visibleViewController)
}
if let tab = base as? UITabBarController {
if let selected = tab.selectedViewController {
return topViewController(selected)
}
}
if let presented = base?.presentedViewController {
return topViewController(presented)
}
return base
}

这部分代码并没有关心 childViewController ,当然,我觉得也没有必要去关心,毕竟没有什么好办法去知道哪个 childViewController 才是 topViewController 。画个图描述这个问题。

childControllerB -> childControlerD
childControllerB -> childControlerD

一个可以尝试的方案就是把需要的转场信息,诸如 offset size 等随 url 带过去,大部分的信息仍然可以用 JSON 传递。

此外,对于这种场景,本身 ABCD 的交互性就比较强,耦合性自然也比较强,本身不应该存在 URL Router 的事情,这些逻辑交给 A 来管理应该是更合适的,毕竟 BCD 都是 A 的 childViewController 。

from 参数

另外,假如我们实现了一个 video player controller, 不同的地方调用他,显示的 size 不一样,比如列表页播放,则是一个 small size,详情页展示,则是全屏,这种情况,video player controller 自身如何得知自己“被”显示时,应该是什么 size

这个解决起来不算麻烦,传递一个 from 字段即可,表明是从哪个地方过来的。

非 String 类型传递

还有第三点,假设 B 是需要被打开的 controller,他需要的参数是 ENUM(或者 NSOption) 类型(定义在 B 中),A 如果通过 URL Router 的形式(不引用 B 的头文件),优雅的打开 B?

首先,Swift 本身没有头文件一说(哈哈哈哈哈哈)。

既然 AB 都需要这个 enum ,为何不单独放到一个地方呢?大家一起引用/依赖这个 enum 。

此外,为 enum 提供一个 Int 或者 String 的等初始化方法就可以解决传值的问题。

ViewController 交互

如果交互不是很多的话,比如设置地址,只是在最后传递一下值,可以尝试提供的 POST 方法。当然,如果交互很多,那说明本身两个 ViewController 就是强耦合。既然本身二者就是强耦合的,那就没有什么必要通过 URL 解耦。这样做就好比是将两个东西放到一起,再分开,然后再以另一种方式放到一起的意思,这,这很尴尬。

事实上,我理解的 URL Router 本身就是建立在 ViewController 耦合不强的场景下诞生的。我们只是简单的进行一个赋值/传递值和调用一个转场方法。在这过程中产生了依赖关系,Router 的一个用途就是解决这种依赖关系。

ViewController 是什么

这里只是谈一谈个人的观点与理解。

正是因为 A 和 B 逻辑上没有什么关系,才通过 ViewController 将他们分开的。

ViewController 的用途之一就是将相关的逻辑怼到一起,方便管理,同时其属性 view 也方便了我们把相关的视图怼到一起管理。

我想对于一个 ViewControllerA 中放了很多 ViewControllerB 逻辑的代码一定不是我们想看到的。

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.