序
本篇介绍一下在iOS16以上如何设计swiftui路由功能
下一篇路由分析在这儿Swiftui 路由设计基础2 - 掘金 (juejin.cn)
目标
先讲讲一个路由希望能实现的功能吧.
- 定义多个模型跳转
- 支持参数,本地模型参数
- 支持本地路由
- 支持远程路由
- 支持注册
- 支持结果数据回调 目前的项目需要,我目前实现的是前三条功能,45我提供下思路,后续也许会更新,6的话目前没有太好的办法
问题讨论
为什么说需要在iOS16以上才能用
因为在swiftui设计中,他们提供的绝大部分api都是点击跳转,而本篇设计路由的api是围绕下面这个api设计,此api需要iOS16以上才能使用.
iOS16是否有办法设计路由呢
勉勉强强也是可以的,下面这个api提供了一个binding数据来支持代码跳转,不过写起来还是别扭,这里就不做展开了
功能实现
路由跳转模型
仅需实现Hashable,使用枚举的原因是struct,class都需要构造参数,如果有很多自定义参数的话写起来也麻烦,enum则方便很多,而且遍历的时候也能检查到所有路由.
对于模块化来说,每个模块自己建立自己的路由地址,然后注册到主项目中即可,比如MineDestination,MessageDestination,LiveDestination,而且这块儿也能解决掉注册路由的问题,我个人到目前为止没有遇到过需要动态注册路由,动态删除路由的需要(在我个人看来,路由的前置判断拦截即可)
路由跳转控制类
swiftui本身提供了一个跳转类, NavigationPath
该类提供了一系列api,这东西本质其实就是个数组,但是他不支持获取到数组中的元素,比如我想支持到backToController就很难实现.
public mutating func append<V>(_ value: V) where V : Hashable
public mutating func removeLast(_ k: Int = 1)
后来我发现自定义的路径数组也能够支持到路由跳转观察,于是就果断更换成自定义的数组,实现起来更自由.
路由注册逻辑
路由注册我给View写了个拓展,将所有的路由都注册进来,模块化的话可以遍历所有模块的enum来处理.
路由使用
远程路由
本地路由如上面所示,远程路由应与本地路由拆开,在远程路由解析完成后,转到本地路由解析,这个转化逻辑应该由各个子模块自己实现,子模块自己提供远程路由的解析功能. 我在iOS(Swift) 路由设计二 - 简书 (jianshu.com)中曾经写了一篇完完全全使用远程路由解析的uikit路由设计,其实现在回过头看还是稍微有些幼稚,本地路由和远程路由本就可以相互分解,我却硬生生将其柔和在一起,使得代码中调用也需要使用dictionary传参,确实太过幼稚,当时甚至还将它发布到了cacaoapod库去了(其实只是为了测试一下公共库发布流程😆)
结果数据回调
这块儿我确实没有什么好办法实现,比如跳转到生日选择页面,等待生日结果的返回,这块儿flutter做的确实就很舒服.我目前写完的swiftuiApp也是比较简单的项目,没有几个页面需要支持结果范围,所以就统一封装了个通知来处理
结尾
其实路由这块儿还有一些坑,当时也是边踩边填,比如NavigationStack使用位置的问题,导致viewmodel会先释放一次等等,比如根页面替换问题需要注意NavigationStack的rootController等等,这块儿就不多说了,本篇只是个基础介绍篇,如果有什么好的理解或建议,欢迎评论.如果本文对你有一点点帮助,希望能帮忙点点赞,万分感谢!