IOS 讲解 UIView对象(大全)

UIView到现在一共71个方法,64个属性,全在这了~按照UIView.h文件的顺序来的,介绍了各个属性和方法的作用和使用场景,算个对自己的开发经历有个交待吧,以后没事的时候看看再把其他的也写了,不过UIView这头一坑开的确实不小~

Class layerClass

只读,默认值为[CALayer class]。在为视图创建基础层时使用。


- (instancetype)initWithFrame:(CGRect)frame

方法类型:动态

参数:1.CGRect,位置及大小。

返回值:instancetype(就是UIView,以前是id类型,后来严谨了换成这个类型了)。

功能:创建一个UIView并为其确定位置及大小。使用自己布局的话可以传入CGRectZero调用该方法。


- (nullable instancetype)initWithCoder:(NSCoder *)coder

方法类型:动态

参数:NSCoder即归档对象

返回值:同initWithFrame

功能:就是根据NSCoder来创建UIView。例如使用xib进行进行界面的建立,然后链接至某个自定义的UIView对象,那么在初始化时系统就会调用这个方法进行初始化建立。因为是要根据xib的数据结构进行建立么。


BOOL userInteractionEnabled

可修改,初始值为YES,设为NO时,将忽略用户事件(触摸、按键)并将其从事件队列中删除。就是视图将不接收点击事件的响应,事件响应链将忽略该视图。


NSInteger tag

可修改,默认值为0,给视图一个标记,和viewWithTag方法配合使用。


CALayer *layer

只读,属于视图的数据层,操作该层,视图将直接发生对应的变化。视图变成圆角等功能也需要操作该层才可实现。之后会做关于CALayer的专题。


BOOL canBecomeFocused(IOS 9.0以后可使用)

只读,默认值为NO,是否可以成为焦点,焦点的概念主要作为在ipad(外接键盘)和iosTv中等有焦点操作的视图中进行切换使用。

如果视图可以聚焦,则此属性(继承并重写该属性)的值为YES;否则就为NO。

默认情况下,此属性的值为NO。如果视图能够聚焦,此属性将通知聚焦引擎。有时,即使视图返回YES,由于以下原因,视图也可能无法聚焦:

视图是隐藏的。

视图的alpha设置为0。

该视图已将userInteractionEnabled设置为false。

该视图当前不在视图层次结构中。


BOOL focused(IOS 9.0以后可使用)

只读,指示视图当前是否处于焦点状态。


NSString *focusGroupIdentifier(IOS 14.0以后可使用)

可修改,此视图所属的焦点组的标识符。如果为nil,子视图将继承其父视图的焦点组。

当焦点发生切换时会系统保存该组之前的焦点状态,所以需要用focusGroupIdentifier来区分进行保存状态。


UIFocusGroupPriority focusGroupPriority(IOS 15.0以后可使用)

可修改,切换到某个焦点组时会自动聚焦在某个项目焦点上,该项目为主要焦点项目。确定组中的主要焦点项目就通过焦点的优先级来设定,优先级越高就越会被作为主要焦点项目。


UIFocusEffect *focusEffect(IOS 15.0以后可使用)

可修改,视图焦点被选择后的光晕效果。可以对UIFocusEffect的属性来进行自定义颜色或是添加图片。


UISemanticContentAttribute semanticContentAttribute(IOS 9.0以后可使用)

可修改,设定视图的布局方式。举例说话,“我吃了”是普通布局,从左至右,修改布局后,变为“了吃我”(阿拉伯语的阅读习惯为从右至左)。原来设定UIbutton的图片和文字位置要使用修改文字和图片偏移的方式,现在可以直接使用这个属性修改布局方式将button的semanticContentAttribute属性变为
UISemanticContentAttributeForceRightToLeft就可以了~


+ (UIUserInterfaceLayoutDirection)userInterfaceLayoutDirectionForSemanticContentAttribute:(UISemanticContentAttribute)attribute

方法类型:静态

参数:1.attribute参数是一个视图的语言内容属性(semanticContentAttribute)。

返回值:返回内容布局方向。

功能:将视图的内容方向转换为布局方向(从左到右,或者从右到左)。视图可以按照这个方向进行布局。


+ (UIUserInterfaceLayoutDirection)userInterfaceLayoutDirectionForSemanticContentAttribute:(UISemanticContentAttribute)semanticContentAttribute relativeToLayoutDirection:(UIUserInterfaceLayoutDirection)layoutDirection

方法类型:静态

参数:1.attribute参数是一个视图的语言内容属性(semanticContentAttribute)。

2.layoutDirection参数是一个视图的界面布局方向。

返回值:返回内容布局方向。

功能:结合语义内容和视图方向,返回一个合适的布局方向,以供视图进行布局。说白了就是当语义方向和视图布局方向不一致时,系统给出的一个合理的布局方向。用苹果文档的例子:attribute参数为UISemanticContentAttributePlayback,layoutDirection参数为UIUserInterfaceLayoutDirectionRightToLeft,那么返回的值就是UIUserInterfaceLayoutDirectionLeftToRight。所以不用纠结,按苹果的推荐来~


UIUserInterfaceLayoutDirection
effectiveUserInterfaceLayoutDirection(IOS 10.0以后可使用)

只读,可通过继承的方式进行重写。布局方向,从左到右,还是从右到左(阿拉伯语的阅读习惯为从右至左)。设定后,比如collectionView就会进行从右至左的布局(cell下标为:5,4,3,2,1)。


CGRect frame

可修改,视图的位置及大小。


CGRect bounds

可修改,视图的大小。


CGPoint center

可修改,视图的中心点位置坐标。修改后视图中心点将在这个坐标位置上


CGAffineTransform transform

可修改,默认值为CGAffineTransformIdentity,负责处理视图的二维坐标系下的形变,平移,旋转,缩放。使用视图的该值而不使用layer属性的该值的话,可以搭配动画效果。


CATransform3D transform3D(IOS 13.0以后可使用)

可修改,默认值为CATTransferM3DidEntity,负责处理视图的三维坐标系下的形变,平移,旋转,缩放。使用视图的该值而不使用layer属性的该值的话,可以搭配动画效果。


CGFloat contentScaleFactor

可修改,用于描述屏幕的逻辑坐标系(以点为单位)和设备坐标系(以像素为单位)之间的关系。比如一张图片为320*320,屏幕为320*320,显示的话平铺没有问题,但如果640*640则会显示不下,系统为了解决这个问题就将2者给出一个比例值。上面的例子就变成了1:2,即一个点用2个像素填充,就可以将更大的图片放在同样的屏幕中得到正常的显示。同时拥有更高的清晰度。


BOOL multipleTouchEnabled

可修改,默认为NO。用去确认当前视图是否支持多点触摸。设为YES就可以收到多点触摸了。


BOOL exclusiveTouch

可修改,默认为NO。用于设置当前视图是否独享此次点击事件。设为YES后,手指离开此视图前,其他视图都不会收到touch事件。


- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event

方法类型:动态

参数:1.point是在接收者(最开始接收的父视图)视图坐标系中的点。

2.event则是事件对象,表示是一个什么样的事件。

返回值:确定由哪个视图来响应点击事件。

功能:

当我们点击了视图后,是如何确定到底点击了哪个视图呢?以下图举例



上图视图所属关系是,绿<-蓝<-黄<-红。当我们点击了任何一个视图的时候,都是最下面的绿视图(父视图)的hitTest方法最先被调用,然后父视图会调用自己的pointInside方法来确定该事件是否在自己的响应范围内,如果在则先忽略隐藏的,禁用交互的,alpha值小于0.01的子视图,然后调用剩下子视图的hitTest方法。继续以上的步骤直到hitTest返回合适的UIView或者nil。

比如按上图视图层次结构,我们点击了红色视图,那么调用顺序就是

绿视图(hitTest-pointInside返回YES)->蓝视图(hitTest-pointInside返回YES)->黄视图(hitTest-pointInside返回YES)->红视图(hitTest-pointInside返回YES),红视图没有子视图,hitTest返回自己,所以确定了点击事件属于红色视图,红色视图的touchesBegan方法被调用。

