iOS开发-ViewController的生命周期相关

2023-11-29 18:32

本文主要是介绍iOS开发-ViewController的生命周期相关,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • ViewController生命周期
    • 加载流程
    • didReceiveMemoryWarning
  • View的layoutSubviews
    • Runloop相关
  • view的drawRect:方法

ViewController生命周期

加载流程

在这里插入图片描述

1.init或者initWithCoder:(NSCoder *)aDecoder:(如果使用storyboard或者xib)
2.loadView:加载view
3.viewDidLoad:view加载完毕
4.viewWillAppear:控制器的view将要显示
5.viewWillLayoutSubviews:控制器的view将要布局子控件
6.viewDidLayoutSubviews:控制器的view布局子控件完成
这期间系统可能会多次调用viewWillLayoutSubviews、viewDidLayoutSubviews俩个方法7.viewDidAppear:控制器的view完全显示
8.viewWillDisappear:控制器的view即将消失的时候
这期间系统也会调用viewWillLayoutSubviews 、viewDidLayoutSubviews 两个方法9.viewDidDisappear:控制器的view完全消失的时候

didReceiveMemoryWarning

Discussion Your app never calls this method directly. Instead, this
method is called when the system determines that the amount of
available memory is low.

You can override this method to release any additional memory used by
your view controller. If you do, your implementation of this method
must call the super implementation at some point.

当app收到内存警告的时候会发消息给视图控制器。
app从来不会直接调用这个方法,而是当系统确定可用内存不足的时候采取调用。
如果你想覆写这个方法来释放一些控制器使用的额外内存,你应该在你的实现方法中调用父类的实现方法。

参考文章
https://blog.csdn.net/wangyanchang21/article/details/50730902
https://developer.apple.com/documentation/uikit/uiviewcontroller/1621409-didreceivememorywarning?language=objc


View的layoutSubviews

  1. init初始化不会触发layoutSubviews
  2. addSubview会触发layoutSubviews
  3. 改变一个UIViewframe会触发layoutSubviews,当然前提是frame的值设置前后发生了变化。
  4. 滚动一个UIScrollView引发UIView的重新布局会触发layoutSubviews
  5. 旋转Screen会触发父UIView上的layoutSubviews事件。
  6. 直接调用setNeedsLayout 或者 layoutIfNeeded

Runloop相关

在非主页面加载时

* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1* frame #0: 0x0000000100529264 GSWatermarkView`-[GSWaterMarkView layoutSubviews](self=0x000000011d801410, _cmd="layoutSubviews") at GSWaterMarkView.m:110frame #1: 0x00000001a77db5b0 UIKitCore`-[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 2156frame #2: 0x00000001a2fe7af0 libobjc.A.dylib`-[NSObject performSelector:withObject:] + 68frame #3: 0x00000001a9d81c0c QuartzCore`-[CALayer layoutSublayers] + 292frame #4: 0x00000001a9d81f14 QuartzCore`CA::Layer::layout_if_needed(CA::Transaction*) + 484frame #5: 0x00000001a9d953fc QuartzCore`CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 140frame #6: 0x00000001a9cda184 QuartzCore`CA::Context::commit_transaction(CA::Transaction*, double) + 296frame #7: 0x00000001a9d05228 QuartzCore`CA::Transaction::commit() + 684frame #8: 0x00000001a7362d6c UIKitCore`_afterCACommitHandler + 144frame #9: 0x00000001a324bf5c CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 36frame #10: 0x00000001a3246bfc CoreFoundation`__CFRunLoopDoObservers + 420frame #11: 0x00000001a32471ac CoreFoundation`__CFRunLoopRun + 1292frame #12: 0x00000001a3246978 CoreFoundation`CFRunLoopRunSpecific + 480frame #13: 0x00000001ad376534 GraphicsServices`GSEventRunModal + 108frame #14: 0x00000001a7338f0c UIKitCore`UIApplicationMain + 1940frame #15: 0x000000010052814c GSWatermarkView`main(argc=1, argv=0x000000016f8df940) at main.m:14frame #16: 0x00000001a30c6f04 libdyld.dylib`start + 4

在初始界面加载时

* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1* frame #0: 0x0000000100b05264 GSWatermarkView`-[GSWaterMarkView layoutSubviews](self=0x000000010130f210, _cmd="layoutSubviews") at GSWaterMarkView.m:110frame #1: 0x00000001a77db5b0 UIKitCore`-[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 2156frame #2: 0x00000001a2fe7af0 libobjc.A.dylib`-[NSObject performSelector:withObject:] + 68frame #3: 0x00000001a9d81c0c QuartzCore`-[CALayer layoutSublayers] + 292frame #4: 0x00000001a9d81f14 QuartzCore`CA::Layer::layout_if_needed(CA::Transaction*) + 484frame #5: 0x00000001a9d953fc QuartzCore`CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 140frame #6: 0x00000001a9cda184 QuartzCore`CA::Context::commit_transaction(CA::Transaction*, double) + 296frame #7: 0x00000001a9d05228 QuartzCore`CA::Transaction::commit() + 684frame #8: 0x00000001a7350d20 UIKitCore`__34-[UIApplication _firstCommitBlock]_block_invoke_2 + 84frame #9: 0x00000001a324c95c CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 28frame #10: 0x00000001a324c0e0 CoreFoundation`__CFRunLoopDoBlocks + 268frame #11: 0x00000001a32470e0 CoreFoundation`__CFRunLoopRun + 1088frame #12: 0x00000001a3246978 CoreFoundation`CFRunLoopRunSpecific + 480frame #13: 0x00000001ad376534 GraphicsServices`GSEventRunModal + 108frame #14: 0x00000001a7338f0c UIKitCore`UIApplicationMain + 1940frame #15: 0x0000000100b0414c GSWatermarkView`main(argc=1, argv=0x000000016f303940) at main.m:14frame #16: 0x00000001a30c6f04 libdyld.dylib`start + 4

可以看出在app启动时,初始界面View的layoutSubviews__CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__触发,后续的界面由__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__触发


view的drawRect:方法

  1. 直接调用setNeedsDisplay,或者setNeedsDisplayInRect:触发drawRect:,但是有个前提条件是rect大小不能为0。
  2. drawRect的调用时机是在viewWillAppearviewDidAppear之间。且在ViewlayoutSubviews之后
2020-03-03 14:05:58.384185+0800 GSWatermarkView[1318:1216023]  ViewController [-[ViewController loadView]]
2020-03-03 14:05:58.384252+0800 GSWatermarkView[1318:1216023]  ViewController [-[ViewController viewDidLoad]]
2020-03-03 14:05:58.385593+0800 GSWatermarkView[1318:1216023]  GSWaterMarkView [-[GSWaterMarkView didMoveToSuperview]]
2020-03-03 14:05:58.385686+0800 GSWatermarkView[1318:1216023]  ViewController [-[ViewController viewWillAppear:]]
2020-03-03 14:05:58.387915+0800 GSWatermarkView[1318:1216023]  ViewController [-[ViewController viewWillLayoutSubviews]]
2020-03-03 14:05:58.387956+0800 GSWatermarkView[1318:1216023]  ViewController [-[ViewController viewDidLayoutSubviews]]
2020-03-03 14:05:58.387975+0800 GSWatermarkView[1318:1216023]  GSWaterMarkView [-[GSWaterMarkView layoutSubviews]]
2020-03-03 14:05:58.388046+0800 GSWatermarkView[1318:1216023]  GSWaterMarkView [-[GSWaterMarkView drawRect:]]
2020-03-03 14:05:58.427785+0800 GSWatermarkView[1318:1216023]  ViewController [-[ViewController viewDidAppear:]]
  1. 调用sizeToFit,会触发drawRect的调用。
  2. 通过设置contentMode属性值为UIViewContentModeRedraw。那么将在每次设置或更改frame的时候自动调用drawRect:

app启动时,添加到初始界面的堆栈,还是CALayer触发

* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1* frame #0: 0x00000001042e531c GSWatermarkView`-[GSWaterMarkView drawRect:](self=0x0000000104910450, _cmd="drawRect:", rect=(origin = (x = 0, y = -0.125), size = (width = 374, height = 210.5))) at GSWaterMarkView.m:115frame #1: 0x00000001a77da8c0 UIKitCore`-[UIView(CALayerDelegate) drawLayer:inContext:] + 608frame #2: 0x00000001a9d83d78 QuartzCore`-[CALayer drawInContext:] + 312frame #3: 0x00000001a9c4f9e8 QuartzCore`CABackingStoreUpdate_ + 180frame #4: 0x00000001a9d84ce0 QuartzCore`___ZN2CA5Layer8display_Ev_block_invoke + 56frame #5: 0x00000001a9cd6f64 QuartzCore`x_blame_allocations + 148frame #6: 0x00000001a9d847b0 QuartzCore`-[CALayer _display] + 1652frame #7: 0x00000001a9d9551c QuartzCore`CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 428frame #8: 0x00000001a9cda184 QuartzCore`CA::Context::commit_transaction(CA::Transaction*, double) + 296frame #9: 0x00000001a9d05228 QuartzCore`CA::Transaction::commit() + 684frame #10: 0x00000001a7350d20 UIKitCore`__34-[UIApplication _firstCommitBlock]_block_invoke_2 + 84frame #11: 0x00000001a324c95c CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 28frame #12: 0x00000001a324c0e0 CoreFoundation`__CFRunLoopDoBlocks + 268frame #13: 0x00000001a32470e0 CoreFoundation`__CFRunLoopRun + 1088frame #14: 0x00000001a3246978 CoreFoundation`CFRunLoopRunSpecific + 480frame #15: 0x00000001ad376534 GraphicsServices`GSEventRunModal + 108frame #16: 0x00000001a7338f0c UIKitCore`UIApplicationMain + 1940frame #17: 0x00000001042e414c GSWatermarkView`main(argc=1, argv=0x000000016bb23940) at main.m:14frame #18: 0x00000001a30c6f04 libdyld.dylib`start + 4

