本篇文章主要介绍了" iOS系统中导航栏的转场解决方案与最佳实践",主要涉及到方面的内容,对于IOS开发感兴趣的同学可以参考一下:
背景目前,开源社区和业界内已经存在一些 iOS 导航栏转场的解决方案,但对于历史包袱沉重的美团 App 而言,这些解决方案并不完美。有的方案不能满足复杂的页面跳...
背景
目前,开源社区和业界内已经存在一些 iOS 导航栏转场的解决方案,但对于历史包袱沉重的美团 App 而言,这些解决方案并不完美。有的方案不能满足复杂的页面跳转场景,有的方案迁移成本较大,为此我们提出了一套解决方案并开发了相应的转场库,目前该转场库已经成为美团点评多个 App 的基础组件之一。
在美团 App 开发的早期,涉及到导航栏样式改变的需求时,经常会遇到转场效果不佳或者与预期样式不符的“小问题”。在业务体量较小的情况下,为了满足快速的业务迭代,通常会使用硬编码的方式来解决这一类“小问题”。但随着美团 App 业务的高速发展,这种硬编码的方式遇到了以下的挑战:
业务模块的不断增加,导致使用硬编码方式编写的代码维护成本增加,代码质量迅速下降。
大型 App 的路由系统使得页面间的跳转变得更加自由和灵活,也使得导航栏相关的问题激增,不但增加了问题的排查难度,还降低了整体的开发效率。
App 中的导航栏属于各个业务方的公用资源,由于缺乏相应的约束机制和最佳实践,导致业务方之间的代码耦合程度不断增加。
从各个角度来看,硬编码的方式已经不能很好的解决此类问题,美团 App 需要一个更加合理、更加持久、更加简单易行的解决方案来处理导航栏转场问题。
本文将从导航栏的概念入手,通过讲解转场过程中的状态管理、转换时机和样式变化等内容,引出了在大型应用中导航栏转场的三种常见解决方案,并对美团点评的解决方案进行剖析。
重新认识导航栏
导航栏里的 MVC
在 iOS 系统中, 苹果公司不仅建议开发者遵循 MVC 开发框架,在它们的代码里也可以看到 MVC 的影子,导航栏组件的构成就是一个类似 MVC 的结构,让我们先看看下面这张图:

在这张图里,我们可以将 UINavigationController 看做是 C,UINavigationBar 看做是 V,而 UIViewController 和 UINavigationItem 组成的 Stack 可以看做是 M。这里要说明的是,每个 UIViewController 都有一个属于自己的 UINavigationItem,也就是说它们是一一对应的。
UINavigationController 通过驱动 Stack 中的 UIViewController 的变化来实现 View 层级的变化,也就是 UINavigationBar 的改变。而 UINavigationBar 样式的数据就存储在 UIViewController 的 UINavigationItem 中。这也就是为什么我们在代码里只要设置 self.navigationItem 的相关属性就可以改变 UINavigationBar 的样式。
很多时候,国内的开发者会将 UINavigationBar 和 UINavigationController 混在一起叫导航栏,这样的做法不仅增加了开发者之间的沟通成本,也容易导致误解。毕竟它们是两个完全不一样的东西。
所以本文为了更好的阐明问题,会采用英文区分不同的概念,当需要描述笼统的导航栏概念时,会使用导航栏组件一词。
通过这一节的回顾,我们应该明确了 NavigationItem、ViewController、NavigationBar 和 NavigationController 在 MVC 框架下的角色。下面我们会重新梳理一下导航栏的生命周期和各个相关方法的调用顺序。
导航栏组件的生命周期
大家可以通过下图获得更为直观的感受,进而了解到导航栏组件在 push 过程中各个方法的调用顺序。