再举例,如果我们点击的是蓝色视图,那么调用顺序就是

绿视图(hitTest-pointInside返回YES)->蓝视图(hitTest-pointInside返回YES)->黄视图(hitTest-pointInside返回NO)。注意因为我们点击的是蓝视图(未被遮挡的部分!),所以黄视图的pointInside返回是NO,黄视图的hitTest也会返回nil。等于黄视图告诉自己的父视图(蓝),我和我的子视图都响应不了这个事件,这事不归我管。然后父视图(蓝)收到这个消息后就知道了,子视图处理不了,那么最合适处理这个的就是自己了,于是蓝视图的hitTest方法将自己返回。蓝视图的touchesBegan方法被调用。红视图因为是黄视图的子视图,黄视图自己都处理不了,所以压根儿就不问它了~

说了这么多,这方法有什么用呢?用处大了去了!比如我们看到视频上面常见的进度条,非常非常的细,也就0.5像素,根本没法点击。怎么办呢,就得扩大点击区域,这个方法就用上了,点击在进度条附近,虽然没有点击到它,但我们可以返回它~事件不就交给它了么。

重写hitTest方法想看系统怎么返回,提醒下小白们,调用return [super hitTest:point withEvent:event]; pointInside方法怎么返回的YES也是一样。


- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event

方法类型:动态

参数:1.point是在接收者(最开始接收的父视图)视图坐标系中的点。

2.event则是事件对象,表示是一个什么样的事件。

返回值:BOOL值,返回YES点在自己的处理范围内。

功能:确定当前点击是否在自己的处理范围内。

hitTest方法调用,用来确定当前点击是否在自己的处理范围内,如果返回YES,则hitTest方法就会继续调用自己视图的子视图的hitTest

那么pointInsidehitTest有什么区别呢?pointInside会被hitTest调用,用于确定自己是不是在点击的范围内,而hitTest会返回一个响应事件视图。前者是能不能管,后者是谁来管。

还用上面的图举例,如果用hitTest来响应事件,点击蓝色视图后,调用顺序为

绿视图(hitTest-pointInside返回YES)->蓝视图(hitTest-pointInside返回YES)->黄视图(hitTest-pointInside返回NO,注意,这里如果我们将返回值改变,返回YES,那么后续就变为可能)->红视图(hitTest-pointInside返回NO)。这里会发现本来红视图的hitTest是不会被调用的,但由于我们在黄视图的pointInside方法中返回了YES,按照机制的处理继续调用当前视图的子视图的hitTest,所以我们调用到红视图。而红视图我们又没有重写pointInside方法,返回的NO,所以红视图的hitTest返回nil,而黄视图的pointInside返回值我们改写为了YES,系统会认为点击的是黄视图,黄视图的hitTest方法会返回自己,最后黄视图的touchesBegan会被调用。

说的更简单点,就是hitTest可以决定由谁来处理,pointInside仅是说这事在我的职责范围内,然后需要hitTest再去询问,问不到了,最后哪个视图pointInside返回是YES,这事就归谁了。


- (CGPoint)convertPoint:(CGPoint)point toView:(nullable UIView *)view

方法类型:动态

参数:1.point是当前视图坐标系中的点。

2.view 是目标视图。

返回值:一个CGPoint,经过转换的目标view中的点。

功能:将当前视图坐标系中的点(注意,是当前视图中的点!)转换为目标视图(第二个参数)中的点。


- (CGPoint)convertPoint:(CGPoint)point fromView:(nullable UIView *)view

方法类型:动态

参数:1.point是目标视图坐标系中的点。

2.view 是目标视图。

返回值:一个CGPoint,经过转换的目标view中的点。

功能:将目标视图坐标系中的点(注意,是目标视图中的点!)转换为当前视图中的点。


- (CGRect)convertRect:(CGRect)rect toView:(nullable UIView *)view

就是把点换成区域而已,不特意说明了,逻辑一样。


- (CGRect)convertRect:(CGRect)rect fromView:(nullable UIView *)view

就是把点换成区域而已,不特意说明了,逻辑一样。


BOOL autoresizesSubviews

可修改,默认为YES,设置为YES后,子视图将按照其autoresizingMask设置的值进行调整大小。


UIViewAutoresizing autoresizingMask

可修改,简单调整大小,在没有自动布局前要不按比例计算,要不就是使用这个进行调整,现在有了自动布局,这玩意基本没用了~


- (CGSize)sizeThatFits:(CGSize)size

方法类型:动态

参数:1.CGSize,一个视图区域的大小。

返回值:返回一个最适合视图的大小。

功能:当使用UILable这类控件时,可以使用该方法进行测算内容需要的宽度和高度,这个方法只是进行测算并返回结果,并不会改变视图的实际大小。


- (void)sizeToFit

方法类型:动态

参数:无。

返回值:无。

功能:当使用UILable这类控件时,该方法调用sizeThatFits方法,并将当前视图的大小变更为sizeThatFits方法返回的大小,主要作用是以前没有自动布局时代对于文字适应的一种简便的方法吧。


UIView *superview

只读,当前视图的父视图,就是被谁addSubView添加的,不是继承的关系,是属于谁的问题。


NSArray<__kindof UIView *> *subviews

只读,当前视图的子视图,当前视图调用addSubView添加了谁。


UIWindow *window

只读,当前视图属于哪个window,视图必须要属于一个window,相当于是根目录。一个程序可以有多个window。


- (void)removeFromSuperview

方法类型:动态

参数:无。

返回值:无。

功能:将当前视图从父视图中移出。移出后如果当前视图没有父视图或相似的显示容器,则当前视图不会在屏幕中显示。


- (void)insertSubview:(UIView *)view atIndex:(NSInteger)index

方法类型:动态

参数:1.view要添加的视图。2.要添加在哪一层。

返回值:无。

功能:为当前视图添加一个子视图,因为视图会分层显示,同一父视图中,分层的级别就是0,1,2,3,4,.......,数字越大代表层级越高,就会越往上层。上层视图显示时会挡住下层视图(不透明),所以我们为了让某些视图可以在其他视图之上显示,用这个方法可以精确的将子视图加入到某一层上。


- (void)exchangeSubviewAtIndex:(NSInteger)index1 withSubviewAtIndex:(NSInteger)index2

方法类型:动态

参数:1.层级别。2.层级别。

返回值:无。

功能:为当前视图两个层级别的子视图交换层级别。比如原来属于1层的视图和2层的视图交换,变成了原来1层的去2层,原来2层的去1层,就这么一回事。


- (void)addSubview:(UIView *)view

方法类型:动态

参数:1.要添加的视图。

返回值:无。

功能:为当前视图添加一个子视图。添加以后该视图就会在屏幕上显示,视图层级按顺序添加。


- (void)insertSubview:(UIView *)view belowSubview:(UIView *)siblingSubview

方法类型:动态

参数:1.要添加的视图。2.添加在哪个视图下面。

返回值:无。

功能:为当前视图添加一个子视图。同时确定它的层级,位置具体到在某个视图的下面。


- (void)insertSubview:(UIView *)view aboveSubview:(UIView *)siblingSubview

方法类型:动态

参数:1.要添加的视图。2.添加在哪个视图上面。

返回值:无。

功能:为当前视图添加一个子视图。同时确定它的层级,位置具体到在某个视图的上面。


- (void)bringSubviewToFront:(UIView *)view

方法类型:动态

参数:1.要显示到最前面的子视图。

返回值:无。

功能:将某个子视图放到当前父视图层级的最上层显示。


- (void)sendSubviewToBack:(UIView *)view

方法类型:动态

参数:1.要显示到最下面的子视图。

返回值:无。

功能:将某个子视图放到当前父视图层级的最下层显示。


- (void)didAddSubview:(UIView *)subview

方法类型:动态

参数:1.已经添加的子视图。

返回值:无。

功能:当前视图添加一个子视图完毕的时候,就会调用该方法。