参考文章
https://segmentfault.com/a/1190000018645601
https://www.jianshu.com/p/4edfd23ca49a

这篇关于iOS开发-ViewController的生命周期相关的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/433877

相关文章

Linux使用fdisk进行磁盘的相关操作

《Linux使用fdisk进行磁盘的相关操作》fdisk命令是Linux中用于管理磁盘分区的强大文本实用程序,这篇文章主要为大家详细介绍了如何使用fdisk进行磁盘的相关操作,需要的可以了解下... 目录简介基本语法示例用法列出所有分区查看指定磁盘的区分管理指定的磁盘进入交互式模式创建一个新的分区删除一个存

基于Python开发电脑定时关机工具

《基于Python开发电脑定时关机工具》这篇文章主要为大家详细介绍了如何基于Python开发一个电脑定时关机工具,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 简介2. 运行效果3. 相关源码1. 简介这个程序就像一个“忠实的管家”,帮你按时关掉电脑,而且全程不需要你多做

关于Maven生命周期相关命令演示

《关于Maven生命周期相关命令演示》Maven的生命周期分为Clean、Default和Site三个主要阶段,每个阶段包含多个关键步骤,如清理、编译、测试、打包等,通过执行相应的Maven命令,可以... 目录1. Maven 生命周期概述1.1 Clean Lifecycle1.2 Default Li

numpy求解线性代数相关问题

《numpy求解线性代数相关问题》本文主要介绍了numpy求解线性代数相关问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 在numpy中有numpy.array类型和numpy.mat类型,前者是数组类型,后者是矩阵类型。数组

Java中的Opencv简介与开发环境部署方法

《Java中的Opencv简介与开发环境部署方法》OpenCV是一个开源的计算机视觉和图像处理库,提供了丰富的图像处理算法和工具,它支持多种图像处理和计算机视觉算法,可以用于物体识别与跟踪、图像分割与... 目录1.Opencv简介Opencv的应用2.Java使用OpenCV进行图像操作opencv安装j

基于Qt开发一个简单的OFD阅读器

《基于Qt开发一个简单的OFD阅读器》这篇文章主要为大家详细介绍了如何使用Qt框架开发一个功能强大且性能优异的OFD阅读器,文中的示例代码讲解详细,有需要的小伙伴可以参考一下... 目录摘要引言一、OFD文件格式解析二、文档结构解析三、页面渲染四、用户交互五、性能优化六、示例代码七、未来发展方向八、结论摘要

Redis的Hash类型及相关命令小结

《Redis的Hash类型及相关命令小结》edisHash是一种数据结构,用于存储字段和值的映射关系,本文就来介绍一下Redis的Hash类型及相关命令小结,具有一定的参考价值,感兴趣的可以了解一下... 目录HSETHGETHEXISTSHDELHKEYSHVALSHGETALLHMGETHLENHSET

在 VSCode 中配置 C++ 开发环境的详细教程

《在VSCode中配置C++开发环境的详细教程》本文详细介绍了如何在VisualStudioCode(VSCode)中配置C++开发环境,包括安装必要的工具、配置编译器、设置调试环境等步骤,通... 目录如何在 VSCode 中配置 C++ 开发环境:详细教程1. 什么是 VSCode?2. 安装 VSCo

python中的与时间相关的模块应用场景分析

《python中的与时间相关的模块应用场景分析》本文介绍了Python中与时间相关的几个重要模块:`time`、`datetime`、`calendar`、`timeit`、`pytz`和`dateu... 目录1. time 模块2. datetime 模块3. calendar 模块4. timeit

C#图表开发之Chart详解

《C#图表开发之Chart详解》C#中的Chart控件用于开发图表功能,具有Series和ChartArea两个重要属性,Series属性是SeriesCollection类型,包含多个Series对... 目录OverviChina编程ewSeries类总结OverviewC#中,开发图表功能的控件是Char