首先两个方法都是异步执行,layoutSubviews方便数据计算,drawRect方便视图重绘。
layoutSubviews
1
今天在写程序时候遇见layoutSubviews触发时候引起的问题。特来总结一下什么时候会触发layoutSubviews:layoutSubviews在以下情况下会被调用:
1、init初始化不会触发layoutSubviews但是是用initWithFrame 进行初始化时,当rect的值不为CGRectZero时,也会触发
2、addSubview会触发layoutSubviews 但frame !={0,0,0,0}
3、设置view的Frame会触发layoutSubviews,当然前提是frame的值设置前后发生了变化view的with,height发现变化才会触发layoutSubviews,original. x ,original. y变化不会触发layoutSubviews
4、滚动一个UIScrollView会触发layoutSubviews
5、旋转Screen会触发父UIView上的layoutSubviews事件
6、改变一个UIView大小的时候也会触发父UIView上的layoutSubviews事件
http://blog.csdn.net/s133315202/article/details/47108531
2
原文
http://www.superqq.com/blog/2015/07/27/ioskai-fa-zhi-layoutsubviewsde-zuo-yong-he-diao-yong-ji-zhi/
在UIView里面有一个方法layoutSubviews,这个方法具体作用是什么呢?
- (void)layoutSubviews; // override point. called by layoutIfNeeded automatically. As of iOS 6.0, when constraints-based layout is used the base implementation applies the constraints-based layout, otherwise it does nothing.
官方文档解释
我们先来看看苹果官方文档的解释:
The default implementation of this method does nothing on iOS 5.1 and earlier. Otherwise, the default implementation uses any constraints you have set to determine the size and position of any subviews.
Subclasses can override this method as needed to perform more precise layout of their subviews. You should override this method only if the autoresizing and constraint-based behaviors of the subviews do not offer the behavior you want. You can use your implementation to set the frame rectangles of your subviews directly.
You should not call this method directly. If you want to force a layout update, call the setNeedsLayout method instead to do so prior to the next drawing update. If you want to update the layout of your views immediately, call the layoutIfNeeded method.
最后一段说,不要直接调用此方法。如果你想强制更新布局,你可以调用setNeedsLayout方法;如果你想立即数显你的views,你需要调用layoutIfNeeded方法。
layoutSubviews作用
layoutSubviews是对subviews重新布局。比如,我们想更新子视图的位置的时候,可以通过调用layoutSubviews方法,既可以实现对子视图重新布局。
layoutSubviews默认是不做任何事情的,用到的时候,需要在子类进行重写。
layoutSubviews以下情况会被调用
苹果官方文档已经强调,不能直接调用layoutSubviews对子视图进行重新布局。那么,layoutSubviews什么情况下会被调用呢?通过百度搜索,发现以下几种情况layoutSubviews会被调用。
1.直接调用setLayoutSubviews。(这个在上面苹果官方文档里有说明)
2.addSubview的时候。
3.当view的frame发生改变的时候。
4.滑动UIScrollView的时候。
5.旋转Screen会触发父UIView上的layoutSubviews事件。
6.改变一个UIView大小的时候也会触发父UIView上的layoutSubviews事件。
7.init初始化不会触发layoutSubviews。
我简单测试了一下,上面基本都会被调用。 注意:
当view的fram的值为0的时候,`addSubview`也不会调用`layoutSubviews`的。
layoutSubviews方法在对子类视图进行布局的时候非常方便。可以自己动手,深入理解layoutSubviews的调用机制。
3
原文 http://blog.csdn.net/u013243469/article/details/41513129
layoutSubviews是UIView中的属性方法,即只要继承于UIView,就可以使用这个方法,这个方法也很强大,以下是他的触发时机:
1、init初始化不会触发layoutSubviews
2、addSubview会触发layoutSubviews
3、设置view的Frame会触发layoutSubviews,当然前提是frame的值设置前后发生了变化
4、滚动一个UIScrollView会触发layoutSubviews
5、旋转Screen会触发父UIView上的layoutSubviews事件
6、改变一个UIView大小的时候也会触发父UIView上的layoutSubviews事件
在这些触发情况下,我们就可以妙用他,比如说改变数据等等,这是个很不错的方法 而且我们也可以手动调用,即
[self setNeedsLayout];
注意:调用layoutSubviews,也需要调用它的父类方法,即
[super layoutSubviews]
传说如果不调用的话会出现奇怪的问题。
4
原文
博客专区 > 董桉远的博客 > 董桉远的博客详情iOS layoutSubviews 什么时候会被调用
init 方法不会调用layoutSubviews
addSubview 会触发target view(被添加view的view)和其subview的layoutSubviews方法
setFrame 只有当设置的frame的参数的size与原来的size不同,才会触发其view的layoutSubviews方法
滑动 UIScrollView 会调用scrollview及scrollview上的view的layoutSubviews方法
**旋转设备 **只会调用VC的view的layoutSubviews方法
removeFromSuperview 只会调用superview的 layoutSubviews方法
5
http://bbs.csdn.net/topics/390992153
http://www.cnblogs.com/ioriwellings/archive/2012/12/27/2835340.html
http://qa.blog.163.com/blog/static/1901470022015101124723108
http://www.knowsky.com/883371.html
全面http://www.jianshu.com/p/d1ce00f08b7f
drawRect
1
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实时刷新屏幕
2
原文http://blog.sina.com.cn/s/blog_afb4d07f0101iamg.html
setNeedsDisplay和setNeedsLayout两个方法都是异步的,setNeedsDisplay会自动调用drawRect,而setNeedsLayout会自动调用layoutSubviews。
layoutSubviews方便数据计算,drawRect方便视图重绘。
假设我们采用的是直接调用drawRect的机制,先考虑这样一个问题 ,,现在有两个UIViewController A和B,A为当前view的viewController,如果此时在A中调用[B.view drawRect],这样B的view无论如何都会调用drawRect的方法重新绘制一遍,这样问题就出来了,有必要吗,毕竟现在显示的是A中的view!B重新绘制一遍就调用了drawRect中的方法,完全是在浪费系统资源啊,而通过setNeedsDisplay,ios就会很聪明的判断出不需要调用drawRect的方法,这样就避免了资源的重复调用! 同理,setNeedsLayout也采用了同样的机制来避免资源的重复利用!
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实时刷新屏幕