- (void)willRemoveSubview:(UIView *)subview

方法类型:动态

参数:1.将要被移除的子视图。

返回值:无。

功能:将某个子视图将要被当前视图移除的时候,就会调用该方法。


- (void)willMoveToSuperview:(nullable UIView *)newSuperview

方法类型:动态

参数:1.newSuperview当前视图的父视图

返回值:无。

功能:当前的视图将被加入到某个视图时(父视图)时被调用。如果当前视图移除时这个方法也会被调用,参数newSuperview会变为nil。


- (void)didMoveToSuperview

方法类型:动态

参数:无

返回值:无。

功能:同willMoveToSuperview方法类似,作用都是被加入父视图时被调用,只不过需要注意调用次序。willMoveToSuperview将会被先调用,didMoveToSuperview后调用。前者是将要移动到父视图,后者是已经移动完毕。


- (void)willMoveToWindow:(nullable UIWindow *)newWindow

方法类型:动态

参数:1.newWindow当前视图的新窗口。

返回值:无。

功能:因为视图最终都是基于某个window上的,所以说明将其添加至哪个根window上系统会调用该方法。如果当前视图移除时这个方法也会被调用,参数newWindow会变为nil。


- (void)didMoveToWindow

方法类型:动态

参数:无

返回值:无。

功能:同willMoveToWindow方法类似,作用都是被加入window时被调用,只不过需要注意调用次序。willMoveToWindow将会被先调用,didMoveToWindow后调用。前者是将要移动到window,后者是已经移动完毕。


总结以上UIView的方法调用顺序。

1.willMoveToSuperview -> 2.didMoveToSuperview -> 3.willMoveToWindow -> 4.didMoveToWindow


- (BOOL)isDescendantOfView:(UIView *)view

方法类型:动态

参数:1.view 当前视图的祖先~

返回值:返回YES代表当前视图是参数的后代~NO就不是了~如果参数是当前视图的话也会返回YES。

功能:很佩服苹果开发设计人员的用词,这里用了一个Descendant(后代)的词。这个方法的作用是查看当前视图是否是参数视图的后代。为什么是后代呢?比如a视图<-b视图<-c视图。我们可以知道c视图的父视图是b视图,b视图的父视图是a视图。[c isDescendantOfView:b],返回值为YES, 那么[c isDescendantOfView:a]呢?返回的还是YES~ 知道为什么是“后代”了吧~


- (nullable __kindof UIView *)viewWithTag:(NSInteger)tag

方法类型:动态

参数:1.标签,或者叫编号也成,同NSInteger tag属性配合使用。

返回值:返回按标签查找到的第一个子视图视图实例化对象(如果同当前视图标签相同,也会返回当前视图)

功能:按照视图的标签进行递归查询,并将按标签搜索到的第一个子视图的实例化对象返回。而且可以进行深层次的查询。比如a视图(tag为1)<-b视图(tag为2)<-c视图(tag为3),a视图作为根视图,调用[a viewWithTag:3]返回的值就是c视图的实例化对象。


- (void)setNeedsLayout

方法类型:动态

参数:无。

返回值:无

功能:当我们需要调整一个视图中子视图的布局的时候,可以调用这个方法。这个方法会设置一个标记,等待一个更新周期到的时候一起更新,系统会调用layoutIfNeeded方法。比如a视图需要更新,b视图也需要更新,a视图和b视图分别调用该方法,等到更新周期到了时候,a视图和b视图便会都进行更新,这样更加有效率。


- (void)layoutIfNeeded

方法类型:动态

参数:无。

返回值:无

功能:当我们需要调整一个视图中子视图的布局的时候,可以调用这个方法。这个方法同setNeedsLayout不同,会直接进行更新。但如果视图没有调用setNeedsLayout,也就是没有设置更新标记的话,视图重新布局也不会发生。同时layoutSubviews的方法也不会被调用。


- (void)layoutSubviews

方法类型:动态

参数:无。

返回值:无

功能:进行布局子视图的回调,当布局发生调整的时候该方法被调用。当自动布局无法满足需要时,可以重写该方法,当发生布局改变时手动的调整布局。

会被以下几种情况下调用:

1. 由layoutIfNeeded方法调用。2.当前视图或子视图大小,朝向或布局改变时会被调用。3.被添加到父视图时会被调用。4.UIScrollView滚动时,UIScrollView类型的视图该方法也会被调用。


UIEdgeInsets layoutMargins (IOS 8.0以后可使用)

可修改,使用AutoLayout布局后(绝对布局不可以!无效),视图有个内边距的概念。即当前视图边界和其子视图之间的距离。当然是可以直接设定距子视图的距离的,但这类的间距代码可能会很多,可以在父视图中设定一个间距后子视图都会按此设定进行设置。


NSDirectionalEdgeInsets directionalLayoutMargins (IOS 11.0以后可使用)

可修改,功能同layoutMargins属性,layoutMargins属性在ios11版本以后建议使用directionalLayoutMargins属性代替。


BOOL
preservesSuperviewLayoutMargins (IOS 8.0以后可使用)

可修改,默认值为NO,字面意思是保护父视图的layoutMargins布局。但怎么保护,设定完后会如何调整,不清楚......能说清楚的人说说,看了不少网上的文章,大家写的也是比较糊涂,给了个因为,没有所以,直接给了一结果~结果为什么是这个?都没有说明。


BOOL
insetsLayoutMarginsFromSafeArea (IOS 11.0以后可使用)

可修改,默认值为YES,当此属性的值为true时,安全区域之外的任何边距都会自动修改为位于安全区域边界内。设为NO,则忽略安全区域。仅对自动布局有效。


- (void)layoutMarginsDidChange (IOS 8.0以后可使用)

方法类型:动态

参数:无。

返回值:无

功能:改变layoutMargins属性内的值的时候会被调用。注意是结构内的值,不是将layoutMargins属性重新赋值!


UIEdgeInsets safeAreaInsets (IOS 11.0以后可使用)

只读,视图的安全区域(就是那刘海~,即视图操作需要避让的区域,但可以在此区域中进行展示)。注意!这个值不是一开始就确定的,比如在ViewController的viewDidload方法中调用该属性,会发现是一个(0,0,0,0)的值,在viewDidAppear中获取会改变。也可以通过重写方法获取(下面会介绍)


- (void)safeAreaInsetsDidChange (IOS 11.0以后可使用)

方法类型:动态

参数:无。

返回值:无

功能:当视图的安全区域被改变的时候被调用,可以观察safeAreaInsets属性


UILayoutGuide *layoutMarginsGuide (IOS 9.0以后可使用)

只读,UILayoutGuide对象作为一个虚拟视图进行自动布局的占位计算layoutMarginsGuide则就是用于边框的虚拟视图进行自动布局的占位计算。layoutMargins属性设置的边界值在layoutMarginsGuide属性会得到体现(先设置layoutMargins的值再查看layoutMarginsGuide的layoutFrame)。


UILayoutGuide *readableContentGuide (IOS 9.0以后可使用)

只读,视图的最佳阅读区域,就是设定一个UILayoutGuide的虚拟区域,在这个区域中可以更好的进行阅读,在一般机器上感觉不到这个作用。在ipad横屏中会发现这个值很不一样。感觉目的和layoutMarginsGuide一样是为了自动布局给出一个设定的标准。


UILayoutGuide *safeAreaLayoutGuide (IOS 11.0以后可使用)

只读,安全区域,和safeAreaInsets属性的道理一样,只不过类型换成了UILayoutGuide也应该是为了自动布局的使用。


UIKeyboardLayoutGuide *keyboardLayoutGuide(IOS 15.0以后可使用)

只读,键盘的虚拟区域,也是为了自动布局的使用,键盘的位置大小就能确定了,比之前的计算方式不是方便了一点啊!


- (void)drawRect:(CGRect)rect

方法类型:动态

参数:1.rect需要进行绘制的区域。

返回值:无

