UI篇-VC的生命周期以及UIView的layoutSubviews和drawRect方法

前言

看似常用的UIView,其实有很多不经常用到的方法和应该注意的机制,我是一个喜欢打破砂锅问到底的人,可是很多问题在网上搜索不到答案,大部分的博客都是转载相同的东西,所以我自己就新建 Dome,实际测试了一些数据,得到了一些有用的东西,分享给大家,其中也用到了其它大神的理论和指点,在此感谢。


viewController的生命周期

  • 单个viewController的生命周期 initWithCoder:(NSCoder *)aDecoder:(如果使用storyboard或者xib) loadView:#加载view 会多次调用并且会使viewWillLayoutSubviews、viewDidLayoutSubviews不再执行 viewDidLoad:view加载完毕 viewWillAppear:控制器的view将要显示 viewWillLayoutSubviews:控制器的view将要布局子控件 viewDidLayoutSubviews:控制器的view布局子控件完成 viewDidAppear:控制器的view完全显示 viewWillDisappear:控制器的view即将消失的时候 viewDidDisappear:控制器的view完全消失的时候
  • 多个viewControllers跳转 当我们点击push的时候首先会加载下一个界面然后才会调用界面的消失方法 initWithCoder:(NSCoder *)aDecoder:ViewController2 (如果用xib创建的情况下) loadView:ViewController2 viewDidLoad:ViewController2 viewWillDisappear:ViewController1 将要消失 viewWillAppear:ViewController2 将要出现 viewWillLayoutSubviews ViewController2 viewDidLayoutSubviews ViewController2 viewWillLayoutSubviews:ViewController1 viewDidLayoutSubviews:ViewController1 viewDidDisappear:ViewController1 完全消失 viewDidAppear:ViewController2 完全出现
  • 小结: 整个控制器声明周期: viewDidLoad -> viewWillAppear -> viewWillLayoutSubviews -> viewDidLayoutSubviews -> viewDidAppear -> viewWillDisappear -> viewDidDisappear
  • 说明

viewWillLayoutSubviews 在 viewWillAppear 之后 viewDidAppear 之前执行,这个方法会被调用多次,如果在此创建视图,可能会创建多个,而且这个方法中执行耗时操作依然会造成跳转卡顿的问题。 一个VC 在执行viewWillDisappear 或者viewDidDisappear 方法时都是出栈之后才执行的,也就是说 已经不在 self.navigationController 的viewControllers中了,而一个 VC 执行viewWillAppear 时必定是 self.navigationController 的 topViewController即栈顶的视图。 一个很常见的问题,我们需要在VC被销毁的时候处理一些事情,可是 viewWillDisappear 不管是入栈新的视图还是出栈当前视图都会被调用,无法判断,结合我之前说的原理,我们可以利用下面这个方法判断当前VC是否是被出栈了。 - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:YES]; if ([[self.navigationController viewControllers] containsObject:self ]) { NSLog(@"TwoViewController 暂时消失"); }else { NSLog(@"TwoViewController 出栈了"); } }

**首先需要特别说明的一点是: **

在使用 VC绘制UI的时候,它不同于 UIView,UIView中 init方法调用后,UIView就已经绘制好(初始化好了)。

但是在VC中,当前UIView的是在 viewDidLoad 执行后才初始化好的,所以我们会见到这样一个Bug,在VC初始化语句后面调用 一个 VC的绘制UI的方法,你会发现根本没有效果,这就是因为,VC中跟试图的初始化是需要时间的,你在VC根试图初始化之前调用绘制UI的方法当然是不会有效果出现的。

</br>

UIView的setNeedsDisplay和setNeedsLayout方法。

首先两个方法都是异步执行的。setNeedsDisplay会调用 drawRect方法,这样可以拿到UIGraphicsGetCurrentContext,就可以画画。 setNeedsLayout会默认调用layoutSubViews,就可以处理子视图中的一些数据。

**综上两个方法都是异步执行的,layoutSubviews方便数据计算,drawRect方便视图重绘。UIView中方法的执行顺序大概是这样的:

init 方法 >>属性的set/get 方法>> layoutSubviews(当然是要达到触发条件)>>drawRect, 使用得当可以在View的调用中起到很好的效果。

