前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >大前端开发中的路由管理之四:iOS篇

大前端开发中的路由管理之四:iOS篇

作者头像
QQ音乐技术团队
发布2021-11-15 10:10:30
1.8K0
发布2021-11-15 10:10:30
举报

1、iOS上的页面展示和逻辑

1.1 iOS的MVC设计模式

        在介绍iOS的页面展示之前,我们需要先知道iOS应用的运行逻辑和设计模式。MVC即Model,View,Controller(模型,视图,控制器)。

  • View上展示的东西,由Model来定义
  • View上展示的逻辑,由Controller来控制
  • Controller同样负责初始化Model,和传递Model的信息给View

        用户在View层中所进行的创建或修改数据的操作,通过Controller对象传达出去,最终会创建或更新Model。Model更改时(例如通过网络连接接收到新数据),它会通知Controller对象,Controller对象更新相应的View对象。

2、Controller 的页面管理

        上文提到,iOS中通过Controller(控制器)来管理View的绘制逻辑,那么具体是如何实现的呢?

        在iOS中,有两类ViewController:

  • 一类用来展示内容,例如UIViewController,UITableViewController
  • 一类用来作为容器,例如UINavigationController,UITabBarController

        其中,容器类ViewController是这篇文章关注的重点,因为他们管理着View的显示逻辑。

        容器类ViewController都是通过持有一个ViewController的数组来管理,一般来讲UINavigationController是通过先进后出(First In Last Out)的方式来管理,而UITabBarController则不局限于此。

        不管是哪类ViewController,都继承自UIViewController。View作为一个ViewController的属性(property)存在,其生命周期在ViewController的生命周期内。

3、多页面栈的管理方法

        有了上文的铺垫,接下来可以更加细致地介绍iOS中多页面栈的管理方法。正如之前提到的,多页面即多个View。iOS中采用容器类的ViewController来管理多个ViewController,而每个ViewController又对应着自己的View,从而实现统一管理。

3.1 容器类ViewController对于页面的管理

3.1.1 多页面切换的逻辑

        以UINavigationController为例,作为官方推荐的容器类控制器,继承于UIViewController。UINavigationController通过栈的方式管理控制器的切换,控制入栈和出栈来展示各个视图控制器。

        同时UINavigationController还持有屏幕上方的交互栏(navigationBar)和屏幕下方的工具栏(toolBar),并控制他们是否可见。

        根据官方的文档,UINavigationController每次只会展示一个ViewController的View,每次进入到一个View的时候会push这个ViewController到navigation stack的最上层,覆盖并隐藏起其他的页面。而点击应用上方的NavigationBar返回按钮(如果没有隐藏起来的话)就会pop当前的ViewController,也就是返回上一层。

3.1.2 多页面切换的实现方法

        UINavigationController通过一个ordered array来管理,叫做navigation stack。

        应用默认的UINavigationController的第一个view controller是根视图控制器,即 root view controller,放在stack的最底层,最新的在最高层。

UINavigationController* nav = [[UINavigationController alloc] init];//    新建两个ViewController,并设置他们的View的背景颜色UIViewController* vc1 = [[UINavigationController alloc] init];vc1.view.backgroundColor = [UIColor redColor];UIViewController* vc2 = [[UINavigationController alloc] init];vc2.view.backgroundColor = [UIColor blueColor];    [nav pushViewController:vc1 animated:NO];   //把vc1推到nav的stack中[nav pushViewController:vc2 animated:NO];   //把vc2推到nav的stack中
UIViewController* top = nav.topViewController;  //这时top其实就是vc2
[nav popViewControllerAnimated:NO];             //这时nav的顶层VC被pop出,top变成vc1

        通过解析源码的方法,发现UINavigationController不仅有简单的pushViewController和popViewController,还有popToViewController以及popToRootViewController这种指定的页面跳转,同时也可以添加动画效果,可操作范围还是比较大的。

//承接上面的代码..[nav popToViewController:vc1 animated:NO];[nav popToRootViewControllerAnimated:NO];

        跟所有UIViewController一样,UINavigationController通过自己的代理(delegate)来实现方法,可以重写他的push和pop来实现自己的动画效果,但需要遵循UINavigationControllerDelegate这个协议。

一张图概括NavigationController的结构

3.2 通用的页面切换方式

        容器类的ViewController通过一个特定的结构来实现多层级管理,但并不是所有页面都能确保是在同一个容器中,这个情况下ViewController基类提供了以自己为起点的页面跳转:

        以ViewController自己为基础,可以得到自己的父控制器(parentViewController);自己展示的控制器(presentedViewController);展示自己的控制器(presentingViewController)。

        得到了控制器,切换的方法也由ViewController类直接提供:

UIViewController* vc3 = [[UIViewController alloc] init];vc2 = vc3.parentViewController;     //父控制器vc2 = vc3.presentedViewController;  //vc3展示的控制器vc2 = vc3.presentingViewController; //展示vc3的控制器[vc3 presentViewController:vc2 animated:NO completion:nil];[vc3 dismissViewControllerAnimated:vc2 completion:nil];

3.3 自定义转场方式的页面切换

        上述的ViewController的转场方式是比较通用的方式,也许你会注意到,他还会收取一个animated的参数。这个参数就是询问你是否需要在页面切换的时候加入动画。默认的动画就是从右往左推出一个新的页面。但UIViewController还有一个方法可以自定义这个转场动画:

[vc3 transitionFromViewController:vc2                 toViewController:vc1                         duration:0.5                          options:UIViewAnimationOptionTransitionFlipFromRight                       animations:^{}                       completion:nil];

        这个方法就可以自定义转场方式了,可以看见我们在这里设置动画的时间是0.5秒,效果是从右边翻页入场。

3.4 状态的保存和回溯

        从源码中可以发现ViewController实现了一个叫做UIStateRestoring的协议,所以持有一个叫做restorationIdentifier的属性,给他赋予一个NSString的值,会让ViewController在App被放到后台之前完成编码(保存)。保存的时候ViewController会把他内部的所有带有同样restorationIdentifier的子视图控制器(child view controller)的状态也一起保存下来。但ViewController自己不会自动保存其他的状态。

        如果自己实现一个容器类的ViewController,就需要自己去给子视图控制器编码,保证每一个都必须是有独一无二的 restorationIdentifier。

3.5 多页面的内存管理

        每个UIViewController的类都会有自动的内存管理,通过didReceiveMemoryWarning这个方法来释放不需要的内存,进而管理low-memory condition。

        如果多层级页面过多,清理过之后物理内存还是不满足,就会发生out of memory crash。

        统计iOS设备的内存上限:以 iPhone XS Max 为例,总共的可用内存是 3735 MB(比硬件大小小一些,因为系统本身也会消耗一部分内存),而单个 app 可用内存达到 2039 MB,达到了 55%。当 app 使用的内存超过这个临界值,就会发生 OOM 崩溃。

4、总结

        多层级页面的管理由ViewController运营,同时包含有各种的view controller 分类结构来完成复杂的页面跳转或是实现不同的页面功能,如展示类ViewController和容器ViewController。

        容器类控制器会根据添加的member value来决定是否需要留存之前的状态,会保存带有restorationIdentifier的所有ViewController的状态。但是内存有限制,如果进程根据didReceiveMemoryWarning的警告清理了内存却还是不够,应用就会崩溃。


        至此,我们了解到了iOS端是如何去实现路由管理的,那么,就请期待我们下一篇文章《大前端开发中的路由管理之五:Flutter篇》吧,下篇文章将为大家揭秘Flutter是如何去做路由管理的。

参考资料

[1] View Programming Guide for iOS

https://developer.apple.com/library/archive/documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/Introduction/Introduction.html#//apple_ref/doc/uid/TP40009503-CH1-SW2

[2] iOS MVC、MVVM、MVP详解

https://www.jianshu.com/p/d39a5eee48d7

[3] window and view 架构

https://blog.csdn.net/qq_30185503/article/details/102758732

[4] 深入理解ViewController以及view的加载

https://www.jianshu.com/p/52072a0d49c3

[5] UINavigationController 的详解(基于 API )

https://juejin.cn/post/6844903543262937096

[6] class UINavigationController

https://developer.apple.com/documentation/uikit/uinavigationcontroller?language=objc

QQ音乐招聘 Android / iOS 客户端开发,点击左下方“查看原文”投递简历~

也可将简历发送至邮箱:tmezp@tencent.com


文末为大家推荐一个技术号《腾讯音乐天琴实验室》,TME天琴实验室致力于对业内前沿科技如AI等方向进行相关研发,持续推出新技术提升TME旗下QQ音乐等平台的音乐视听体验,对音视频相关AI研发感兴趣的同仁们一起交流学习起来吧!!!

↓   ↓   ↓

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-11-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 腾讯音乐技术团队 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.1 iOS的MVC设计模式
    • 3.1 容器类ViewController对于页面的管理
      • 3.1.1 多页面切换的逻辑
      • 3.1.2 多页面切换的实现方法
    • 3.2 通用的页面切换方式
      • 3.3 自定义转场方式的页面切换
        • 3.4 状态的保存和回溯
          • 3.5 多页面的内存管理
          • 4、总结
          • 参考资料
          相关产品与服务
          容器服务
          腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档