功能:为当前视图进行绘图操作。当一个绘制周期到了且被标记为需要绘制时被系统调用。基本上我们很少会用到这个方法,因为苹果将视图上面的绘制要不集成在控件里,或者放在了CALayer中,如果我们使用这个方法进行绘制,还要小心屏幕上元素过多,绘制频率很高导致发生多次加载,屏幕会发生闪屏的情况。CALayer会对绘制进行优化,所以这个方法真的不建议用,就算是游戏开发,各种精灵其实也是CALayer。该方法会被setNeedsDisplay或setNeedsDisplayInRect调用。


- (void)setNeedsDisplay

方法类型:动态

参数:无

返回值:无

功能:同setNeedsLayout方法类似也是设定一个标记,只不过setNeedsLayout针对于布局,setNeedsDisplay针对于绘制,调用一个方法并不会引起另一个方法的触发。


- (void)setNeedsDisplayInRect:(CGRect)rect

方法类型:动态

参数:1.rect设置需要进行绘制的区域。

返回值:无

功能:同setNeedsDisplay方法基本相同,不同是可以设定一个重绘的区域,用于提升效率。使用以后系统都会调用drawRect方法,只不过传入的rect参数不同。


BOOL clipsToBounds

可修改,默认值为NO。当前视图的子视图超出父视图的边界时是否要裁剪,换个说法a视图的子视图为b,b的大小或位置如果在a视图的边界外的部分还要不要显示。


UIColor *backgroundColor

可修改,视图的背景色。


CGFloat alpha

可修改,视图的透明度,可以设置0-1之间的数,默认为1,即不透明。


BOOL opaque

可修改,默认为YES。不透明设置。但让视图发生透明度改变的设置他又没用.....佩服苹果的设计人员,一个事就是一个事,不同的事情不混淆,虽说难理解吧.....苹果文档中说明当alpha属性不为1时,这个值要为NO,如果为1时要为YES。该值的目的是在于是否使用绘制优化,如果透明的话进行绘制运算会消耗资源,关闭的话运算就会简便,给使用者一个选择。


BOOL clearsContextBeforeDrawing

可修改,默认值为YES,视图每次重绘前是否将上次的内容清除。


BOOL hidden

可修改,默认值为NO,隐藏当前视图和包含的子视图。


UIViewContentMode contentMode

可修改,默认值为
UIViewContentModeScaleToFill。
就是用于当前视图对于大小,位置,旋转发生改变后,当前视图将如何展示。其属性分为拉伸填充,拉伸裁剪等等。


CGRect contentStretch

可修改,图像的拉伸。已废弃,使用[UIImage
resizableImageWithCapInsets:]
可以达到相同的效果。


UIView *maskView (IOS 8.0以后可使用)

可修改,maskView的颜色不显示,且视图与maskView重叠的部分才会显示。maskView的透明度可设置。相当于在视图上面加了个“可设置透明度的罩子”,它在哪里,下层的视图才会被看到。只能说明它能干什么,但不清楚它当初被设计出来的主要目的是什么.......


UIColor *tintColor (IOS 7.0以后可使用)

可修改,按文字意思就是色调的颜色。比如一件衣服(系统控件),白色为底,有些线条为红色。那么底色白色就是backgroundColor,红色就是tintColor。至于哪里使用tintColor那就是这个衣服设计师的事了~~我们最多作为厂家在制作衣服时将tintColor变为我们想要的颜色,但不能决定哪里将使用这个值~

这个属性还有一个重要的特点,就是和消息链一样,可以进行传递。从父视图开始向子视图进行传递,子视图也会随之改变,除非子视图又做了自己的设定(然后从这个改变的视图开始,该视图的子视图又会按照这个改变的视图设置进行传递)。这样只要我们为window设置好色调以后,整个app的色调都会发生变化。如果大多数控件都采用图片及自定义颜色设置的话就忽略这个属性吧~


UIViewTintAdjustmentMode tintAdjustmentMode (IOS 7.0以后可使用)

可修改,和tintColor配合使用,可以设定tintColor的明暗色。也是可以根据父视图进行传递,设定父视图后,子视图也会随之改变,除非子视图又做了自己的设定然后从这个改变的视图开始,该视图的子视图又会按照这个改变的视图设置进行传递)。


- (void)tintColorDidChange(IOS 7.0以后可使用)

方法类型:静态

参数:无

返回值:无

功能:当tintColor属性被改变时该方法被调用。


+ (void)setAnimationsEnabled:(BOOL)enabled

方法类型:静态

参数:1.enabled指定“YES”以启用动画效果,或指定“NO”以禁用动画效果。

返回值:无

功能:禁用视图(当前应用的,因为是静态方法)的动画效果。如果调用该方法前动画就已经运行,不会禁止仍会继续播放,会影响调用该方法后动画效果的使用。


BOOL areAnimationsEnabled

只读,当前视图是否可以进行动画效果。


+ (void)performWithoutAnimation:(void (NS_NOESCAPE ^)(void))actionsWithoutAnimation (IOS 7.0以后可使用)

方法类型:静态

参数:1.actionsWithoutAnimation 禁用动画效果以后运行的代码块。

返回值:无

功能:先禁用(同setAnimationsEnabled类似)动画效果,然后执行代码块的代码,然后再启用动画。感觉应该等于[UIView setAnimationsEnabled:NO];然后执行一部分代码,再[UIView setAnimationsEnabled:YES];如果真这样的话还弄这么一玩意儿.......有什么必要呢


NSTimeInterval
inheritedAnimationDuration (IOS 9.0以后可使用)

只读,设定的动画持续时长。就是播放多久。


+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOLfinished))completion)

方法类型:静态

参数:1.duration 动画效果运行的时长,单位秒。 2.delay 动画效果延迟运行的时间,单位秒。 3.options动画效果选项,可多选,用|号间隔。里面有重复播放,反向播放,开始慢速最后慢速等动画效果选项,具体大家写代码试验吧,这个很简单,很简单的事咱尽量不说了~ 4.animations在这个参数中设置将产生动画效果视图的代码块。视图的frame,bounds,center,transform,alpha,backgroundColor这些属性在代码块中执行都会引发动画效果,当然还有一点,设定的值和初始的值是不同的,也就是有变化的,如果是一样的,等于没改变,有动画效果你也看不出来啊~ 如果是使用自动布局的话,使用动画效果不要忘记使用setNeedsLayout设定该视图需要重新布局,再调用layoutIfNeeded进行立即布局。 5.completion参数就是动画完成后运行的代码块。如果被设置为重复播放,则completion代码块不会被执行。

返回值:无

功能:视图属性的改变使用动画效果来进行展现。使用这个方法比beginAnimations这种调用方式方便的多,且beginAnimations在iOS13中已经被废弃。


+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion

功能:animateWithDuration的重载方法,只是少了延迟和选项这两个参数(方法会设定默认值,均为0)。


+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations

功能:animateWithDuration的重载方法,只是少了延迟,选项,完成时回调这三个参数(方法会设定默认值,延迟和选项为0,完成时的回调为nil)。


+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay usingSpringWithDamping:(CGFloat)dampingRatio initialSpringVelocity:(CGFloat)velocity options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOLfinished))completion

功能:animateWithDuration的重载方法,实现弹性动画效果。多了dampingRatio和velocity这两个参数。dampingRatio为弹簧的阻尼参数。范围0-1。设为1时,阻尼为最大,动画效果会直接到最终结果,不会发生振荡,如果值设的越小阻尼越小,发生的震荡就会越大。当前这个值怎么设的合适,有什么依据,不晓得了~velocity参数是设定弹簧初始化的速度,或者叫做形变的速度,如果值越大,形变的速度也就越快。那么这个参数怎么设置好呢?苹果给出的建议是初始速度要和视图的动画效果的速度要一致,使动画平滑。举例,比如我们动画时长为5秒,距离为200pt,那么视图速度就为200/5=40pt/s,当这个值设为1时,就是在1秒钟内经过动画的全部距离,所以我们就将该值设为0.2是最合适的。当然也可以将值设大(超过1),设的值越大看上去变化的速度也越快。


+ (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^ __nullable)(void))animations completion:(void (^ __nullable)(BOOL finished))completion