layoutSubviews在以下情况下会被调用:

1、init初始化不会触发layoutSubviews。
2、addSubview会触发layoutSubviews。
3、设置view的Frame会触发layoutSubviews,当然前提是frame的值设置前后发生了变化。
4、滚动一个UIScrollView会触发layoutSubviews。
5、旋转Screen会触发父UIView上的layoutSubviews事件。
6、改变一个UIView大小的时候也会触发父UIView上的layoutSubviews事件。
7、直接调用setLayoutSubviews。

drawRect在以下情况下会被调用:

 1、如果在UIView初始化时没有设置rect大小,将直接导致drawRect不被自动调用。drawRect 掉用是在Controller->loadView, Controller->viewDidLoad 两方法之后掉用的.所以不用担心在 控制器中,这些View的drawRect就开始画了.这样可以在控制器中设置一些值给View(如果这些View draw的时候需要用到某些变量 值).
 2、该方法在调用sizeToFit后被调用,所以可以先调用sizeToFit计算出size。然后系统自动调用drawRect:方法。
 3、通过设置contentMode属性值为UIViewContentModeRedraw。那么将在每次设置或更改frame的时候自动调用drawRect:。
 4、直接调用setNeedsDisplay,或者setNeedsDisplayInRect:触发drawRect:,但是有个前提条件是rect不能为0。以上1,2推荐;而3,4不提倡

drawRect方法使用注意点:

1、 **若使用UIView绘图,只能在drawRect:方法中获取相应的contextRef并绘图。如果在其他方法中获取将获取到一个invalidate 的ref并且不能用于画图**。**drawRect:方法不能手动显示调用,必须通过调用setNeedsDisplay 或 者 setNeedsDisplayInRect,让系统自动调该方法。强行调用也不会起作用的。**
2、**若使用calayer绘图,只能在drawInContext: 中(类似鱼drawRect)绘制**,或者在delegate中的相应方法绘制。同样也是调用setNeedDisplay等间接调用以上方法
3、**若要实时画图,不能使用gestureRecognizer,只能使用touchbegan等方法来掉用setNeedsDisplay实时刷新屏幕。**

setNeedsDisplay和setNeedsLayout 详解

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏向治洪

React Native之StyleSheet样式表

概述 在React Native中,StyleSheet是实现了类似Web中CSS样式表的功能。最简单的使用如下,先定一个StyleSheet的样式表,然后在V...

19170
来自专栏前端vue

SimpleMDE - Vue-Markdown编辑器

52720
来自专栏一“技”之长

iOS中表视图(UITableView)使用详解

- (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style;  

10730
来自专栏君赏技术博客

Jekyll-Admin-Mac 开发纪要-左侧菜单栏

本文章文字大约 4500字,大概花费 10分钟阅读。本文章设计的图片比较多,流量党慎入!。

18510
来自专栏Windows Community

New UWP Community Toolkit - ImageEx

概述 UWP Community Toolkit  中有一个图片的扩展控件 - ImageEx,本篇我们结合代码详细讲解  ImageEx 的实现。 Image...

33170
来自专栏前端儿

React 基础实例教程

首先,需要核心库react.js与React的DOM操作组件react-dom.js

21420
来自专栏一“技”之长

iOS中UITextView方法解读 原

@property(nonatomic,assign) id<UITextViewDelegate> delegate;

10240
来自专栏向治洪

React Native在Android平台运行gif的解决方法

概述 目前RN在Android平台上不支持gif格式的图片,而在ios平台是支持的,期待以后的版本中系统也是可以默认支持Android的。首先说下在ios平台怎...

29560
来自专栏一个会写诗的程序员的博客

一段探索React自建内部构造的旅程

在先前的文章里我们涵盖了React基本原理和如何构建更加复杂的交互组件。此篇文章我们将会继续探索React组件的特性,特别是生命周期。

10140
来自专栏贾鹏辉的技术专栏@CrazyCodeBoy

React Native之React速学教程(中)

React Native之React速学教程(中) 本文出自《React Native学习笔记》系列文章。 React Native是基于React的,在开发R...

31980

扫码关注云+社区

领取腾讯云代金券