UIView
一、UIView.h 目录
iOS
$1 /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.1.sdk/System/Library/Frameworks/UIKit.framework/Headers/UIView.h
$2 /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator6.1.sdk/System/Library/Frameworks/UIKit.framework/Headers/UIView.h
一、UIView 总结
1、布局
2、布局约束
3、视图树,视图内容模型,状态
4、动画
UIView剖析
UIView中文介绍总结
官方UIView介绍
二、UIView结构
分析结构,有利于对整体视图层次优化,调试,<<参考地址>>
- (void)dumpView:(UIView *)aView atIndent:(int)indent into:(NSMutableString *)outstring { for (int i = 0; i < indent; i++) { [outstring appendString:@"--"]; } [outstring appendFormat:@"[%2d] %@\n", indent, [[aView class] description]]; for (UIView *view in [aView subviews]) { [self dumpView:view atIndent:indent + 1 into:outstring]; } } - (NSString *) displayViews: (UIView *) aView { NSMutableString *outstring = [[NSMutableString alloc] init]; [self dumpView: self.window atIndent:0 into:outstring]; return [outstring autorelease]; } - (void)logViewTreeForMainWindow { NSLog(@"The view tree:\n%@", [self displayViews:self.window]); } [self logViewTreeForMainWindow];
[ 0] UIWindow
--[ 1] UIView
----[ 2] UIImageView
----[ 2] UILabel
----[ 2] UIButton
------[ 3] UIImageView
----[ 2] UIButton
------[ 3] UIImageView
----[ 2] UIButton
------[ 3] UIImageView
----[ 2] UIButton
------[ 3] UIImageView
----[ 2] UIButton
------[ 3] UIImageView
----[ 2] UIButton
------[ 3] UIImageView
----[ 2] UIButton
------[ 3] UIImageView
----[ 2] UIButton
------[ 3] UIImageView
一. UIView基本概念
UIView是组成画面的基本元素。拥有位置属性及一定尺寸的四方形,背景色。可以包含字符串或者图片等内容(信息)。例如UILabel就是包含字符串的UIView,而UIImageView是包含图片的UIView。最重要的一点是UIView可以拥有UIView类型的子元素。可以轻易地在UIView上追加UIView,创建各种各样的画面。在iPhone应用程序中,应用程序的UIWindow也是UIView的子类。也就是说,所有的画面都是在UIWindow中追加各种UIView而组成的。
二、坐标大小
1、bounds是指这个view在它自己坐标系的坐标和大小,绝对坐标,以屏幕为原点的坐标系,以用来帮助它的subview来定位的 ,layoutSubviews。
2、frame指的是这个view在它superview的坐标系的坐标和大小,相对坐标
三、功能介绍
1、创建一个视图对象
2、动画
3、管理视图层次结构
4、子视图的布局(layout)
5、绘制/重绘视图
6、以块展现动画的方式
7、视图和坐标系统之间转换
8、跟踪视图相关的变化
1、UIView 和CALayer1、UIView绘图部分来源于CALayer,UIView类似一个CALayer管理器,【访问<<绘图:坐标>>有关的属性(frame,bounds):访问CALayer相关属性】。
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator6.1.sdk/System/Library/Frameworks/QuartzCore.framework/Headers/CALayer.h
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk/System/Library/Frameworks/QuartzCore.framework/Versions/A/Headers/CALayer.h
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk/System/Library/Frameworks/QuartzCore.framework/Versions/A/Headers/CALayer.h
2.【layer属性:return CALayer实例】<>【【layerClass方法:返回主layer所使用的类】:【UIView的子类重载 :不同CALayer显示】。
3.UIView的CALayer类似UIView的子View树形结构,也可以向它的layer上添加子layer,来完成某些特殊的表示。
4.UIView的layer树形在系统内部,被系统维护着三份copy。
第一份,逻辑树,就是代码里可以操纵的,例如更改layer的属性等就在这一份。
第二份,动画树,这是一个中间层,系统正在这一层上更改属性,进行各种渲染操作。
第三份,显示树,这棵树的内容是当前正被显示在屏幕上的内容。
这三棵树的逻辑结构都是一样的,区别只有各自的属性。
5.动画的运作
UIView的主layer以外,对它的subLayer,也就是子layer的属性进行更改,系统将自动进行动画生成,动画持续时间有个缺省时间,在动画时间里,系统自动判定哪些属性更改了,自动对更改的属性进行动画插值,生成中间帧然后连续显示产生动画效果。
6.坐标系系统
CALayer的坐标系系统和UIView有点不一样,它多了一个叫anchorPoint的属性,它使用CGPoint结构,但是值域是0~1,也就是按照比例来设置。这个点是各种图形变换的坐标原点,同时会更改layer的position的位置,它的缺省值是{0.5, 0.5},也就是在layer的中央。某layer.anchorPoint = CGPointMake(0.f, 0.f);如果这么设置,layer的左上角就会被挪到原来的中间的位置,加上这样一句就好了某layer.position = CGPointMake(0.f, 0.f).
一、- (id)initWithFrame:(CGRect)frame;
【1】、与座标系统有关的物件结构有以下几个:
CGPoint -- 座标上的点,包含x和y
CGSize -- 物件的大小,包含width和height
CGRect -- 结合以上两者,包含origin和size
【2】、相对应的建立函式有以下几种(参数均为浮点数):
CGPointMake(x, y)
CGSizeMake(width, height)
CGRectMake(x, y, width, height)
一、UIView 几何属性
UIView类默认提供了四个属性来管理提几何信息:
1、frame,CGRect类型,描述view在其父view坐标系中的定位和大小;
2、bounds,CGRect类型,描述view自身的本地坐标系统的定位和大小;
3、center,CGPoint类型,描述view的frame属性的中心点;
4、transform, CGAffineTransform类型,指定view相对于自身bounds本地坐标系的平移量
核心来源于CGGeometry.h
struct CGPoint { CGFloat x; CGFloat y; }; typedef struct CGPoint CGPoint; /* Sizes. */ struct CGSize { CGFloat width; CGFloat height; }; typedef struct CGSize CGSize; /* Rectangles. */ struct CGRect { CGPoint origin; CGSize size; }; typedef struct CGRect CGRect;
UIView* testView = [[UIView alloc] initWithFrame:CGRectMake(50, 50, 100, 100)];
[self.window addSubview:testView];
NSLog(@"Frame: (%.2f, %.2f, %.2f, %.2f)", testView.frame.origin.x, testView.frame.origin.y, testView.frame.size.width, testView.frame.size.height);
NSLog(@"Bounds: (%.2f, %.2f, %.2f, %.2f)", testView.bounds.origin.x, testView.bounds.origin.y, testView.bounds.size.width, testView.bounds.size.height);
NSLog(@"Center: (%.2f, %.2f)", testView.center.x, testView.center.y);
NSLog(@"Modify Bounds to (50, 50, 100, 100)");
testView.bounds = CGRectMake(50, 50, 100, 100);
NSLog(@"Frame: (%.2f, %.2f, %.2f, %.2f)", testView.frame.origin.x, testView.frame.origin.y, testView.frame.size.width, testView.frame.size.height);
NSLog(@"Bounds: (%.2f, %.2f, %.2f, %.2f)", testView.bounds.origin.x, testView.bounds.origin.y, testView.bounds.size.width, testView.bounds.size.height);
NSLog(@"Center: (%.2f, %.2f)", testView.center.x, testView.center.y);
2013-03-24 08:39:10.728 iosDemo[568:11303] Frame: (50.00, 50.00, 100.00, 100.00)
2013-03-24 08:39:10.729 iosDemo[568:11303] Bounds: (0.00, 0.00, 100.00, 100.00)
2013-03-24 08:39:10.730 iosDemo[568:11303] Center: (100.00, 100.00)
2013-03-24 08:39:10.731 iosDemo[568:11303] Modify Bounds to (50, 50, 100, 100)
2013-03-24 08:39:10.732 iosDemo[568:11303] Frame: (50.00, 50.00, 100.00, 100.00)
2013-03-24 08:39:10.732 iosDemo[568:11303] Bounds: (50.00, 50.00, 100.00, 100.00)
2013-03-24 08:39:10.733 iosDemo[568:11303] Center: (100.00, 100.00)
一、@property(nonatomic,getter=isUserInteractionEnabled) BOOL userInteractionEnabled; // default is YES. if set to NO, user events (touch, keys) are ignored and removed from the event queue. 确定是否接受用户事件
getter=isUserInteractionEnabled ,重构getter 方法, userInteractionEnabled=> isUserInteractionEnabled;
二、 - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event; // recursively calls -pointInside:withEvent:. point is in the receiver's coordinate system 接收视图触摸事件,遍历视图,确定最终接受视图层
三、- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event; // default returns YES if point is in bounds 判断触摸事件是否在当前视图
参考地址:hitTest:withEvent:方法流程 UIView的剖析!
【1】. hitTest:withEvent:调用过程
iOS系统检测到手指触摸(Touch)操作时会将其放入当前活动Application的事件队列,UIApplication会从事件队列中取出触摸事件并传递给key window(当前接收用户事件的窗口)处理,window对象首先会使用hitTest:withEvent:方法寻找此次Touch操作初始点所在的视图(View),即需要将触摸事件传递给其处理的视图,称之为hit-test view。
window对象会在首先在view hierarchy的顶级view上调用hitTest:withEvent:,此方法会在视图层级结构中的每个视图上调用pointInside:withEvent:,如果pointInside:withEvent:返回YES,则继续逐级调用,直到找到touch操作发生的位置,这个视图也就是hit-test view。
hitTest:withEvent:方法的处理流程如下:
1、首先调用当前视图的pointInside:withEvent:方法判断触摸点是否在当前视图内;
2、若返回NO,则hitTest:withEvent:返回nil;
3、若返回YES,则向当前视图的所有子视图(subviews)发送hitTest:withEvent:消息,所有子视图的遍历顺序是从top到bottom,即从subviews数组的末尾向前遍历,直到有子视图返回非空对象或者全部子视图遍历完毕;
4、若第一次有子视图返回非空对象,则hitTest:withEvent:方法返回此对象,处理结束;
5、如所有子视图都返回非,则hitTest:withEvent:方法返回自身(self)。
hitTest:withEvent:方法忽略隐藏(hidden=YES)的视图,禁止用户操作(userInteractionEnabled=YES)的视图,以及alpha级别小于0.01(alpha<0.01)的视图。如果一个子视图的区域超过父视图的bound区域(父视图的clipsToBounds 属性为NO,这样超过父视图bound区域的子视图内容也会显示),那么正常情况下对子视图在父视图之外区域的触摸操作不会被识别,因为父视图的pointInside:withEvent:方法会返回NO,这样就不会继续向下遍历子视图了。当然,也可以重写pointInside:withEvent:方法来处理这种情况。
对于每个触摸操作都会有一个UITouch对象,UITouch对象用来表示一个触摸操作,即一个手指在屏幕上按下、移动、离开的整个过程。UITouch对象在触摸操作的过程中在不断变化,所以在使用UITouch对象时,不能直接retain,而需要使用其他手段存储UITouch的内部信息。UITouch对象有一个view属性,表示此触摸操作初始发生所在的视图,即上面检测到的hit-test view,此属性在UITouch的生命周期不再改变,即使触摸操作后续移动到其他视图之上。
四、- (CGPoint)convertPoint:(CGPoint)point toView:(UIView *)view; 转化当前视图的坐标相对于另外一个视图的坐标
五、- (CGPoint)convertPoint:(CGPoint)point fromView:(UIView *)view; 转化另外视图坐标相对于当前视图的坐标
六、- (CGRect)convertRect:(CGRect)rect toView:(UIView *)view;转化当前视图的矩形坐标相对于另外一个视图的矩形
七、- (CGRect)convertRect:(CGRect)rect fromView:(UIView *)view;转化另外视图的矩形坐标相对于当前视图矩形
UIView* testOneView = [[UIView alloc] initWithFrame:CGRectMake(100.00, 100.00, 200.00, 200.00)];
CGRect viewRect = CGRectMake(50.00,50.00,50.00,50.00);
CGRect convertRectOne;
CGRect convertRectTwo;
CGPoint convertPointOne;
CGPoint convertPointTwo;
convertRectOne = [testOneView convertRect: viewRect toView:testView];
convertRectTwo = [testOneView convertRect: viewRect fromView:testView];
convertPointOne = [testOneView convertPoint: CGPointMake(10.00, 30.00) toView:testView];
convertPointTwo = [testView convertPoint: CGPointMake(-10.00, 50.00) fromView:testOneView];
1、- (CGSize)sizeThatFits:(CGSize)size; // return 'best' size to fit given size. does not actually resize view. Default is return existing view size 计算并返回一个最适应接收子视图的大小
2、- (void)sizeToFit; // calls sizeThatFits: with current view bounds and changes bounds size. 移动并调整子视图的大小
UIView *oneViewDemo = [[[UIView alloc] initWithFrame:CGRectMake(10.00, 50.00, 300.00, 300.00)] autorelease];
oneViewDemo.backgroundColor = [UIColor blueColor];
themeLabel.backgroundColor = [UIColor redColor];
themeLabel.text = @"TEST";
themeLabel.numberOfLines = 0;
labelFrame.size = [themeLabel sizeThatFits:CGSizeMake(100, 100)];
[themeLabel sizeToFit];
[themeLabel setFrame:labelFrame];
[oneViewDemo addSubview:themeLabel];
1、- (void)removeFromSuperview; 将当前视图从父视图和窗口移除,并且把它的响应事件的响应链移除。
在ios当中,视图的设计模式可以看做是组件模式,即以树作为存储的数据结构,这种数据结构具有明确的两个特点:
【1】.父子关系分明,从根节点出发,通过叶节点向下扩展,同一枝的上一个节点就是下一个节点的superview,下一个节点就是上一个节点的subview;不同枝如果同层,则为兄弟节点。
【2】.layer关系分明,layer在ios中对事件响应具有举足轻重的作用,通常两个重叠的控件,处在上层的会优先响应;
view在操作时候的核心,即一个view的操作关系到两个方面,视图结构和响应者链。
removeFromSuperview,类似一个剪枝,执行此函数,就等于在树形结构中找到该节点,剪去该节点及其子节点,而并非只是剪去该节点自己。同时,另一个操作就是把该对象从响应者链中移除。
【3】、如果当前view对象的父视图不为空,则父视图会release一次当前视图对象。如果你还想重用当前view,你应该在调用removeFromSuperview之前,retain一次当前view对象,但不要忘记,在恰当的时候要release它,以确保没有内存泄露。
【4】、永远不要在view的drawRect方法中调用removeFromSuperview;
[oneViewDemo removeFromSuperview];
2、- (void)insertSubview:(UIView *)view atIndex:(NSInteger)index; 指定索引插入视图
UIView* insertDemoOne=[[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
insertDemoOne.backgroundColor=[UIColor yellowColor];
[oneViewDemo insertSubview:insertDemoOne atIndex:2];
UIView* insertDemoTwo=[[UIView alloc] initWithFrame:CGRectMake(50, 50, 100, 100)];
insertDemoTwo.backgroundColor=[UIColor orangeColor];
[oneViewDemo insertSubview:insertDemoTwo atIndex:1];
3、- (void)exchangeSubviewAtIndex:(NSInteger)index1 withSubviewAtIndex:(NSInteger)index2; 指定索引交换子视图
[oneViewDemo exchangeSubviewAtIndex:2 withSubviewAtIndex:1];
4、- (void)addSubview:(UIView *)view; 添加视图到最后
addSubview 是添加到最后,即最后一个进栈,显示在所有子视图的最上面。
insertSubview:AtIndex:是根据索引添加到栈里面,可以根据需要添加到对应的栈的位置里面。
[oneViewDemo addSubview:themeLabel];
5、- (void)insertSubview:(UIView *)view belowSubview:(UIView *)siblingSubview; 添加视图到底层UIView *insetDemoThree = [[[UIView alloc] initWithFrame:CGRectMake(150, 150, 100, 100)] autorelease];
insetDemoThree.backgroundColor = [UIColor brownColor];
[oneViewDemo insertSubview:insetDemoThree aboveSubview:insertDemoOne];
6、- (void)insertSubview:(UIView *)view aboveSubview:(UIView *)siblingSubview; 添加视图到顶层
UIView *insetDemoFour = [[[UIView alloc] initWithFrame:CGRectMake(25, 75, 100, 100)] autorelease];
insetDemoFour.backgroundColor = [UIColor brownColor];
[oneViewDemo insertSubview:insetDemoFour aboveSubview:insertDemoTwo];
7、- (void)bringSubviewToFront:(UIView *)view; 将指定子视图推送前台(顶层)[oneViewDemo bringSubviewToFront:insetDemoFour];
8、- (void)sendSubviewToBack:(UIView *)view; 将指定子视图推送到后台[oneViewDemo sendSubviewToBack:insetDemoThree];
9、- (void)didAddSubview:(UIView *)subview; 通知视图已经添加子视图, 默认不执行任何操作,子类可以重写
10、- (void)willRemoveSubview:(UIView *)subview; 通知视图某个子视图即将移除, 默认不执行任何操作,子类可以重写
1、- (void)willMoveToSuperview:(UIView *)newSuperview; 通知即将移动到新的父视图中
2、- (void)didMoveToSuperview; 通知已经到新父视图
3、- (void)willMoveToWindow:(UIWindow *)newWindow; 通知即将已移动到新的窗口
4、- (void)didMoveToWindow; 通知已经移动新的窗口
5、- (BOOL)isDescendantOfView:(UIView *)view; // returns YES for self. 判断一个视图是否在父视图层中
6、- (UIView *)viewWithTag:(NSInteger)tag; // recursive search. includes self 获取标记的子视图
《刷新布局》
7、- (void)setNeedsLayout; 标记为需要重新布局,异步调用layoutIfNeeded刷新布局,不立即刷新,但layoutSubviews一定会被调用
8、- (void)layoutIfNeeded; 如果有需要刷新的标记,立即调用layoutSubviews进行布局(如果没有标记,不会调用layoutSubviews)
9、- (void)layoutSubviews; 重新布局
layoutSubviews在以下情况下会被调用:
1、init初始化不会触发layoutSubviews , 但 initWithFrame 进行初始化时,当rect的值不为CGRectZero时,也会触发.
2、addSubview会触发layoutSubviews.
3、设置view的Frame会触发layoutSubviews,当然前提是frame的值设置前后发生了变化.
4、滚动一个UIScrollView会触发layoutSubviews.
5、旋转Screen会触发父UIView上的layoutSubviews事件.
6、改变一个UIView大小的时候也会触发父UIView上的layoutSubviews事件.
[1]、layoutSubviews对subviews重新布局
[2]、layoutSubviews方法调用先于drawRect
[3]、setNeedsLayout在receiver标上一个需要被重新布局的标记,在系统runloop的下一个周期自动调用layoutSubviews
[4]、layoutIfNeeded方法如其名,UIKit会判断该receiver是否需要layout
[5]、layoutIfNeeded遍历的不是superview链,应该是subviews链
《重绘》
10、-drawRect:(CGRect)rect方法:重写此方法,执行重绘
11、-setNeedsDisplay方法:标记为需要重绘,异步调用drawRect
12、-setNeedsDisplayInRect:(CGRect)invalidRect方法:标记为需要局部重绘
drawRect是对receiver的重绘
setNeedDisplay在receiver标上一个需要被重新绘图的标记,在下一个draw周期自动重绘,iphone device的刷新频率是60hz,也就是1/60秒后重绘
一、@property(nonatomic) BOOL clipsToBounds; 标示子视图边界是否超过父视图范围
insertDemoOne.clipsToBounds = YES; 子视图超出父视图部分会隐藏
[insertDemoOne insertSubview:insertDemoTwo atIndex:1];
insertDemoOne.clipsToBounds = NO; 默认为NO, 子视图超出父视图部分会显示
二、@property(nonatomic,copy) UIColor *backgroundColor; 背景颜色
insertDemoTwo.backgroundColor=[UIColor orangeColor];
三、@property(nonatomic) CGFloat alpha; 透明度, 取值范围为0.0 --- 1.0
insertDemoTwo.alpha = 0.3;
四、@property(nonatomic,getter=isOpaque) BOOL opaque; 决定该消息接收者(UIView instance)是否让其视图不透明,用处在于给绘图系统提供一个性能优化开关。
insertDemoTwo.opaque = NO;
该值为YES, 那么绘图在绘制该视图的时候把整个视图当作不透明对待。优化绘图过程并提升系统性能;为了性能方面的考量,默认被置为YES。
该值为NO,,不去做优化操作。
一个不透明视图需要整个边界里面的内容都是不透明。基于这个原因,opaque设置为YES,要求对应的alpha必须为1.0。如果一个UIView实例opaque被设置为YES, 而同时它又没有完全填充它的边界(bounds),或者它包含了整个或部分的透明的内容视图,那么将会导致未知的结果。
因此,如果视图部分或全部支持透明,那么你必须把opaque这个值设置为NO.
五、@property(nonatomic) BOOL clearsContextBeforeDrawing; 决定绘制前是否清屏,默认为YES
insertDemoOne.clearsContextBeforeDrawing = YES;
提高描画性能(特别是在滚动过程)的另一个方法是将视图的clearsContextBeforeDrawing属性设置为NO。当这个属性被设置为YES时,UIKIt会在调用drawRect:方法之前,把即将被该方法更新的区域填充为透明的黑色。将这个属性设置为NO可以取消相应的填充操作,而由应用程序负责完全重画传给drawRect:方法的更新矩形中的部。这样的优化在滚动过程中通常是一个好的折衷。
insertDemoTwo.hidden = YES;
七、@property(nonatomic) UIViewContentMode contentMode; 视图边界填充
insertDemoTwo. contentMode = UIViewContentModeScaleAspectFill;
typedef NS_ENUM(NSInteger, UIViewContentMode) {
UIViewContentModeScaleToFill, 缩放内容到合适比例大小
UIViewContentModeScaleAspectFit, // contents scaled to fit with fixed aspect. remainder is transparent 缩放内容到合适的大小,边界多余部分透明
UIViewContentModeScaleAspectFill, // contents scaled to fill with fixed aspect. some portion of content may be clipped.缩放内容填充到指定大小,边界多余的部分省略
UIViewContentModeRedraw, // redraw on bounds change (calls -setNeedsDisplay) 重绘视图边界
UIViewContentModeCenter, // contents remain same size. positioned adjusted. 视图保持等比缩放
UIViewContentModeTop, 视图顶部对齐
UIViewContentModeBottom, 视图底部对齐
UIViewContentModeLeft, 视图左侧对齐
UIViewContentModeRight, 视图右侧对齐
UIViewContentModeTopLeft, 视图左上角对齐
UIViewContentModeTopRight, 视图右上角对齐
UIViewContentModeBottomLeft, 视图左下角对齐
UIViewContentModeBottomRight, 视图右下角对齐
};
八、@property(nonatomic) CGRect contentStretch NS_DEPRECATED_IOS(3_0,6_0); 视图拉伸和缩略
imageDemo.image = [UIImage imageNamed:@"demo.png"];
[imageDemo setContentStretch:CGRectMake(50.0/100.0, 75.0/150.0, 10.0/100.0, 10.0/150.0)];
当demo.png大于imageDemo的大小时,就缩小。
当demo.png小于imageDemo的大小时,就放大。
二、UIView.h 分析
// // UIView.h // UIKit // // Copyright (c) 2005-2012, Apple Inc. All rights reserved. // #import <Foundation/Foundation.h> 基础框架入口 #import <UIKit/UIResponder.h>触摸事件响应处理 #import <UIKit/UIInterface.h> 界面UIcolor, UIFont 定义 #import <UIKit/UIKitDefines.h> 一些宏定义 #import <UIKit/UIAppearance.h> 外观代理 #import <UIKit/NSLayoutConstraint.h> 布局对象约束 typedef NS_ENUM(NSInteger, UIViewAnimationCurve) { //动画曲线 UIViewAnimationCurveEaseInOut, // slow at beginning and end 缓慢开始,中间加速,然后减速到结束 UIViewAnimationCurveEaseIn, // slow at beginning 缓慢开始,加速到结束 UIViewAnimationCurveEaseOut, // slow at end 加速开始,加速到结束 UIViewAnimationCurveLinear //正常速度 }; typedef NS_ENUM(NSInteger, UIViewContentMode) { UIViewContentModeScaleToFill, 缩放内容到合适比例大小 UIViewContentModeScaleAspectFit, // contents scaled to fit with fixed aspect. remainder is transparent 缩放内容到合适的大小,边界多余部分透明 UIViewContentModeScaleAspectFill, // contents scaled to fill with fixed aspect. some portion of content may be clipped.缩放内容填充到指定大小,边界多余的部分省略 UIViewContentModeRedraw, // redraw on bounds change (calls -setNeedsDisplay) 重绘视图边界 UIViewContentModeCenter, // contents remain same size. positioned adjusted. 视图保持等比缩放 UIViewContentModeTop, 视图顶部对齐 UIViewContentModeBottom, 视图底部对齐 UIViewContentModeLeft, 视图左侧对齐 UIViewContentModeRight, 视图右侧对齐 UIViewContentModeTopLeft, 视图左上角对齐 UIViewContentModeTopRight, 视图右上角对齐 UIViewContentModeBottomLeft, 视图左下角对齐 UIViewContentModeBottomRight, 视图右下角对齐 }; typedef NS_ENUM(NSInteger, UIViewAnimationTransition) { UIViewAnimationTransitionNone, 没有过渡 UIViewAnimationTransitionFlipFromLeft, 翻转视图从左到右 UIViewAnimationTransitionFlipFromRight, 翻转视图从右到左 UIViewAnimationTransitionCurlUp, 从上卷动 UIViewAnimationTransitionCurlDown, 从下卷动 }; typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) { UIViewAutoresizingNone = 0, 父视图变化,自己不变化 UIViewAutoresizingFlexibleLeftMargin = 1 << 0, 视图的左边界和父视图的宽度等比例变化 UIViewAutoresizingFlexibleWidth = 1 << 1,视图的宽度和父视图的宽度成比例变化 UIViewAutoresizingFlexibleRightMargin = 1 << 2, 视图的右边界和父视图的宽度等比例变化 UIViewAutoresizingFlexibleTopMargin = 1 << 3, 视图的上边界和父视图的高度成等比例变化 UIViewAutoresizingFlexibleHeight = 1 << 4, 视图的高度和父视图的高度成比例变化 UIViewAutoresizingFlexibleBottomMargin = 1 << 5 视图的下边界和父视图的高度成等比例变化 }; typedef NS_OPTIONS(NSUInteger, UIViewAnimationOptions) { UIViewAnimationOptionLayoutSubviews = 1 << 0, UIViewAnimationOptionAllowUserInteraction = 1 << 1, // turn on user interaction while animating UIViewAnimationOptionBeginFromCurrentState = 1 << 2, // start all views from current value, not initial value UIViewAnimationOptionRepeat = 1 << 3, // repeat animation indefinitely UIViewAnimationOptionAutoreverse = 1 << 4, // if repeat, run animation back and forth UIViewAnimationOptionOverrideInheritedDuration = 1 << 5, // ignore nested duration UIViewAnimationOptionOverrideInheritedCurve = 1 << 6, // ignore nested curve UIViewAnimationOptionAllowAnimatedContent = 1 << 7, // animate contents (applies to transitions only) UIViewAnimationOptionShowHideTransitionViews = 1 << 8, // flip to/from hidden state instead of adding/removing UIViewAnimationOptionCurveEaseInOut = 0 << 16, // default UIViewAnimationOptionCurveEaseIn = 1 << 16, UIViewAnimationOptionCurveEaseOut = 2 << 16, UIViewAnimationOptionCurveLinear = 3 << 16, UIViewAnimationOptionTransitionNone = 0 << 20, // default UIViewAnimationOptionTransitionFlipFromLeft = 1 << 20, UIViewAnimationOptionTransitionFlipFromRight = 2 << 20, UIViewAnimationOptionTransitionCurlUp = 3 << 20, UIViewAnimationOptionTransitionCurlDown = 4 << 20, UIViewAnimationOptionTransitionCrossDissolve = 5 << 20, UIViewAnimationOptionTransitionFlipFromTop = 6 << 20, UIViewAnimationOptionTransitionFlipFromBottom = 7 << 20, } NS_ENUM_AVAILABLE_IOS(4_0); @class UIEvent, UIWindow, UIViewController, UIColor, UIGestureRecognizer, CALayer; NS_CLASS_AVAILABLE_IOS(2_0) @interface UIView : UIResponder<NSCoding, UIAppearance, UIAppearanceContainer> { @package CALayer *_layer; id _tapInfo; id _gestureInfo; NSMutableArray *_gestureRecognizers; NSArray *_subviewCache; float _charge; NSInteger _tag; UIViewController *_viewDelegate; NSString *_backgroundColorSystemColorName; struct { unsigned int userInteractionDisabled:1; unsigned int implementsDrawRect:1; unsigned int implementsDidScroll:1; unsigned int implementsMouseTracking:1; unsigned int hasBackgroundColor:1; unsigned int isOpaque:1; unsigned int becomeFirstResponderWhenCapable:1; unsigned int interceptMouseEvent:1; unsigned int deallocating:1; unsigned int debugFlash:1; unsigned int debugSkippedSetNeedsDisplay:1; unsigned int debugScheduledDisplayIsRequired:1; unsigned int isInAWindow:1; unsigned int isAncestorOfFirstResponder:1; unsigned int dontAutoresizeSubviews:1; unsigned int autoresizeMask:6; unsigned int patternBackground:1; unsigned int fixedBackgroundPattern:1; unsigned int dontAnimate:1; unsigned int superLayerIsView:1; unsigned int layerKitPatternDrawing:1; unsigned int multipleTouchEnabled:1; unsigned int exclusiveTouch:1; unsigned int hasViewController:1; unsigned int needsDidAppearOrDisappear:1; unsigned int gesturesEnabled:1; unsigned int deliversTouchesForGesturesToSuperview:1; unsigned int chargeEnabled:1; unsigned int skipsSubviewEnumeration:1; unsigned int needsDisplayOnBoundsChange:1; unsigned int hasTiledLayer:1; unsigned int hasLargeContent:1; unsigned int unused:1; unsigned int traversalMark:1; unsigned int appearanceIsInvalid:1; unsigned int monitorsSubtree:1; unsigned int layoutEngineIsOverridden:1; unsigned int constraintsAreClean:1; unsigned int subviewLayoutConstraintsAreClean:1; unsigned int potentiallyHasDanglyConstraints:1; unsigned int doesNotTranslateAutoresizingMaskIntoConstraints:1; unsigned int autolayoutIsClean:1; unsigned int subviewsAutolayoutIsClean:1; unsigned int layoutFlushingDisabled:1; unsigned int layingOutFromConstraints:1; unsigned int wantsAutolayout:1; unsigned int subviewWantsAutolayout:1; unsigned int isApplyingValuesFromEngine:1; unsigned int isInAutolayout:1; unsigned int isUpdatingAutoresizingConstraints:1; unsigned int isUpdatingConstraints:1; unsigned int stayHiddenAwaitingReuse:1; unsigned int stayHiddenAfterReuse:1; unsigned int skippedLayoutWhileHiddenForReuse:1; } _viewFlags; } + (Class)layerClass; // default is [CALayer class]. Used when creating the underlying layer for the view. 绘图布局 - (id)initWithFrame:(CGRect)frame; // default initializer 初始化视图布局 @property(nonatomic,getter=isUserInteractionEnabled) BOOL userInteractionEnabled; // default is YES. if set to NO, user events (touch, keys) are ignored and removed from the event queue.确定是否接受用户事件 @property(nonatomic) NSInteger tag; // default is 0 标记视图对象 @property(nonatomic,readonly,retain) CALayer *layer; // returns view's layer. Will always return a non-nil value. view is layer's delegate 返回一个只读的视图层 @end @interface UIView(UIViewGeometry) // animatable. do not use frame if view is transformed since it will not correctly reflect the actual location of the view. use bounds + center instead. @property(nonatomic) CGRect frame; 描述view在其父view坐标系中的定位和大小 // use bounds/center and not frame if non-identity transform. if bounds dimension is odd, center may be have fractional part @property(nonatomic) CGRect bounds; // default bounds is zero origin, frame size. animatable 描述view自身的本地坐标系统的定位和大小 @property(nonatomic) CGPoint center; // center is center of frame. animatable 描述view的frame属性的中心点 @property(nonatomic) CGAffineTransform transform; // default is CGAffineTransformIdentity. animatable 描述view相对bounds的平移量 @property(nonatomic) CGFloat contentScaleFactor NS_AVAILABLE_IOS(4_0); 改变视图比例,主要用于修改分辨率,来支持高,低分辨率转化绘图 @property(nonatomic,getter=isMultipleTouchEnabled) BOOL multipleTouchEnabled; // default is NO 设置是否接受多点触摸。YES 是接受多点,NO 接受单点。 @property(nonatomic,getter=isExclusiveTouch) BOOL exclusiveTouch; // default is NO 当前视图独占触摸事件 - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event; // recursively calls -pointInside:withEvent:. point is in the receiver's coordinate system 接收视图触摸事件,遍历视图,确定最终接受视图层 - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event; // default returns YES if point is in bounds 判断触摸事件是否在当前视图 - (CGPoint)convertPoint:(CGPoint)point toView:(UIView *)view; 转化当前视图的坐标相对于另外一个视图的坐标 - (CGPoint)convertPoint:(CGPoint)point fromView:(UIView *)view; 转化另外视图坐标相对于当前视图的坐标 - (CGRect)convertRect:(CGRect)rect toView:(UIView *)view; 转化当前视图的矩形坐标相对于另外一个视图的矩形 - (CGRect)convertRect:(CGRect)rect fromView:(UIView *)view;转化另外视图的矩形坐标相对于当前视图矩形 @property(nonatomic) BOOL autoresizesSubviews; // default is YES. if set, subviews are adjusted according to their autoresizingMask if self.bounds changes 判断是否接收边界的改变,YES:接收 NO:不接收 @property(nonatomic) UIViewAutoresizing autoresizingMask; // simple resize. default is UIViewAutoresizingNone 视图边界大小调整参数 - (CGSize)sizeThatFits:(CGSize)size; // return 'best' size to fit given size. does not actually resize view. Default is return existing view size 计算并返回一个最适应接收子视图的大小 - (void)sizeToFit; // calls sizeThatFits: with current view bounds and changes bounds size. 移动并调整子视图的大小 @end @interface UIView(UIViewHierarchy) @property(nonatomic,readonly) UIView *superview; 父视图 @property(nonatomic,readonly,copy) NSArray *subviews; 子视图 @property(nonatomic,readonly) UIWindow *window; 窗口 - (void)removeFromSuperview; 将当前视图从父视图和窗口移除,并且把它的响应事件的响应链移除。 - (void)insertSubview:(UIView *)view atIndex:(NSInteger)index; 指定索引插入视图 - (void)exchangeSubviewAtIndex:(NSInteger)index1 withSubviewAtIndex:(NSInteger)index2; 指定索引交换子视图 视图的添加都是以栈的方式,即后进先出。 - (void)addSubview:(UIView *)view; 添加视图到最后- (void)insertSubview:(UIView *)view belowSubview:(UIView *)siblingSubview;添加视图到底层 - (void)insertSubview:(UIView *)view aboveSubview:(UIView *)siblingSubview; 添加视图到顶层 - (void)bringSubviewToFront:(UIView *)view; 将指定子视图推送到前台(顶层) - (void)sendSubviewToBack:(UIView *)view; 将指定子视图推送到后台 - (void)didAddSubview:(UIView *)subview;通知某个子视图已经添加 - (void)willRemoveSubview:(UIView *)subview;通知视图某个子视图即将移除 - (void)willMoveToSuperview:(UIView *)newSuperview; 通知即将移动到新的父视图中 - (void)didMoveToSuperview;通知已经到新父视图 - (void)willMoveToWindow:(UIWindow *)newWindow; 通知即将已移动到新的窗口 - (void)didMoveToWindow; 通知已经移动新的窗口 - (BOOL)isDescendantOfView:(UIView *)view; // returns YES for self. 判断一个视图是否在父视图层中 - (UIView *)viewWithTag:(NSInteger)tag; // recursive search. includes self 获取标记的子视图 // Allows you to perform layout before the drawing cycle happens. -layoutIfNeeded forces layout early - (void)setNeedsLayout; 标记为需要重新布局,异步调用layoutIfNeeded刷新布局,不立即刷新,但layoutSubviews一定会被调用 - (void)layoutIfNeeded;如果,有需要刷新的标记,立即调用layoutSubviews进行布局(如果没有标记,不会调用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. 重新布局 @end @interface UIView(UIViewRendering) - (void)drawRect:(CGRect)rect; 子类重写方法,重绘 - (void)setNeedsDisplay; 标记为需要重绘,异步调用drawRect - (void)setNeedsDisplayInRect:(CGRect)rect; 标记为需要局部重绘 @property(nonatomic) BOOL clipsToBounds; // When YES, content and subviews are clipped to the bounds of the view. Default is NO. 决定子视图边界是否可以超过父视图范围 @property(nonatomic,copy) UIColor *backgroundColor; // default is nil 背景颜色 @property(nonatomic) CGFloat alpha; // animatable. default is 1.0 透明度, 取值范围为0.0 --- 1.0 @property(nonatomic,getter=isOpaque) BOOL opaque; // default is YES. opaque views must fill their entire bounds or the results are undefined. the active CGContext in drawRect: will not have been cleared and may have non-zeroed pixels 决定该消息接收者(UIView instance)是否让其视图不透明,用处在于给绘图系统提供一个性能优化开关。 @property(nonatomic) BOOL clearsContextBeforeDrawing; // default is YES. ignored for opaque views. for non-opaque views causes the active CGContext in drawRect: to be pre-filled with transparent pixels 决定绘制前是否清屏,默认为YES @property(nonatomic,getter=isHidden) BOOL hidden; // default is NO. doesn't check superviews 视图是否隐藏,默认为NO(显示),YES为隐藏 @property(nonatomic) UIViewContentMode contentMode; // default is UIViewContentModeScaleToFill 视图边界填充 @property(nonatomic) CGRect contentStretch NS_DEPRECATED_IOS(3_0,6_0); // animatable. default is unit rectangle {{0,0} {1,1}}. Now deprecated: please use -[UIImage resizableImageWithCapInsets:] to achieve the same effect. 视图拉伸和缩略 @end @interface UIView(UIViewAnimation) + (void)beginAnimations:(NSString *)animationID context:(void *)context; // additional context info passed to will start/did stop selectors. begin/commit can be nested 开始一个动画 + (void)commitAnimations; // starts up any animations when the top level animation is commited 结束一个动画,类似数据库的事务处理 // no getters. if called outside animation block, these setters have no effect. + (void)setAnimationDelegate:(id)delegate; // default = nil 设置动画委托 + (void)setAnimationWillStartSelector:(SEL)selector; // default = NULL. -animationWillStart:(NSString *)animationID context:(void *)context //当动画执行开始时,执行selector方法 + (void)setAnimationDidStopSelector:(SEL)selector; // default = NULL. -animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context //当动画执行结束时,执行selector方法 + (void)setAnimationDuration:(NSTimeInterval)duration; // default = 0.2 //设置动画时间, 时间参数为double类型 + (void)setAnimationDelay:(NSTimeInterval)delay; // default = 0.0 //设置动画延迟时间,单位秒 + (void)setAnimationStartDate:(NSDate *)startDate; // default = now ([NSDate date]) 设置在动画块内部动画属性改变的开始时间 + (void)setAnimationCurve:(UIViewAnimationCurve)curve; // default = UIViewAnimationCurveEaseInOut 设置动画的旋转曲度变化 + (void)setAnimationRepeatCount:(float)repeatCount; // default = 0.0. May be fractional 设置动画在动画模块中的重复次数 + (void)setAnimationRepeatAutoreverses:(BOOL)repeatAutoreverses; // default = NO. used if repeat count is non-zero 设置动画块中的动画效果是否自动重复播放 + (void)setAnimationBeginsFromCurrentState:(BOOL)fromCurrentState; // default = NO. If YES, the current view position is always used for new animations -- allowing animations to "pile up" on each other. Otherwise, the last end state is used for the animation (the default). 设置动画是否从当前状态开始播放。 + (void)setAnimationTransition:(UIViewAnimationTransition)transition forView:(UIView *)view cache:(BOOL)cache; // current limitation - only one per begin/commit block //在动画块设置过渡效果 + (void)setAnimationsEnabled:(BOOL)enabled; // ignore any attribute changes while set. 设置是否开启动画,默认YES,开启 + (BOOL)areAnimationsEnabled; 验证动画是否开启,YES:开启 NO:关闭 @end @interface UIView(UIViewAnimationWithBlocks) + (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion NS_AVAILABLE_IOS(4_0); 动画效果处理块 + (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion NS_AVAILABLE_IOS(4_0); // delay = 0.0, options = 0 动画效果处理块,无延迟 + (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations NS_AVAILABLE_IOS(4_0); // delay = 0.0, options = 0, completion = NULL 动画效果处理块。无延迟,简单版 + (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion NS_AVAILABLE_IOS(4_0); 过渡动画处理块 + (void)transitionFromView:(UIView *)fromView toView:(UIView *)toView duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options completion:(void (^)(BOOL finished))completion NS_AVAILABLE_IOS(4_0); // toView added to fromView.superview, fromView removed from its superview 视图之间切换过渡动画处理块 @end @interface UIView (UIViewGestureRecognizers) @property(nonatomic,copy) NSArray *gestureRecognizers NS_AVAILABLE_IOS(3_2); 手势识别器 - (void)addGestureRecognizer:(UIGestureRecognizer*)gestureRecognizer NS_AVAILABLE_IOS(3_2);绑定手势到视图 - (void)removeGestureRecognizer:(UIGestureRecognizer*)gestureRecognizer NS_AVAILABLE_IOS(3_2);从视图中分离手势 // called when the recognizer attempts to transition out of UIGestureRecognizerStatePossible if a touch hit-tested to this view will be cancelled as a result of gesture recognition // returns YES by default. return NO to cause the gesture recognizer to transition to UIGestureRecognizerStateFailed // subclasses may override to prevent recognition of particular gestures. for example, UISlider prevents swipes parallel to the slider that start in the thumb - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer NS_AVAILABLE_IOS(6_0); 手势识别处理方式 @end // // UIView Constraint-based Layout Support // typedef NS_ENUM(NSInteger, UILayoutConstraintAxis) { UILayoutConstraintAxisHorizontal = 0, UILayoutConstraintAxisVertical = 1 }; // Installing Constraints /* A constraint is typically installed on the closest common ancestor of the views involved in the constraint. It is required that a constraint be installed on _a_ common ancestor of every view involved. The numbers in a constraint are interpreted in the coordinate system of the view it is installed on. A view is considered to be an ancestor of itself. */ @interface UIView (UIConstraintBasedLayoutInstallingConstraints) - (NSArray *)constraints NS_AVAILABLE_IOS(6_0);视图布局约束 - (void)addConstraint:(NSLayoutConstraint *)constraint NS_AVAILABLE_IOS(6_0);/视图布局上添加一个约束 - (void)addConstraints:(NSArray *)constraints NS_AVAILABLE_IOS(6_0);视图布局上添加多个约束 - (void)removeConstraint:(NSLayoutConstraint *)constraint NS_AVAILABLE_IOS(6_0);移除视图布局上的一个约束 - (void)removeConstraints:(NSArray *)constraints NS_AVAILABLE_IOS(6_0);移除视图布局上的多个约束 @end // Core Layout Methods /* To render a window, the following passes will occur, if necessary. update constraints layout display Please see the conceptual documentation for a discussion of these methods. */ @interface UIView (UIConstraintBasedLayoutCoreMethods) - (void)updateConstraintsIfNeeded NS_AVAILABLE_IOS(6_0); // Updates the constraints from the bottom up for the view hierarchy rooted at the receiver. UIWindow's implementation creates a layout engine if necessary first. 调用新的视图布局自动触发,更新视图布局上的约束 - (void)updateConstraints NS_AVAILABLE_IOS(6_0); // Override this to adjust your special constraints during a constraints update pass更新自定义视图布局约束 - (BOOL)needsUpdateConstraints NS_AVAILABLE_IOS(6_0);判断视图布局是否需要更新约束 - (void)setNeedsUpdateConstraints NS_AVAILABLE_IOS(6_0);设置视图布局是否需要更新约束 @end // Compatibility and Adoption @interface UIView (UIConstraintBasedCompatibility) /* by default, the autoresizing mask on a view gives rise to constraints that fully determine the view's position. Any constraints you set on the view are likely to conflict with autoresizing constraints, so you must turn off this property first. IB will turn it off for you. */ - (BOOL)translatesAutoresizingMaskIntoConstraints NS_AVAILABLE_IOS(6_0); // Default YES 标示是否自动遵循视图布局约束 - (void)setTranslatesAutoresizingMaskIntoConstraints:(BOOL)flag NS_AVAILABLE_IOS(6_0); 设置是否自动遵循视图布局约束 /* constraint-based layout engages lazily when someone tries to use it (e.g., adds a constraint to a view). If you do all of your constraint set up in -updateConstraints, you might never even receive updateConstraints if no one makes a constraint. To fix this chicken and egg problem, override this method to return YES if your view needs the window to use constraint-based layout. */ + (BOOL)requiresConstraintBasedLayout NS_AVAILABLE_IOS(6_0); 返回是遵循自定义视图布局约束 @end // Separation of Concerns @interface UIView (UIConstraintBasedLayoutLayering) /* Constraints do not actually relate the frames of the views, rather they relate the "alignment rects" of views. This is the same as the frame unless overridden by a subclass of UIView. Alignment rects are the same as the "layout rects" shown in Interface Builder 3. Typically the alignment rect of a view is what the end user would think of as the bounding rect around a control, omitting ornamentation like shadows and engraving lines. The edges of the alignment rect are what is interesting to align, not the shadows and such. */ /* These two methods should be inverses of each other. UIKit will call both as part of layout computation. They may be overridden to provide arbitrary transforms between frame and alignment rect, though the two methods must be inverses of each other. However, the default implementation uses -alignmentRectInsets, so just override that if it's applicable. It's easier to get right. A view that displayed an image with some ornament would typically override these, because the ornamental part of an image would scale up with the size of the frame. Set the NSUserDefault UIViewShowAlignmentRects to YES to see alignment rects drawn. */ - (CGRect)alignmentRectForFrame:(CGRect)frame NS_AVAILABLE_IOS(6_0);返回矩形对于指定视图框架。 - (CGRect)frameForAlignmentRect:(CGRect)alignmentRect NS_AVAILABLE_IOS(6_0);返回框架对于指定视图矩形 /* override this if the alignment rect is obtained from the frame by insetting each edge by a fixed amount. This is only called by alignmentRectForFrame: and frameForAlignmentRect:. */ - (UIEdgeInsets)alignmentRectInsets NS_AVAILABLE_IOS(6_0);返回自定义视图框架 /* When you make a constraint on the NSLayoutAttributeBaseline of a view, the system aligns with the bottom of the view returned from this method. A nil return is interpreted as the receiver, and a non-nil return must be in the receiver's subtree. UIView's implementation returns self. */ - (UIView *)viewForBaselineLayout NS_AVAILABLE_IOS(6_0);如果超出约束范围,自动生成基线限制,以满足视图需求 /* Override this method to tell the layout system that there is something it doesn't natively understand in this view, and this is how large it intrinsically is. A typical example would be a single line text field. The layout system does not understand text - it must just be told that there's something in the view, and that that something will take a certain amount of space if not clipped. In response, UIKit will set up constraints that specify (1) that the opaque content should not be compressed or clipped, (2) that the view prefers to hug tightly to its content. A user of a view may need to specify the priority of these constraints. For example, by default, a push button -strongly wants to hug its content in the vertical direction (buttons really ought to be their natural height) -weakly hugs its content horizontally (extra side padding between the title and the edge of the bezel is acceptable) -strongly resists compressing or clipping content in both directions. However, you might have a case where you'd prefer to show all the available buttons with truncated text rather than losing some of the buttons. The truncation might only happen in portrait orientation but not in landscape, for example. In that case you'd want to setContentCompressionResistancePriority:forAxis: to (say) UILayoutPriorityDefaultLow for the horizontal axis. The default 'strong' and 'weak' priorities referred to above are UILayoutPriorityDefaultHigh and UILayoutPriorityDefaultLow. Note that not all views have an intrinsicContentSize. UIView's default implementation is to return (UIViewNoIntrinsicMetric, UIViewNoIntrinsicMetric). The _intrinsic_ content size is concerned only with data that is in the view itself, not in other views. Remember that you can also set constant width or height constraints on any view, and you don't need to override instrinsicContentSize if these dimensions won't be changing with changing view content. */ UIKIT_EXTERN const CGFloat UIViewNoIntrinsicMetric NS_AVAILABLE_IOS(6_0); // -1 - (CGSize)intrinsicContentSize NS_AVAILABLE_IOS(6_0); 返回自定义视图大小 - (void)invalidateIntrinsicContentSize NS_AVAILABLE_IOS(6_0); // call this when something changes that affects the intrinsicContentSize. Otherwise UIKit won't notice that it changed. 自定义视图内容大小无效 - (UILayoutPriority)contentHuggingPriorityForAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);返回放大的视图布局的轴线 - (void)setContentHuggingPriority:(UILayoutPriority)priority forAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);设置放大的视图布局的轴线 - (UILayoutPriority)contentCompressionResistancePriorityForAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);返回缩小的视图布局的轴线 - (void)setContentCompressionResistancePriority:(UILayoutPriority)priority forAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);设置缩小的视图布局的轴线 @end // Size To Fit UIKIT_EXTERN const CGSize UILayoutFittingCompressedSize NS_AVAILABLE_IOS(6_0); UIKIT_EXTERN const CGSize UILayoutFittingExpandedSize NS_AVAILABLE_IOS(6_0); @interface UIView (UIConstraintBasedLayoutFittingSize) /* The size fitting most closely to targetSize in which the receiver's subtree can be laid out while optimally satisfying the constraints. If you want the smallest possible size, pass UILayoutFittingCompressedSize; for the largest possible size, pass UILayoutFittingExpandedSize. Also see the comment for UILayoutPriorityFittingSizeLevel. */ - (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize NS_AVAILABLE_IOS(6_0);满足约束视图布局的大小 @end // Debugging /* Everything in this section should be used in debugging only, never in shipping code. These methods may not exist in the future - no promises. */ @interface UIView (UIConstraintBasedLayoutDebugging) /* This returns a list of all the constraints that are affecting the current location of the receiver. The constraints do not necessarily involve the receiver, they may affect the frame indirectly. Pass UILayoutConstraintAxisHorizontal for the constraints affecting [self center].x and CGRectGetWidth([self bounds]), and UILayoutConstraintAxisVertical for the constraints affecting[self center].y and CGRectGetHeight([self bounds]). */ - (NSArray *)constraintsAffectingLayoutForAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);返回影响视图布局限制的轴线 /* If there aren't enough constraints in the system to uniquely determine layout, we say the layout is ambiguous. For example, if the only constraint in the system was x = y + 100, then there are lots of different possible values for x and y. This situation is not automatically detected by UIKit, due to performance considerations and details of the algorithm used for layout. The symptom of ambiguity is that views sometimes jump from place to place, or possibly are just in the wrong place. -hasAmbiguousLayout runs a check for whether there is another center and bounds the receiver could have that could also satisfy the constraints. -exerciseAmbiguousLayout does more. It randomly changes the view layout to a different valid layout. Making the UI jump back and forth can be helpful for figuring out where you're missing a constraint. */ - (BOOL)hasAmbiguousLayout NS_AVAILABLE_IOS(6_0);返回视图布局约束是否影响指定视图,主要用于调试约束布局,结合exerciseAmbiguityInLayout。 - (void)exerciseAmbiguityInLayout NS_AVAILABLE_IOS(6_0); 随机改变不同效值布局视图,主要用于调试基于约束布局的视图 @end @interface UIView (UIStateRestoration) @property (nonatomic, copy) NSString *restorationIdentifier NS_AVAILABLE_IOS(6_0);标示是否支持保存,恢复视图状态信息 - (void) encodeRestorableStateWithCoder:(NSCoder *)coder NS_AVAILABLE_IOS(6_0);保存视图状态相关信息 - (void) decodeRestorableStateWithCoder:(NSCoder *)coder NS_AVAILABLE_IOS(6_0); 恢复和保持视图状态相关信息 @end