方法类型:静态

参数:1.view作为容器的视图(父视图)。2.duration动画效果运行的时长。3.options动画效果选项,可多选,用|号间隔。里面有重复播放,反向播放,翻页等各类动画效果选项。4.animations在这个参数中设置将产生动画效果视图的代码块。可以设置产生动画效果的有视图(子视图发生的操作也可以)的添加,移除,隐藏。因为其实动画效果发生的是父视图,其中子视图只是跟着父视图的动画效果走而已。 5.completion参数就是动画完成后运行的代码块。如果被设置为重复播放,则completion代码块不会被执行。

返回值:无

功能:这个方法是作用于视图的转场的动画效果,就是视图添加或者移除用动画效果来进行展现。


+ (void)transitionFromView:(UIView *)fromView toView:(UIView *)toView duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options completion:(void (^ __nullable)(BOOL finished))completion

方法类型:静态

参数:1.fromView将要被移除的视图。2. toView 被添加的视图,会被添加到fromView的父视图中 3.duration动画效果运行的时长。4.options动画效果选项,可多选,用|号间隔。里面有重复播放,反向播放,翻页等各类动画效果选项。 5.completion参数就是动画完成后运行的代码块。如果被设置为重复播放,则completion代码块不会被执行。

返回值:无

功能:这个方法是作用于视图的转场的便捷动画效果,不需要使用代码块进行操作。只需要说明哪个视图(fromView参数)将被移除,哪个视图(toView视图)将被显示就可以了。如果不希望使用添加和移除方式,可以使用隐藏显示的方法来进行切换,options参数添加上
UIViewAnimationOptionShowHideTransitionViews
就可以了。


+ (void)performSystemAnimation:(UISystemAnimation)animation onViews:(NSArray<__kindof UIView *> *)views options:(UIViewAnimationOptions)options animations:(void (^ __nullable)(void))parallelAnimations completion:(void (^ __nullable)(BOOL finished))completion (IOS 7.0以后可使用)

方法类型:静态

参数:1.animation参数为系统会使用的动画效果类型,目前只有移除(使用后会真的将视图移除)类型。2.onViews参数为一个或多个将要使用animation参数设定的动作进行动画效果的视图。3.animations参数为同onViews参数设定的视图一同产生动画效果的代码块,修改frame等属性,或者添加移除视图等。但注意不要修改正在执行系统动画的视图的属性!4,5参数同上,不在多做阐述。

返回值:无

功能:这个方法的设计思路其实是很好的,当我们做一些动画效果的时候是希望和系统的动画效果一起的。这个方法就是为了实现这个,所以他没有动画效果运行时间参数,因为是和系统的动画运行时长是相同的,所以不用设置。但问题是,只有一种系统动画类型啊!并且还不是所有的视图系统在移除时会有动画效果啊!所以这玩意,用处窄的很呐~

备注:以上所有动画转场效果进行时,默认视图的交互会被禁止,如果仍然希望可以使用视图交互,在options参数中添加
UIViewAnimationOptionAllowUserInteraction。


+ (void)
modifyAnimationsWithRepeatCount:(CGFloat)count autoreverses:(BOOL)autoreverses animations:(void(NS_NOESCAPE ^)(void))animations(IOS13.0以后可使用)

方法类型:静态

参数:1.count参数为动画效果重复播放的次数。2.autoreverses参数为重复播放时是否要用动画效果到开始状态。同
UIViewAnimationOptionAutoreverse值。3.
animations参数就是要进行动画效果的代码块。

返回值:无

功能:这个方法是为了解决原有的动画效果进行设定重复播放时是没有次数限制的,会一直进行播放,使用这个方法就可以设定动画播放具体的次数了。这个方法的调用方式比较特别,必须要放在其他执行动画块的代码嵌套中才可以使用,单独调用无效。举例代码如下:

[UIView animateWithDuration:2 delay:0 options:0 animations:^{

[UIView modifyAnimationsWithRepeatCount:2 autoreverses:YES animations:^{

//在这里设置要进行重复次数的视图代码,而不是放在animateWithDuration方法的动画块中

yellowColorView.frame = CGRectMake(0, 0, 20, 20);

}];

} completion:^(BOOL finished) {

}];


+ (void)
animateKeyframesWithDuration
:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(
UIViewKeyframeAnimationOptions
)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion(IOS7.0以后可使用)

方法类型:静态

参数:1.duration参数为当前动画效果的持续时长,单位秒。2.delay参数为当前动画效果延时进行时长,单位秒。3.options参数为如果执行动画的选项,可多选。但有一些选项是这个方法特有的。具体效果就不具体说明了,有兴趣的自己试试吧,很难用语言描述~ 4.animations参数为执行动画块代码。这个参数和其他动画的参数不同在于,可以进行嵌套另一个方法
addKeyframeWithRelativeStartTime
,从而进行更精确的动画效果控制。5.completion参数和之前提过的视图动画相关方法参数相同。

返回值:无

功能:关键帧动画是为了让一个或多个视图在同一动画时长内,在不同的动画帧(时间点)拥有动画效果,
animateKeyframesWithDuration
方法等于是创建了一个可以添加动画的容器。
addKeyframeWithRelativeStartTime
方法向这个容器中添加内容。


+ (void)
addKeyframeWithRelativeStartTime:(double)frameStartTime relativeDuration:(double)frameDuration animations:(void (^)(void))animations(IOS7.0以后可使用)

方法类型:静态

参数:1.frameStartTime参数为当前动画在什么时间开始。该值的范围就是0-1。全部的动画时长就是
animateKeyframesWithDuration
方法中设定的时长。可以当成1,举例:4秒长度,我们想让这个动画在2秒时运行,那么设置0.5就可以了。说简单点,就是一个百分比。根据百分比设置开始播放的时间点。 2.frameDuration参数为当前动画效果运行时长,和frameStartTime参数相同,也是一个百分比,取值范围也是0-1。 3.animations参数为执行动画块代码。

返回值:无

功能:这个方法只能在
animateKeyframesWithDuration
方法的animations的参数中被调用。添加在
animateKeyframesWithDuration
方法中后就可以设定在某个具体的关键帧(时间点)运行的动画了。代码举例如下:

[UIView animateKeyframesWithDuration:4 delay:0options:UIViewKeyframeAnimationOptionCalculationModeCubic animations:^{

[UIView addKeyframeWithRelativeStartTime:0.2 relativeDuration:1 animations:^{

yellowColorView.frame = CGRectMake(0, 0, 20, 20);

}];

[UIView addKeyframeWithRelativeStartTime:0.5 relativeDuration:0.2animations:^{

blueColorView.frame = CGRectMake(0, 0, 50, 50);

}];

} completion:^(BOOL finished) {

}];


NSArray<__kindof UIGestureRecognizer *> *gestureRecognizers

可修改,当前视图的手势识别器集合。


- (void)addGestureRecognizer:(UIGestureRecognizer*)gestureRecognizer

方法类型:动态

参数:1.gestureRecognizer参数为一个手势对象实例。

返回值:无

功能:将一个手势对象实例添加到当前视图。就是说手势对象实例有了载体,将在当前视图中使用。


- (void)removeGestureRecognizer:(UIGestureRecognizer*)gestureRecognizer

方法类型:动态

参数:1.gestureRecognizer参数为一个手势对象实例。

返回值:无

功能:将一个手势对象实例从当前视图移除。当前视图中如果拥有这个手势实例,方法被调用后将会从当前视图中移除该手势实例。如果之前添加了该实例,视图销毁时一定要记得移除,否则可能会引起内存问题(无效地址的访问)。


- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer*)gestureRecognizer

方法类型:动态

参数:1.gestureRecognizer参数为一个状态为
UIGestureRecognizerStatePossible的手势对象实例。

返回值:该手势是否可以使用,如果可以使用则返回YES,不能使用则返回NO。返回NO以后,对应的手势对象实例状态变为
UIGestureRecognizerStateFailed。

功能:这个方法可以避免有些手势被识别使用。就是说当前视图如果想要在某种情况下不想使用某些手势,通过手势对象实例判断出以后,对应的手势返回NO,就可以不使用这些手势了。


- (void)addMotionEffect:(UIMotionEffect *)effect (IOS7.0以后可使用)

方法类型:动态

参数:1.effect参数为一个运动效果的对象实例。

返回值:无

功能:将一个运动效果的对象实例添加到当前视图中。这个效果就是当设备角度发生变化时,看到的效果也不同。以后开篇讲UIMotionEffect的时候再介绍吧。


- (void)removeMotionEffect:(UIMotionEffect *)effect (IOS7.0以后可使用)

方法类型:动态

参数:1.effect参数为一个运动效果的对象实例。

返回值:无

功能:将一个运动效果的对象实例从当前视图移除。当前视图中如果拥有这个运动效果实例,方法被调用后将会从当前视图中移除该实例。如果之前添加了该实例,视图销毁时一定要记得移除,否则可能会引起内存问题(无效地址的访问)。


NSArray<__kindof UIMotionEffect *> *motionEffects(IOS 7.0以后可使用)

可修改,当前视图的水平运动识别集合。就是根据设备水平角度的改变来做对应的处理。


NSArray<__kindof NSLayoutConstraint *> *constraints(IOS 6.0以后可使用)

只读,自动布局的约束集合。


- (void)addConstraint:(UIMotionEffect *)effect

- (void)addConstraints:(NSArray<__kindof NSLayoutConstraint *> *)constraints

- (void)removeConstraint:(NSLayoutConstraint *)constraint

- (void)removeConstraints:(NSArray<__kindof NSLayoutConstraint *> *)constraints(IOS7.0以后可使用)

功能:这几个方法都是自动布局的添加和移除方法,就是之前的那套反人类的原生“自动布局”方式~后来慢慢了原生锚点的方式后,这套慢慢要被废弃的,UIView.h文件中,系统也建议不要再用这些方法了,后期肯定要会被废弃的。所以也就别看了,我也少说几句~


- (void)updateConstraintsIfNeeded (IOS6.0以后可使用)

方法类型:动态

参数:无

返回值:无

功能:当布局的约束需要更新时,系统会自动的调用该方法。该方法调用后会立即进行更新。和之前的layoutIfNeeded方法很像,逻辑完全相同,只不过功能不同,这个方法仅更新约束。注:子类不应该重写此方法。


- (void)updateConstraints (IOS6.0以后可使用)

方法类型:动态

参数:无

返回值:无

功能:更新约束,会由系统调用每个子视图,可以重写该方法进行约束的更新。但系统建议只是在可能约束更新比较多,导致性能低下的时候重写该方法。并不是说让我们将所有的约束都在这里添加或修改。而且这个方法由系统调用,不建议个人调用,且重写后一定要加[super updateConstraints];调用父类的方法。


- (BOOL)needsUpdateConstraints (IOS6.0以后可使用)

方法类型:动态

参数:无

返回值:YES代表需要更新,NO则是不需要。

功能:该方法就是可以知道当前视图的约束是否需要更新。


- (void)setNeedsUpdateConstraints (IOS6.0以后可使用)

方法类型:动态

参数:无

返回值:无

功能:同setNeedsLayout方法类似,也是设定一个标识。不同在于仅为布局约束的更新标识。


BOOL
translatesAutoresizingMaskIntoConstraints(IOS 6.0以后可使用)

可修改,默认值为YES。作用是将使用绝对布局的autoresizingMask转换为自动布局的约束。如果要使用自动布局来进行视图定位时,该值必须设为NO。其实autoresizingMask的默认值为UIViewAutoresizingNone,也就是不使用,所以这个值不设为NO也是可以的。前提是没人手欠,把autoresizingMask给改了~


BOOL
requiresConstraintBasedLayout(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.

*/

就是说使用updateConstraints进行更新约束时,必须要重写这个属性且返回YES!因为约束是懒触发的,只有在有约束的情况时,使用updateConstraints才会有效果,但没有约束时使用updateConstraints更新(这时应该叫初始化)约束后,系统不会进行更新。要解决这个先有鸡还有先有蛋的问题,所以要使用
requiresConstraintBasedLayout这个属性来告诉系统,必须要更新约束。


- (CGRect)alignmentRectForFrame:(CGRect)frame (IOS6.0以后可使用)

方法类型:动态

参数:1.frame参数为一个视图的矩形区域(绝对布局)。

返回值:返回一个视图对应的对齐矩形(自动布局)。

功能:通过视图的一个矩形区域(绝对布局)转换为对应的对齐矩形(自动布局)。alignmentRectInset属性(看下面),自动布局并不是通过frame来决定视图的位置及大小的,而是通过alignmentRect,为了将这俩个值明确关系,系统提供了这个转换方法。当然如果自定义视图想要重新定义的话也是可以的,重写该方法就可以了,进行重新定义转换关系。


- (CGRect)frameForAlignmentRect:(CGRect)alignmentRect (IOS6.0以后可使用)

方法类型:动态

参数:1.alignmentRect参数为一个视图的对齐矩形区域(自动布局)。

返回值:返回一个视图对应的矩形(绝对布局)。

功能:通过视图的一个对齐矩形转换为对应的矩形。和alignmentRectForFrame是相反的方法。也可以重写,不过系统建议重写了一个,别忘了另外一个~。


UIEdgeInsets alignmentRectInsets(IOS 6.0以后可使用)

只读,视图自动布局的大小和位置我们一般认为就是视图的frame,这么认为也确实没错~因为大多数情况确实如此。但自动布局其实是使用alignmentRect来确定位置及大小的。那么alignmentRectInsets就是alignmentRect的偏移值。比如一个视图有阴影,但我们进行布局时希望可以忽略掉阴影的大小,那么我们就可以重写该属性,进行设定视图矩形上下左右的偏移值,设为负值就可以了。这样就会按忽略掉阴影大小的视图进行布局。


UIView *
viewForFirstBaselineLayout(IOS 9.0以后可使用)

只读,基于视图的第一条基线UIView。这个属性有什么作用呢?当自动布局使用
NSLayoutAttributeFirstBaseline的方式进行布局时,系统将会调用该属性,然后根据这个值进行布局。
但不要太美,系统默认返回的就是当前视图,就是return self; 所以真要用起来需要重写该属性,然后返回指定的UIView来进行对齐。


UIView *viewForLastBaselineLayout(IOS 9.0以后可使用)

只读,基于视图的最后一条基线UIView。同
viewForFirstBaselineLayout。当自动布局使用
NSLayoutAttributeLastBaseline(跟上面的不一样哟)的方式进行布局时,系统将会调用该属性,然后根据这个值进行布局。
但不要太美,系统默认返回的就是当前视图,就是return self; 所以真要用起来需要重写该属性,然后返回指定的UIView来进行对齐。


CGSize intrinsicContentSize(IOS 6.0以后可使用)

只读,词的意思是叫做固定内容大小。作用是当我们使用自动布局的时候,比如UILabel只指定了一个位置,没有定义大小的时候,UIabel会根据文字内容的多少来决定自己的大小。它是怎么做到的呢?根据文字量来重新定义自己的约束吗?或者重新计算自己的frame吗?都不是,UILabel类在自己内部重写了intrinsicContentSize这个属性然后返回了自己计算后的大小。为什么不重新定义约束或者重新计算自己的frame呢?第一随意添加约束和修改约束会引发冲突的,第二计算frame就成了绝对布局了,使用自动布局,然后还用绝对布局最为布局的变化发起者,明显不合适。

但并不是所有的继承UIView的视图都会重写intrinsicContentSize这个属性,大部分视图这个属性会返回一个值为UIViewNoIntrinsicMetric常量的CGSize的值。所以当我们使用自动布局,视图又希望根据内容的来决定自身大小的话,重写这个属性是最优雅的方法了!


- (void)
invalidateIntrinsicContentSize (IOS6.0以后可使用)

方法类型:动态

参数:无

返回值:无

功能:当intrinsicContentSize属性有变化的时候,调用这个方法,会重新调用intrinsicContentSize属性重新设置。


- (UILayoutPriority)
contentHuggingPriorityForAxis
:(UILayoutConstraintAxis)axis (IOS6.0以后可使用)

方法类型:动态

参数:1.axis参数是设定要获取哪个方向上的优先级,水平方向或者垂直方向。

返回值:返回一个当前视图某个方向上对应的抗被拉伸优先级。

功能:获取视图对应方向上面的优先级,没有设置这个有用~。


- (void)setContentHuggingPriority:(UILayoutPriority)priority forAxis:(UILayoutConstraintAxis)axis (IOS6.0以后可使用)

方法类型:动态

参数:1.priority参数是对应方向上的优先级,本质是个float类型,数值越大级别越高。 2.axis参数是设定哪个方向上的优先级,水平方向或者垂直方向。

返回值:无

功能:设定视图某个方向的抗拉伸级别。级别越高越不容易被拉伸。下图具体举例。


以下代码运行起来就是上图的样子。

左面的UILabel

UILabel *blueColorView = [[UILabel alloc] init];

blueColorView.text = @"左面的内容";

blueColorView.backgroundColor = [UIColor blueColor];

blueColorView.translatesAutoresizingMaskIntoConstraints = NO;

[self.view addSubview:blueColorView];

//开始设定blueColorView的大小及位置,因为是UILabel,所以宽度不指定。

[blueColorView.leftAnchor constraintEqualToAnchor:self.view.leftAnchor].active= YES;

[blueColorView.topAnchor constraintEqualToAnchor:self.view.topAnchor].active= YES;

[blueColorView.bottomAnchorconstraintEqualToAnchor:self.view.bottomAnchor].active = YES;

//右边的UILabel

UILabel *yellowColorView = [[UILabel alloc] init];

yellowColorView.backgroundColor = [UIColor yellowColor];

yellowColorView.translatesAutoresizingMaskIntoConstraints = NO;

yellowColorView.text = @"右边的内容";

[self.view addSubview:yellowColorView];


[yellowColorView.leftAnchorconstraintEqualToAnchor:blueColorView.rightAnchor].active = YES;

[yellowColorView.rightAnchorconstraintEqualToAnchor:self.view.rightAnchor].active = YES;

[yellowColorView.topAnchorconstraintEqualToAnchor:self.view.topAnchor].active = YES;

[yellowColorView.bottomAnchorconstraintEqualToAnchor:self.view.bottomAnchor].active = YES;

再次感谢苹果出了布局锚点,再次谢谢饶程序员不死,不用再用三方的布局(系统更新一次一堆警告,扒一层皮,坤啊,你还记得不),不用再用以前的原生自动布局~

然后这些和setContentHuggingPriority抗拉伸有什么关系呢?我们可以看到左面的内容实际空白很多,实际就是被拉伸了。我们怎么能拒绝这种拉伸呢?设置抗拉伸吧。加入[blueColorView setContentHuggingPriority:UILayoutPriorityRequired forAxis:
UILayoutConstraintAxisHorizontal];这行代码,将blueColorView的水平抗拉伸级别调高,那么就可以抵抗这种拉伸了。下图就是加入这行代码的结果。



- (UILayoutPriority)
contentCompressionResistancePriorityForAxis:(UILayoutConstraintAxis)axis (IOS6.0以后可使用)

方法类型:动态

参数:1.priority参数是对应方向上的优先级,本质是个float类型,数值越大级别越高。 2.axis参数是设定哪个方向上的优先级,水平方向或者垂直方向。

返回值:返回一个当前视图某个方向上对应的抗被压缩优先级。

功能:获取视图对应方向上面的优先级,没有设置这个有用~。


- (void)
setContentCompressionResistancePriority:(UILayoutPriority)priority forAxis:(UILayoutConstraintAxis)axis (IOS6.0以后可使用)

方法类型:动态

参数:1.priority参数是对应方向上的优先级,本质是个float类型,数值越大级别越高。 2.axis参数是设定哪个方向上的优先级,水平方向或者垂直方向。

返回值:无

功能:设定视图某个方向的抗压缩级别。级别越高越不容易被压缩。下图具体举例。


代码和之前抗拉伸的一致,只不过把文字换了,把右边的文字颜色变成红色。现在左面的文字内容全部显示出来,但右边的只剩....了。通过设定
setContentCompressionResistancePriority抗压缩级别,我们可以将右边的内容显示出来。添加[yellowColorView
setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:
UILayoutConstraintAxisHorizontal];代码,结果如下图。


总结下啊,通过调整抗拉伸和抗压缩优先级我们可以完成视图在使用自动布局时对于内容显示上更加灵活的展示。当然其实方法也有很多种,比如通过使用自动布局的小于等于,大于等于等等方式也基本能达到以上的效果。但这里其实最重要的是告诉大家,在使用自动布局时要有优先级的概念,在做自动布局约束时如果发现一些问题,不妨考虑下优先级的问题。就像之前的例子一样,没给左面的UILabel指定宽度,所以他的布局就是要将所有的内容显示出来。而右边的UILabel又要依赖左面UILabel的宽度,为了解决这种冲突,苹果利用对应的优先级概念很好的解决了这个问题!这个才是大家应该注意的。


- (CGSize)
systemLayoutSizeFittingSize:(CGSize)targetSize (IOS6.0以后可使用)

方法类型:动态

参数:1.targetSize参数是用两个常量就可以了,一个为
UILayoutFittingCompressedSize表示给出一个最小的大小。另一个为UILayoutFittingExpandedSize表示最大的大小。

返回值:按照targetSize的设定返回的一个系统计算后的视图最适合的大小。

功能:这个功能和sizeThatFits方法有些类似都是可以计算视图内容的大小,不同点在于sizeThatFits是计算在布局后的视图,而这个方法则是可以计算在未完成布局的时候。注意啊,这个是和sizeThatFits方法类似,可千万别认为这方法是可以计算任何布局的,别傻傻的以为随便一个自动布局就可以算了,比如以下代码:

UIView *blueColorView = [[UIView alloc] init];

blueColorView.backgroundColor = [UIColor blueColor];

blueColorView.translatesAutoresizingMaskIntoConstraints = NO;

[self.view addSubview:blueColorView];

[blueColorView.leftAnchor constraintEqualToAnchor:self.view.leftAnchor].active= YES;

[blueColorView.rightAnchorconstraintEqualToAnchor:self.view.rightAnchor].active = YES;

[blueColorView.topAnchor constraintEqualToAnchor:self.view.topAnchor].active= YES;

[blueColorView.bottomAnchorconstraintEqualToAnchor:self.view.bottomAnchor].active = YES;

CGSize size = [blueColorView systemLayoutSizeFittingSize:UILayoutFittingExpandedSize];

最后size的结果就是(10000,10000)........

再举例如果要计算一个有内容的视图比如UILabel,把numberOfLines属性设为0,代表我们要多行显示,然后还有个关键的属性preferredMaxLayoutWidth也要给出一个宽度。然后
systemLayoutSizeFittingSize这个方法才可以正常工作........所以这个方法记住类比sizeThatFits的功能就可以了。同样,也不会对视图的大小作出修改。


- (CGSize)
systemLayoutSizeFittingSize:(CGSize)targetSize
withHorizontalFittingPriority:(UILayoutPriority)horizontalFittingPriority verticalFittingPriority:(UILayoutPriority)verticalFittingPriority (IOS8.0以后可使用)

方法类型:动态

参数:1.targetSize参数是用两个常量就可以了,一个为
UILayoutFittingCompressedSize表示给出一个最小的大小。另一个为UILayoutFittingExpandedSize表示最大的大小。2.horizontalFittingPriority参数是水平约束的优先级。3.verticalFittingPriority参数是垂直约束的优先级。

返回值:按照targetSize,的设定返回的一个系统计算后的视图最适合的大小。

功能:和
systemLayoutSizeFittingSize方法功能基本一致,只不过加入了约束优先级的概念。和之前讲过的setContentCompressionResistancePriority方法和setContentHuggingPriority方法有联系,因为如果视图设定了优先级,所以计算时也要将该优先级考虑进去。


NSArray<__kindof UILayoutGuide *> *layoutGuides(IOS 9.0以后可使用)

只读,当前视图添加的UILayoutGuide对象的集合。


- (void)addLayoutGuide:(UILayoutGuide *)layoutGuide (IOS9.0以后可使用)

方法类型:动态

参数:1.layoutGuide参数为一个UILayoutGuide对象的实例。

返回值:无。

功能:作用是将一个UILayoutGuide对象的实例添加至当前的视图中。之前在属性中讲过这个,不再多做阐述,简单的再说一下,就是将一个虚拟的区域添加至视图中,用于自动布局。


- (void)removeLayoutGuide:(UILayoutGuide *)layoutGuide (IOS9.0以后可使用)

方法类型:动态

参数:1.layoutGuide参数为一个UILayoutGuide对象的实例。

返回值:无。

功能:作用是将一个UILayoutGuide对象的实例从当前的视图中移除。


NSLayoutXAxisAnchor *leadingAnchor(IOS 9.0以后可使用)

只读,新的约束方法,用于替换原生NSLayoutConstraint这一套惨绝人寰的使用方法......

头部的布局锚点,和semanticContentAttribute属性有关联,也就是“阅读习惯”,从左往右,还是从右至左布局。和左边leftAnchor的区别就是根据阅读习惯的设置会发生改变。

leftAnchor,rightAnchor等等不在此特别说明,介绍NSLayoutAnchor时再说吧。


- (NSArray<__kindof NSLayoutConstraint *> *)constraintsAffectingLayoutForAxis:(UILayoutConstraintAxis)axis (IOS6.0以后可使用)

方法类型:动态

参数:1.axis参数为方向参数,水平或垂直方向。

返回值:返回当前视图对应方向上面的全部约束。

功能:按参数返回当前视图上面的全部约束,主要用于调试基于约束的布局。


BOOL hasAmbiguousLayout(IOS 10.0以后可使用)

只读,“有模糊的布局”,作用是可以用于检查约束是否具有唯一性,或者缺少。如果返回YES则代表约束是模糊的,可能会导致显示位置不正确。为什么不在编译时就进行提示呢?苹果文档中原文是这样的“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.

中提到了“由于性能考虑和布局所用算法的细节,UIKit不会自动检测到这种情况。”。所以如果布局发现有问题了,看一下这个值来确定一下是否因为约束缺少或有问题。约束错了的话那就得自己找了......聊胜于无的功能吧。


- (void)exerciseAmbiguityInLayout (IOS6.0以后可使用)

方法类型:动态

参数:无。

返回值:无。

功能:将“模糊的布局”切换成有效布局,就是系统帮你“补完”,但别指望帮你补完成你想要的,顶多是不报错。


NSString *restorationIdentifier(IOS 6.0以后可使用)

可修改,恢复标识符,用于退出系统后再启动的系统视图恢复。如果要使用恢复功能的话,该值必须设置,且不能为nil,否则恢复机制会忽略该视图。一般来说设置当前的对象名就可以了。NSStringFromClass(self.class)


- (void) encodeRestorableStateWithCoder:(NSCoder *)coder (IOS6.0以后可使用)

方法类型:动态

参数:1.coder参数是用于进行数据保存或恢复的对象。

返回值:无。

功能:作用是为了退出系统后再启动的视图恢复,重写该方法已保存退出后下次恢复时的数据。和restorationIdentifier配套使用。这块等讲UIViewController时再说吧,那个才是主要的使用场景。


- (void) decodeRestorableStateWithCoder:(NSCoder *)coder (IOS6.0以后可使用)

方法类型:动态

参数:1.coder参数是用于进行数据保存或恢复的对象。

返回值:无。

功能:作用是为了退出系统后再启动的视图恢复,重写该方法在启动时从coder取出退成程序时保存的数据已重现之前的视图状态。同上,不讲清楚的理由也同上~


- (nullable UIView *)snapshotViewAfterScreenUpdates:(BOOL)afterUpdates (IOS7.0以后可使用)

方法类型:动态

参数:1.afterUpdates参数为YES是在视图设置后进行截屏,NO是马上进行截屏。苹果文档中的例子:

- (void)layoutSubviews {

UIView *snapshot = [self snapshotViewAfterScreenUpdates:YES];

self.alpha = 0.0;

}

以上代码最后得到的就是一个空的视图,因为设置的afterUpdates参数是YES,所以截屏就是要将self.alpha = 0.0这个考虑进去的。透明度为0,那当然就看不到了。

返回值:返回一个当前视图的“副本”,但对象本身不能像主对象那样可以有自定义的方法等等,仅仅是“展现的样子”一样。

功能:以前我们只能通过截图的方式来进行截屏,现在我们可以通过这个方法直接对视图进行截屏,不生成图像截屏干什么呢?最通常的作用就是我们要做动画~


- (nullable UIView *)resizableSnapshotViewFromRect:(CGRect)rect afterScreenUpdates:(BOOL)afterUpdates withCapInsets:(UIEdgeInsets)capInsets (IOS7.0以后可使用)

方法类型:动态

参数:1.rect参数为要截屏的范围。 2.afterUpdates参数为YES是在视图设置后进行截屏,NO是马上进行截屏。3.capInsets参数将按照这个区域进行拉伸和缩放,取值范围是0-1。

返回值:返回一个当前视图的“副本”,但对象本身不能像主对象那样可以有自定义的方法等等,仅仅是“展现的样子”一样。

功能:同snapshotViewAfterScreenUpdates功能一致,只不过可以进行指定范围的截屏,并还可以通过capInsets的设置进行拉伸和缩放操作的。该方法和UIImage的resizableImageWithCapInsets方法很像。


- (BOOL)drawViewHierarchyInRect:(CGRect)rect afterScreenUpdates:(BOOL)afterUpdates (IOS7.0以后可使用)

方法类型:动态

参数:1.rect参数为要生成快照的范围。 2.afterUpdates参数为YES是在视图设置后进行快照,NO是马上进行快照。

返回值:如果能将快照放到当前图形上下文中,则返回YES,如果无法放入则返回NO。

功能:这就是截屏并要生成图像的重要方法了。先调用该方法,然后再从图形上下文中进行截图。

@implementation UIView(UIView)


- (UIImage *)snapshot

{

[self drawViewHierarchyInRect:self.bounds afterScreenUpdates:YES];//放入上下文中

//以下为从上下文中获得该图像。

UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, [UIScreen mainScreen].scale);

CGContextRef context = UIGraphicsGetCurrentContext();

[self.layer renderInContext:context];

UIImage *image = UIGraphicsGetImageFromCurrentImageContext();

UIGraphicsEndImageContext();

}

@end


UIUserInterfaceStyle
overrideUserInterfaceStyle(IOS 13.0以后可使用)

可修改,作用就是推出的夜晚模式和白天模式的配置。通过设置可以设置某个特定的视图。但该视图的子视图也将遵循该设置。没什么特殊需要的话,直接设置window的这个属性就完了。


UIContentSizeCategory minimumContentSizeCategory

可修改,对于动态类型大小的支持,当前视图的最小值,可以设置为nil,等于没有限制。例如系统设置里面文字大小,我们设置了最小值,也就是如果系统设置的比我们的值小,那么该视图将按照
minimumContentSizeCategory这个属性设置的最小值显示,而不是按照系统设置的。


UIContentSizeCategory maximumContentSizeCategory

可修改,对于动态类型大小的支持,当前视图的最大值,可以设置为nil,等于没有限制。同上。


NSString *appliedContentSizeCategoryLimitsDescription

只读,一个字符串,内容是当前视图的层级关系(当前视图的父视图一直到window)。还有UIContentSizeCategory的值苹果文档的说法是用于调试目的。


完了完了,有功夫再写,下一次就是UIViewController~这坑也不小~

举报
评论 0