UIView 半解(2)

原文:cyrill's blog

@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.
// frame是指視圖在其父視圖坐標(biāo)系中的位置與尺寸??梢杂胋ounds和center代替
@property(nonatomic) CGRect            frame;

// use bounds/center and not frame if non-identity transform. if bounds dimension is odd, center may be have fractional part
// 是指視圖在其自己的坐標(biāo)系(有一個(gè)自身的坐標(biāo)系)中的位置和尺寸(與父視圖無(wú)關(guān))
@property(nonatomic) CGRect            bounds;      // default bounds is zero origin, frame size. animatable
// 該視圖的中心點(diǎn)在其父視圖坐標(biāo)系中的位置坐標(biāo)
@property(nonatomic) CGPoint          center;      // center is center of frame. animatable
// 形變屬性(平移\縮放\旋轉(zhuǎn))
@property(nonatomic) CGAffineTransform transform;   // default is CGAffineTransformIdentity. animatable
@property(nonatomic) CGFloat          contentScaleFactor NS_AVAILABLE_IOS(4_0);
// getter=isMultipleTouchEnabled 重構(gòu)getter方法 當(dāng)前View是否支持多點(diǎn)觸控事件 默認(rèn)NO
@property(nonatomic,getter=isMultipleTouchEnabled) BOOL multipleTouchEnabled;   // default is NO
// 決定當(dāng)前的view是否是處理觸摸事件的唯一對(duì)象(不能同時(shí)點(diǎn)擊多個(gè)view) 默認(rèn)是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

/**==========*******convertPonit****===================*/

/** 將像素point由point所在視圖轉(zhuǎn)換到目標(biāo)視圖view中,返回在目標(biāo)視圖view中的像素值 */
- (CGPoint)convertPoint:(CGPoint)point toView:(UIView *)view;
/** 將像素point由point所在視圖轉(zhuǎn)換到目標(biāo)視圖view中,返回在目標(biāo)視圖view中的像素值 */
// CGPoint pointInView =  [self.redView convertPoint:pointInOriView fromView:self.view];
- (CGPoint)convertPoint:(CGPoint)point fromView:(UIView *)view;
/** 將rect由rect所在視圖轉(zhuǎn)換到目標(biāo)視圖view中,返回在目標(biāo)視圖view中的rect */
- (CGRect)convertRect:(CGRect)rect toView:(UIView *)view;
/** 將rect從view中轉(zhuǎn)換到當(dāng)前視圖中,返回在當(dāng)前視圖中的rect */
- (CGRect)convertRect:(CGRect)rect fromView:(UIView *)view;

// 例把UITableViewCell中的subview(btn)的frame轉(zhuǎn)換到 controllerA中
// controllerA 中有一個(gè)UITableView, UITableView里有多行UITableVieCell,cell上放有一個(gè)button

/*
// 在controllerA中實(shí)現(xiàn):

CGRect rc = [cell convertRect:cell.btn.frame toView:self.view];

或

CGRect rc = [self.view convertRect:cell.btn.frame fromView:cell];

// 此rc為btn在controllerA中的rect
或當(dāng)已知btn時(shí):

CGRect rc = [btn.superview convertRect:btn.frame toView:self.view];

或

CGRect rc = [self.view convertRect:btn.frame fromView:btn.superview];
=================***************==========================*/

//當(dāng)你改變視圖的邊框矩形時(shí),其內(nèi)嵌的子視圖的位置和尺寸往往需要改變,以適應(yīng)原始視圖的新尺寸。如果視圖的autoresizesSubViews屬性聲明被設(shè)置為YES,其子視圖會(huì)根據(jù)autoresizingMask屬性的值自動(dòng)進(jìn)行尺寸調(diào)整
@property(nonatomic) BOOL              autoresizesSubviews; // default is YES. if set, subviews are adjusted according to their autoresizingMask if self.bounds changes
// 設(shè)置視圖的自動(dòng)尺寸調(diào)整行為的方法是通過(guò)OR操作符講期望的自定尺寸調(diào)整常量連接起來(lái)。并將結(jié)果賦值給視圖的autoresizingMask屬性。比如要使一個(gè)視圖和其父視圖左下角的相對(duì)位置保持不變可以加入U(xiǎn)IViewAutoresizingFlexibleRightMargin
@property(nonatomic) UIViewAutoresizing autoresizingMask;    // simple resize. default is UIViewAutoresizingNone
// 計(jì)算并且返回一個(gè)最適應(yīng)接收子視圖的大小
- (CGSize)sizeThatFits:(CGSize)size;     // return 'best' size to fit given size. does not actually resize view. Default is return existing view size
//移動(dòng)并調(diào)整子視圖的大小
- (void)sizeToFit;                       // calls sizeThatFits: with current view bounds and changes bounds size.

@end

@interface UIView(UIViewHierarchy)
//父View
@property(nonatomic,readonly) UIView      *superview;
//子view 子控件的子控件并不在里面
@property(nonatomic,readonly,copy) NSArray *subviews;
//窗口
@property(nonatomic,readonly) UIWindow    *window;
//將當(dāng)前視圖從父視圖和窗口移除,并且把他的響應(yīng)事件的響應(yīng)鏈移除
- (void)removeFromSuperview;
//指定索引插入視圖
- (void)insertSubview:(UIView *)view atIndex:(NSInteger)index;
//交換指定索引的兩個(gè)View的位置
- (void)exchangeSubviewAtIndex:(NSInteger)index1 withSubviewAtIndex:(NSInteger)index2;
//視圖的添加都是以棧的方式,先進(jìn)先出
//添加一個(gè)子控件(新添加的控件默認(rèn)都在subviews數(shù)組的后面,新添加的控件默認(rèn)都顯示在最上面\最頂部)
- (void)addSubview:(UIView *)view;
//添加一個(gè)子控件(被擋在siblingSubview下面)
- (void)insertSubview:(UIView *)view belowSubview:(UIView *)siblingSubview;
//添加一個(gè)子控件(蓋在siblingSubview上面)
- (void)insertSubview:(UIView *)view aboveSubview:(UIView *)siblingSubview;
//將某個(gè)子控件拉到最上面(最頂部)來(lái)顯示
- (void)bringSubviewToFront:(UIView *)view;
//將某個(gè)子控件拉到最下面(最底部)來(lái)顯示
- (void)sendSubviewToBack:(UIView *)view;
/***系統(tǒng)自動(dòng)調(diào)用(留給子類(lèi)去實(shí)現(xiàn))***/
//通知視圖已經(jīng)添加子視圖 默認(rèn)不執(zhí)行任何操作,子類(lèi)可以重寫(xiě)
- (void)didAddSubview:(UIView *)subview;
//通知視圖某個(gè)子視圖即將被移除 默認(rèn)不執(zhí)行任何操作 子類(lèi)可以重寫(xiě)
- (void)willRemoveSubview:(UIView *)subview;
//通知即將移動(dòng)到新的父視圖中
- (void)willMoveToSuperview:(UIView *)newSuperview;
//通知已經(jīng)到新父視圖
- (void)didMoveToSuperview;
//通知即將已移動(dòng)到新的窗口
- (void)willMoveToWindow:(UIWindow *)newWindow;
//通知已經(jīng)移動(dòng)到新的窗口
- (void)didMoveToWindow;
/***系統(tǒng)自動(dòng)調(diào)用***/
//是不是view的子控件或者子控件的子空間(是否為view的后代)
- (BOOL)isDescendantOfView:(UIView *)view;  // returns YES for self.
//通過(guò)tag獲得對(duì)應(yīng)的子控件(也可以是子控件的子控件)
- (UIView *)viewWithTag:(NSInteger)tag;     // recursive search. includes self
/***********布局*********/
// Allows you to perform layout before the drawing cycle happens. -layoutIfNeeded forces layout early
//使當(dāng)前的layout棄用當(dāng)收到并且觸發(fā)一個(gè)layout更新在下一個(gè)更新循環(huán)中 進(jìn)行標(biāo)記
- (void)setNeedsLayout;
//立刻layout 一般和上面的setNeedsLayout配合使用
- (void)layoutIfNeeded;
/***系統(tǒng)自動(dòng)調(diào)用(留給子類(lèi)去實(shí)現(xiàn))***/
//控件的frame,約束發(fā)生改變的時(shí)候就會(huì)調(diào)用,一般在這里重寫(xiě)布局子控件的位置和尺寸
//重寫(xiě)了這個(gè)方法后一定要調(diào)用[super 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.
/*
 layoutSubviews在以下情況下會(huì)被調(diào)用:
 1、init初始化不會(huì)觸發(fā)layoutSubviews ,  但 initWithFrame 進(jìn)行初始化時(shí),當(dāng)rect的值不為CGRectZero時(shí),也會(huì)觸發(fā).
 2、addSubview會(huì)觸發(fā)layoutSubviews.
 3、設(shè)置view的Frame會(huì)觸發(fā)layoutSubviews,當(dāng)然前提是frame的值設(shè)置前后發(fā)生了變化.
 4、滾動(dòng)一個(gè)UIScrollView會(huì)觸發(fā)layoutSubviews.
 5、旋轉(zhuǎn)Screen會(huì)觸發(fā)父UIView上的layoutSubviews事件.
 6、改變一個(gè)UIView大小的時(shí)候也會(huì)觸發(fā)父UIView上的layoutSubviews事件.
 [1]、layoutSubviews對(duì)subviews重新布局
 [2]、layoutSubviews方法調(diào)用先于drawRect
 [3]、setNeedsLayout在receiver標(biāo)上一個(gè)需要被重新布局的標(biāo)記,在系統(tǒng)runloop的下一個(gè)周期自動(dòng)調(diào)用layoutSubviews
 [4]、layoutIfNeeded方法如其名,UIKit會(huì)判斷該receiver是否需要layout
 [5]、layoutIfNeeded遍歷的不是superview鏈,應(yīng)該是subviews鏈
 */

/* -layoutMargins returns a set of insets from the edge of the view's bounds that denote a default spacing for laying out content.
 If preservesSuperviewLayoutMargins is YES, margins cascade down the view tree, adjusting for geometry offsets, so that setting
 the left value of layoutMargins on a superview will affect the left value of layoutMargins for subviews positioned close to the
 left edge of their superview's bounds
 If your view subclass uses layoutMargins in its layout or drawing, override -layoutMarginsDidChange in order to refresh your
 view if the margins change.
 On iOS 11.0 and later, please support both user interface layout directions by setting the directionalLayoutMargins property
 instead of the layoutMargins property. After setting the directionalLayoutMargins property, the values in the left and right
 fields of the layoutMargins property will depend on the user interface layout direction.
 */
//iOS8之后可以用 可以使用layoutMargins定義view之間的間距 這個(gè)屬性只對(duì)autolayout布局生效
@property (nonatomic) UIEdgeInsets layoutMargins NS_AVAILABLE_IOS(8_0);

/* directionalLayoutMargins.leading is used on the left when the user interface direction is LTR and on the right for RTL.
 Vice versa for directionalLayoutMargins.trailing.
 */
@property (nonatomic) NSDirectionalEdgeInsets directionalLayoutMargins API_AVAILABLE(ios(11.0),tvos(11.0));

//這個(gè)屬性默認(rèn)是NO 如果把它設(shè)置為YES layoutMargins會(huì)根據(jù)屏幕中相關(guān)view的布局而改變
@property (nonatomic) BOOL preservesSuperviewLayoutMargins NS_AVAILABLE_IOS(8_0); // default is NO - set to enable pass-through or cascading behavior of margins from this view’s parent to its children

@property (nonatomic) BOOL insetsLayoutMarginsFromSafeArea API_AVAILABLE(ios(11.0),tvos(11.0));  // Default: YES // 默認(rèn)按照safeArea insets

//在改變view的layoutMargins這個(gè)屬性時(shí),會(huì)觸發(fā)這個(gè)方法,我們?cè)谧约旱膙iew里面可以重寫(xiě)這個(gè)方法來(lái)捕獲layoutMargins的變化。我們可以在這個(gè)方法中觸發(fā)drawing和layout的update
- (void)layoutMarginsDidChange NS_AVAILABLE_IOS(8_0);

/*safeAreaInsets 也就是 iPhoneX 的安全區(qū)域*/
@property (nonatomic,readonly) UIEdgeInsets safeAreaInsets API_AVAILABLE(ios(11.0),tvos(11.0));
/*當(dāng)safeAreaInsets改變時(shí)會(huì)調(diào)用*/
- (void)safeAreaInsetsDidChange API_AVAILABLE(ios(11.0),tvos(11.0));

/* The edges of this guide are constrained to equal the edges of the view inset by the layoutMargins
 */
@property(readonly,strong) UILayoutGuide *layoutMarginsGuide NS_AVAILABLE_IOS(9_0);

/// This content guide provides a layout area that you can use to place text and related content whose width should generally be constrained to a size that is easy for the user to read. This guide provides a centered region that you can place content within to get this behavior for this view.
@property (nonatomic, readonly, strong) UILayoutGuide *readableContentGuide  NS_AVAILABLE_IOS(9_0);

/* The top of the safeAreaLayoutGuide indicates the unobscured top edge of the view (e.g, not behind
 the status bar or navigation bar, if present). Similarly for the other edges.
 */
@property(nonatomic,readonly,strong) UILayoutGuide *safeAreaLayoutGuide API_AVAILABLE(ios(11.0),tvos(11.0));
@end

@interface UIView(UIViewRendering)
/*
 drawRect是對(duì)receiver的重繪
 setNeedDisplay在receiver標(biāo)上一個(gè)需要被重新繪圖的標(biāo)記,在下一個(gè)draw周期自動(dòng)重繪,iphone device的刷新頻率是60hz,也就是1/60秒后重繪
 */
//渲染 重寫(xiě)此方法 執(zhí)行重繪
- (void)drawRect:(CGRect)rect;
//需要重新渲染 標(biāo)記為需要重繪 異步調(diào)用drawRect
- (void)setNeedsDisplay;
//需要重新渲染在某一塊區(qū)域
- (void)setNeedsDisplayInRect:(CGRect)rect;


//YES:超出控件邊框范圍的內(nèi)容都剪掉
@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 UI_APPEARANCE_SELECTOR; // default is nil. Can be useful with the appearance proxy on custom UIView subclasses.
//透明度(0.0~1.0)
@property(nonatomic)                 CGFloat          alpha;                      // animatable. default is 1.0
//YES:不透明 NO:透明
/*
 決定該消息接收者(UIView instance)是否讓其視圖不透明,用處在于給繪圖系統(tǒng)提供一個(gè)性能優(yōu)化開(kāi)關(guān)。
 insertDemoTwo.opaque = NO;
 該值為YES, 那么繪圖在繪制該視圖的時(shí)候把整個(gè)視圖當(dāng)作不透明對(duì)待。優(yōu)化繪圖過(guò)程并提升系統(tǒng)性能;為了性能方面的考量,默認(rèn)被置為YES。
 該值為NO,,不去做優(yōu)化操作。
 一個(gè)不透明視圖需要整個(gè)邊界里面的內(nèi)容都是不透明?;谶@個(gè)原因,opaque設(shè)置為YES,要求對(duì)應(yīng)的alpha必須為1.0。如果一個(gè)UIView實(shí)例opaque被設(shè)置為YES, 而同時(shí)它又沒(méi)有完全填充它的邊界(bounds),或者它包含了整個(gè)或部分的透明的內(nèi)容視圖,那么將會(huì)導(dǎo)致未知的結(jié)果。
 因此,如果視圖部分或全部支持透明,那么你必須把opaque這個(gè)值設(shè)置為NO.
 */
@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

/*YES:自動(dòng)的清除之前的渲染(繪制前是否清屏)  NO:不自動(dòng)清除   default is YES
 insertDemoOne.clearsContextBeforeDrawing = YES;
 提高描畫(huà)性能(特別是在滾動(dòng)過(guò)程)的另一個(gè)方法是將視圖的clearsContextBeforeDrawing屬性設(shè)置為NO。當(dāng)這個(gè)屬性被設(shè)置為YES時(shí),UIKIt會(huì)在調(diào)用drawRect:方法之前,把即將被該方法更新的區(qū)域填充為透明的黑色。將這個(gè)屬性設(shè)置為NO可以取消相應(yīng)的填充操作,而由應(yīng)用程序負(fù)責(zé)完全重畫(huà)傳給drawRect:方法的更新矩形中的部。這樣的優(yōu)化在滾動(dòng)過(guò)程中通常是一個(gè)好的折衷。*/
@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:隱藏 NO:顯示
@property(nonatomic,getter=isHidden) BOOL              hidden;                     // default is NO. doesn't check superviews
//內(nèi)容模式主要用于指定控件內(nèi)容(注意不是子控件)如何填充,一般UIImageView經(jīng)常使用,默認(rèn)為UIViewContentModeScaleToFill
@property(nonatomic)                 UIViewContentMode     contentMode;                // default is UIViewContentModeScaleToFill
/*http://blog.csdn.net/andyddd/article/details/7574885//視圖拉伸和縮略 (0.0-1.0之間)iOS6.0棄用 被-[UIImage resizableImageWithCapInsets:]代替  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)];
 當(dāng)demo.png大于imageDemo的大小時(shí),就縮小。
 當(dāng)demo.png小于imageDemo的大小時(shí),就放大。*/
@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.
//遮罩View
@property(nonatomic,retain)          UIView          *maskView NS_AVAILABLE_IOS(8_0);

/*
 -tintColor always returns a color. The color returned is the first non-default value in the receiver's superview chain (starting with itself).
 If no non-default value is found, a system-defined color is returned.
 If this view's -tintAdjustmentMode returns Dimmed, then the color that is returned for -tintColor will automatically be dimmed.
 If your view subclass uses tintColor in its rendering, override -tintColorDidChange in order to refresh the rendering if the color changes.
 */
//色調(diào)顏色
@property(nonatomic,retain) UIColor *tintColor NS_AVAILABLE_IOS(7_0);

/*
 -tintAdjustmentMode always returns either UIViewTintAdjustmentModeNormal or UIViewTintAdjustmentModeDimmed. The value returned is the first non-default value in the receiver's superview chain (starting with itself).
 If no non-default value is found, UIViewTintAdjustmentModeNormal is returned.
 When tintAdjustmentMode has a value of UIViewTintAdjustmentModeDimmed for a view, the color it returns from tintColor will be modified to give a dimmed appearance.
 When the tintAdjustmentMode of a view changes (either the view's value changing or by one of its superview's values changing), -tintColorDidChange will be called to allow the view to refresh its rendering.
 */
//色調(diào)調(diào)整模式
@property(nonatomic) UIViewTintAdjustmentMode tintAdjustmentMode NS_AVAILABLE_IOS(7_0);

/*
 The -tintColorDidChange message is sent to appropriate subviews of a view when its tintColor is changed by client code or to subviews in the view hierarchy of a view whose tintColor is implicitly changed when its superview or tintAdjustmentMode changes.
 */
//當(dāng)tintColor屬性改變時(shí)會(huì)觸發(fā)方法的調(diào)用 iOS7之后可用
- (void)tintColorDidChange NS_AVAILABLE_IOS(7_0);

@end

@interface UIView(UIViewAnimation)
//類(lèi)方法  開(kāi)始一個(gè)動(dòng)畫(huà) 4.0以后不推薦使用
+ (void)beginAnimations:(NSString *)animationID context:(void *)context;  // additional context info passed to will start/did stop selectors. begin/commit can be nested
//結(jié)束動(dòng)畫(huà) 類(lèi)似數(shù)據(jù)庫(kù)的事物處理
+ (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.
//設(shè)置動(dòng)畫(huà)委托
+ (void)setAnimationDelegate:(id)delegate;                          // default = nil
//當(dāng)動(dòng)畫(huà)執(zhí)行結(jié)束時(shí) 執(zhí)行selector
+ (void)setAnimationWillStartSelector:(SEL)selector;                // default = NULL. -animationWillStart:(NSString *)animationID context:(void *)context
+ (void)setAnimationDidStopSelector:(SEL)selector;                  // default = NULL. -animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context
//設(shè)置動(dòng)畫(huà)時(shí)間  時(shí)間參數(shù)為double類(lèi)型 默認(rèn)是0.2秒
+ (void)setAnimationDuration:(NSTimeInterval)duration;              // default = 0.2
//設(shè)置動(dòng)畫(huà)延遲時(shí)間
+ (void)setAnimationDelay:(NSTimeInterval)delay;                    // default = 0.0
//設(shè)置在動(dòng)畫(huà)塊內(nèi)部動(dòng)畫(huà)屬性改變的開(kāi)始時(shí)間
+ (void)setAnimationStartDate:(NSDate *)startDate;                  // default = now ([NSDate date])
//設(shè)置動(dòng)畫(huà)的旋轉(zhuǎn)曲度變化
+ (void)setAnimationCurve:(UIViewAnimationCurve)curve;              // default = UIViewAnimationCurveEaseInOut
//設(shè)置動(dòng)畫(huà)在動(dòng)畫(huà)模塊中重復(fù)次數(shù)
+ (void)setAnimationRepeatCount:(float)repeatCount;                 // default = 0.0.  May be fractional
//設(shè)置動(dòng)畫(huà)塊中的動(dòng)畫(huà)效果是否自動(dòng)播放
+ (void)setAnimationRepeatAutoreverses:(BOOL)repeatAutoreverses;    // default = NO. used if repeat count is non-zero
//設(shè)置動(dòng)畫(huà)是否從當(dāng)前狀態(tài)開(kāi)始播放
+ (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).
/* 在動(dòng)畫(huà)塊設(shè)置過(guò)渡效果 transition把一個(gè)過(guò)渡效果應(yīng)用到視圖中  view需要過(guò)渡的視圖對(duì)象  cache
如果是YES,那么在開(kāi)始和結(jié)束圖片視圖渲染一次并在動(dòng)畫(huà)中創(chuàng)建幀;否則,視圖將會(huì)在每一幀都渲染。例如緩存,你不需要在視圖轉(zhuǎn)變中不停的更新,你只需要等到轉(zhuǎn)換完成再去更新視圖。
1、開(kāi)始一個(gè)動(dòng)畫(huà)塊。
2、在容器視圖中設(shè)置轉(zhuǎn)換。
3、在容器視圖中移除子視圖。
4、在容器視圖中添加子視圖。
5、結(jié)束動(dòng)畫(huà)塊。
 */
+ (void)setAnimationTransition:(UIViewAnimationTransition)transition forView:(UIView *)view cache:(BOOL)cache;  // current limitation - only one per begin/commit block
//設(shè)置是否開(kāi)啟動(dòng)畫(huà) 默認(rèn)YES
+ (void)setAnimationsEnabled:(BOOL)enabled;                         // ignore any attribute changes while set.
#if UIKIT_DEFINE_AS_PROPERTIES
@property(class, nonatomic, readonly) BOOL areAnimationsEnabled;
#else
//驗(yàn)證動(dòng)畫(huà)是否開(kāi)啟 YES:開(kāi)啟 NO:關(guān)閉
+ (BOOL)areAnimationsEnabled;
#endif
//先檢查動(dòng)畫(huà)當(dāng)前是否啟用,然后禁止動(dòng)畫(huà),執(zhí)行block內(nèi)方法,最后重新啟用動(dòng)畫(huà)。它并不會(huì)阻塞基于CoreAnimation的動(dòng)畫(huà)
+ (void)performWithoutAnimation:(void (NS_NOESCAPE ^)(void))actionsWithoutAnimation NS_AVAILABLE_IOS(7_0);

#if UIKIT_DEFINE_AS_PROPERTIES
@property(class, nonatomic, readonly) NSTimeInterval inheritedAnimationDuration NS_AVAILABLE_IOS(9_0);
#else
+ (NSTimeInterval)inheritedAnimationDuration NS_AVAILABLE_IOS(9_0);
#endif

@end

@interface UIView(UIViewAnimationWithBlocks)
//動(dòng)畫(huà)效果處理塊 duration動(dòng)畫(huà)時(shí)間 delay延遲時(shí)間 options動(dòng)畫(huà)參數(shù) animations動(dòng)畫(huà)效果塊 可以設(shè)置屬性如下:frame bounds center
//transform alpha backgroundColor contentStretch  completion完成后需要做的操作
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion NS_AVAILABLE_IOS(4_0);
//沒(méi)有延遲時(shí)間 沒(méi)有動(dòng)畫(huà)參數(shù) options默認(rèn)為0
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion NS_AVAILABLE_IOS(4_0); // delay = 0.0, options = 0
//動(dòng)畫(huà)效果處理塊 delay = 0.0, options = 0, completion = NULL
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations NS_AVAILABLE_IOS(4_0); // delay = 0.0, options = 0, completion = NULL

/* Performs `animations` using a timing curve described by the motion of a spring. When `dampingRatio` is 1, the animation will smoothly decelerate to its final model values without oscillating. Damping ratios less than 1 will oscillate more and more before coming to a complete stop. You can use the initial spring velocity to specify how fast the object at the end of the simulated spring was moving before it was attached. It's a unit coordinate system, where 1 is defined as travelling the total animation distance in a second. So if you're changing an object's position by 200pt in this animation, and you want the animation to behave as if the object was moving at 100pt/s before the animation started, you'd pass 0.5. You'll typically want to pass 0 for the velocity. */
//參考 http://www.tuicool.com/articles/ZR7nYv  http://www.woshipm.com/ucd/85600.html
// Spring(彈簧) Animation的API 比一般動(dòng)畫(huà)多了兩個(gè)參數(shù) usingSpringWithDamping(范圍為0.0f~1.0f),數(shù)值越小彈簧的震動(dòng)的效果越明顯
// initialSpringVelocity 表示初始速度,數(shù)值越大一開(kāi)始移動(dòng)越快
// dampingRatio 設(shè)置彈簧的阻尼比例
// velocity 設(shè)置彈簧的最初速度
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay usingSpringWithDamping:(CGFloat)dampingRatio initialSpringVelocity:(CGFloat)velocity options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion NS_AVAILABLE_IOS(7_0);



/* [UIView transitionWithView:_redView
 duration:2.0
 options:UIViewAnimationOptionTransitionCurlDown
 animations:^{
 [_blackView removeFromSuperview];
 [_redView addSubview:_blackView];
 } completion:^(BOOL finished) {
 _redView.backgroundColor = [UIColor brownColor];
 }];***/
//國(guó)度動(dòng)畫(huà)效果塊
+ (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion NS_AVAILABLE_IOS(4_0);

//視圖之間切換的國(guó)度動(dòng)畫(huà)效果塊
+ (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

/* Performs the requested system-provided animation on one or more views. Specify addtional animations in the parallelAnimations block. These additional animations will run alongside the system animation with the same timing and duration that the system animation defines/inherits. Additional animations should not modify properties of the view on which the system animation is being performed. Not all system animations honor all available options.
 */
//在一組視圖上執(zhí)行指定的系統(tǒng)動(dòng)畫(huà),并可以并行自定義動(dòng)畫(huà)。其中parallelAnimations就是與系統(tǒng)動(dòng)畫(huà)并行的自定義動(dòng)畫(huà)
+ (void)performSystemAnimation:(UISystemAnimation)animation onViews:(NSArray *)views options:(UIViewAnimationOptions)options animations:(void (^)(void))parallelAnimations completion:(void (^)(BOOL finished))completion NS_AVAILABLE_IOS(7_0);

@end

@interface UIView (UIViewKeyframeAnimations)
/***********
 [UIViewanimateKeyframesWithDuration:2.0delay:0options:UIViewKeyframeAnimationOptionRepeatanimations:^{
 
 _blackView.frame = CGRectMake(30, 30, 50, 50);
 [UIView addKeyframeWithRelativeStartTime:0.5 relativeDuration:0 animations:^{
 _redView.frame = CGRectMake(50, 50, 50, 50);
 }];
 
 
 } completion:^(BOOL finished) {
 
 _redView.frame= CGRectMake(50, 50, 100, 100);;
 _blackView.frame = CGRectMake(30, 30, 80, 80);
 
 }];
 
 */

// 為當(dāng)前視圖創(chuàng)建一個(gè)可以用于設(shè)置基本關(guān)鍵幀動(dòng)畫(huà)的block對(duì)象從IOS7開(kāi)始使用
// 這里說(shuō)一下參數(shù),第一個(gè)frameStartTime其實(shí)是個(gè)倍數(shù)從0到1,假設(shè)一個(gè)動(dòng)畫(huà)持續(xù)的時(shí)間是2秒
// 設(shè)置frameStartTime為0.5,那么后面設(shè)置的動(dòng)畫(huà),將會(huì)在整體動(dòng)畫(huà)執(zhí)行1秒后開(kāi)始執(zhí)行
// 第二個(gè)參數(shù)frameDuration同第一個(gè),是指動(dòng)畫(huà)持續(xù)時(shí)間
// 第四個(gè)是一個(gè)block對(duì)象,里面就是你設(shè)置的所要執(zhí)行的動(dòng)畫(huà),無(wú)參數(shù)和返回值
// 這個(gè)方法可以結(jié)合  + (Class)layerClass 使用
+ (void)animateKeyframesWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewKeyframeAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion NS_AVAILABLE_IOS(7_0);

// 指定一個(gè)關(guān)鍵幀的單個(gè)貞的時(shí)間和動(dòng)畫(huà) iOS7后可用
// frameStartTime是一個(gè)倍數(shù)從0到1,假設(shè)一個(gè)動(dòng)畫(huà)持續(xù)的時(shí)間是2秒 設(shè)置frameStartTime為0.5那么后面設(shè)置的動(dòng)畫(huà)將會(huì)在整體動(dòng)畫(huà)執(zhí)行1秒后開(kāi)始
// frameDuration是指動(dòng)畫(huà)持續(xù)時(shí)間
+ (void)addKeyframeWithRelativeStartTime:(double)frameStartTime relativeDuration:(double)frameDuration animations:(void (^)(void))animations NS_AVAILABLE_IOS(7_0); // start time and duration are values between 0.0 and 1.0 specifying time and duration relative to the overall time of the keyframe animation

@end

@interface UIView (UIViewGestureRecognizers)

@property(nonatomic,copy) NSArray *gestureRecognizers NS_AVAILABLE_IOS(3_2);//手勢(shì)識(shí)別器
/*
 UIKit 中UIGestureRecognizer類(lèi)的子類(lèi)系列如下:
 UITapGestureRecognizer – “輕擊”手勢(shì)??梢耘渲脼椤皢螕簟焙汀斑B擊”的識(shí)別。
 UIPinchGestureRecognizer –“捏合”手勢(shì)。該手勢(shì)通常用于縮放視圖或改變可視組件的大小。
 UIPanGestureRecognizer – “平移”手勢(shì)。識(shí)別拖拽或移動(dòng)動(dòng)作。
 UISwipeGestureRecognizer – “輕掃”手勢(shì)。當(dāng)用戶(hù)從屏幕上劃過(guò)時(shí)識(shí)別為該手勢(shì)。可以指定該動(dòng)作的方向(上、下、左、右)。
 UIRotationGestureRecognizer – “轉(zhuǎn)動(dòng)”手勢(shì)。用戶(hù)兩指在屏幕上做相對(duì)環(huán)形運(yùn)動(dòng)。
 UILongPressGestureRecognizer – “長(zhǎng)按”手勢(shì)。使用1指或多指觸摸屏幕并保持一定時(shí)間。
 */
//給VIew添加一個(gè)手勢(shì)
- (void)addGestureRecognizer:(UIGestureRecognizer*)gestureRecognizer NS_AVAILABLE_IOS(3_2);
//移除VIew的手勢(shì)
- (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
/*
 手勢(shì)識(shí)別處理方式在gesture recognizer視圖轉(zhuǎn)出《UIGestureRecognizerStatePossible》狀態(tài)時(shí)調(diào)用,
 如果返回NO,則轉(zhuǎn)換到《UIGestureRecognizerStateFailed》;
 如果返回YES,則繼續(xù)識(shí)別觸摸序列.(默認(rèn)情況下為YES)。
 [insertDemoOne gestureRecognizerShouldBegin:demoGesture];
 */
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer NS_AVAILABLE_IOS(6_0);

@end

@interface UIView (UIViewMotionEffects)

/*! Begins applying `effect` to the receiver. The effect's emitted keyPath/value pairs will be
 applied to the view's presentation layer.
 
 Animates the transition to the motion effect's values using the present UIView animation
 context. */
/*
 當(dāng)你打開(kāi)裝有iOS7以上的iPhone主屏,默認(rèn)的背景是一幅藍(lán)色的星空?qǐng)D片。當(dāng)上下左右翻轉(zhuǎn)iPhone時(shí),有趣的效果將會(huì)出現(xiàn),星空背景也會(huì)沿著各個(gè)方向發(fā)生位移,這與主屏上的各個(gè)App Icon形成了一種獨(dú)特的視差效果。
 //UIMotionEffect
 1. UIInterpolatingMotionEffect
 
 UIInterpolatingMotionEffect是UIMotionEffect的子類(lèi),雖然擴(kuò)展也不復(fù)雜,提供的方法也很簡(jiǎn)單,但在很多場(chǎng)景下可以比較直接和方便的滿(mǎn)足我們的需求。
 
 它有4個(gè)property:
 
 1.keyPath,左右翻轉(zhuǎn)屏幕將要影響到的屬性,比如center.x。
 
 2.type(UIInterpolatingMotionEffectType類(lèi)型),觀(guān)察者視角,也就是屏幕傾斜的方式,目前區(qū)分水平和垂直兩種方式。
 
 3&4.minimumRelativeValue和maximumRelativeValue,keyPath對(duì)應(yīng)的值的變化范圍,注意這個(gè)是id類(lèi)型。min對(duì)應(yīng)最小的offset,max對(duì)應(yīng)最大的offset。
 
 UIInterpolatingMotionEffect * xEffect = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.x" type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis];
 xEffect.minimumRelativeValue =  [NSNumber numberWithFloat:-40.0];
 xEffect.maximumRelativeValue = [NSNumber numberWithFloat:40.0];
 [targetView addMotionEffect:xEffect];
 參考自http://www.cocoachina.com/ios/20150121/10967.html
 */
- (void)addMotionEffect:(UIMotionEffect *)effect NS_AVAILABLE_IOS(7_0);

/*! Stops applying `effect` to the receiver. Any affected presentation values will animate to
 their post-removal values using the present UIView animation context. */
//移除一個(gè)UIMotionEffect
- (void)removeMotionEffect:(UIMotionEffect *)effect NS_AVAILABLE_IOS(7_0);
//包含的UIMotionEffect
@property (copy, nonatomic) NSArray *motionEffects NS_AVAILABLE_IOS(7_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);

//視圖布局添加一個(gè)約束
- (void)addConstraint:(NSLayoutConstraint *)constraint NS_AVAILABLE_IOS(6_0); // This method will be deprecated in a future release and should be avoided.  Instead, set NSLayoutConstraint's active property to YES.
//視圖布局上添加多個(gè)約束
- (void)addConstraints:(NSArray *)constraints NS_AVAILABLE_IOS(6_0); // This method will be deprecated in a future release and should be avoided.  Instead use +[NSLayoutConstraint activateConstraints:].
//移除視圖布局一個(gè)約束
- (void)removeConstraint:(NSLayoutConstraint *)constraint NS_AVAILABLE_IOS(6_0); // This method will be deprecated in a future release and should be avoided.  Instead set NSLayoutConstraint's active property to NO.
//移除視圖布局上多個(gè)約束
- (void)removeConstraints:(NSArray *)constraints NS_AVAILABLE_IOS(6_0); // This method will be deprecated in a future release and should be avoided.  Instead use +[NSLayoutConstraint deactivateConstraints:].
@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)
//調(diào)用新的視圖布局自動(dòng)觸發(fā),更新視圖布局上的約束
- (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.
//更新自定義視圖布局 重寫(xiě)這個(gè)方法去適應(yīng)特殊的約束在更新約束期間
- (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);
//設(shè)置視圖布局是否需要更新約束
- (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.
 */
//標(biāo)示是否自動(dòng)遵循視圖布局約束 默認(rèn)是YES
- (BOOL)translatesAutoresizingMaskIntoConstraints NS_AVAILABLE_IOS(6_0); // Default YES
//設(shè)置是否自動(dòng)遵循視圖布局約束
- (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.
 */
// AutoLayout并不會(huì)直接操作View的Frame,但是視圖的alignment rect是起作用的。視圖的默認(rèn)alignmentRectInsets值就是(0,0,0,0)。
// 我們可以簡(jiǎn)單的對(duì)當(dāng)前View設(shè)置用來(lái)布局的矩形,比如:
// 我們有一個(gè)自定義icon類(lèi)型的Button,但是icon的大小比我們期望點(diǎn)擊的Button區(qū)域要小。這個(gè)時(shí)候我們可以重寫(xiě)alignmentRectInsets,把icon放在適當(dāng)?shù)奈恢谩?// 大多數(shù)情況下重寫(xiě)alignmentRectInsets這個(gè)方法可以滿(mǎn)足我們的工作。如果需要更加個(gè)性化的修改,我們可以重寫(xiě)alignmentRectForFrame和frameForAlignmentRect這兩個(gè)方法。比如我們不想減去視圖固定的Insets,而是需要基于當(dāng)前frame修改alignment rect。在重寫(xiě)這兩個(gè)方法時(shí),我們應(yīng)該確保是互為可逆的。
- (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:.
 */
#if UIKIT_DEFINE_AS_PROPERTIES
@property(nonatomic, readonly) UIEdgeInsets alignmentRectInsets NS_AVAILABLE_IOS(6_0);
#else
- (UIEdgeInsets)alignmentRectInsets NS_AVAILABLE_IOS(6_0);
#endif

/* 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.
 */
// 我們?cè)谑褂貌季旨s束中NSLayoutAttributeBaseline屬性時(shí),系統(tǒng)會(huì)默認(rèn)返回當(dāng)前視圖的底部作為baseline。我們可以重寫(xiě)上述方法,但必須返回的是當(dāng)前視圖中的子視圖
- (UIView *)viewForBaselineLayout NS_DEPRECATED_IOS(6_0, 9_0, "Override -viewForFirstBaselineLayout or -viewForLastBaselineLayout as appropriate, instead") __TVOS_PROHIBITED;


/* -viewForFirstBaselineLayout is called by the constraints system when interpreting
 the firstBaseline attribute for a view.
 For complex custom UIView subclasses, override this method to return the text-based
 (i.e., UILabel or non-scrollable UITextView) descendant of the receiver whose first baseline
 is appropriate for alignment.
 UIView's implementation returns [self viewForLastBaselineLayout], so if the same
 descendant is appropriate for both first- and last-baseline layout you may override
 just -viewForLastBaselineLayout.
 */
@property(readonly,strong) UIView *viewForFirstBaselineLayout NS_AVAILABLE_IOS(9_0);

/* -viewForLastBaselineLayout is called by the constraints system when interpreting
 the lastBaseline attribute for a view.
 For complex custom UIView subclasses, override this method to return the text-based
 (i.e., UILabel or non-scrollable UITextView) descendant of the receiver whose last baseline
 is appropriate for alignment.
 UIView's implementation returns self.
 */
@property(readonly,strong) UIView *viewForLastBaselineLayout NS_AVAILABLE_IOS(9_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
#if UIKIT_DEFINE_AS_PROPERTIES
@property(nonatomic, readonly) CGSize intrinsicContentSize NS_AVAILABLE_IOS(6_0);
#else
/* 通過(guò)重寫(xiě)intrinsicContentSize可以設(shè)置當(dāng)前視圖顯示特定內(nèi)容時(shí)的大小。比如我們?cè)O(shè)置一個(gè)自定義View,View里面包含一個(gè)Label顯示文字,為了設(shè)置當(dāng)前View在不同Size Class下內(nèi)容的大小,我們可以這樣:
- (CGSize)intrinsicContentSize
{
    CGSize size = [label intrinsicContentSize];
    if (self.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassCompact) {
        size.width += 4.0f;
    } else {
        size.width += 40.0f;
    }
    if (self.traitCollection.verticalSizeClass == UIUserInterfaceSizeClassCompact) {
        size.height += 4.0;
    } else {
        size.height += 40.0;
    }
    return size;
}
 */

- (CGSize)intrinsicContentSize NS_AVAILABLE_IOS(6_0);
#endif
/*
//當(dāng)有任何會(huì)影響這個(gè)Label內(nèi)容大小的事件發(fā)生時(shí),我們應(yīng)該調(diào)用invalidateIntrinsicContentSize:
label.text = @"content update"
[self invalidateIntrinsicContentSize];
// 或者比如當(dāng)前視圖Size Class改變的時(shí)候
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection
{
    [super traitCollectionDidChange:previousTraitCollection];
    if ((self.traitCollection.verticalSizeClass != previousTraitCollection.verticalSizeClass)
        || (self.traitCollection.horizontalSizeClass != previousTraitCollection.horizontalSizeClass)) {
        [self invalidateIntrinsicContentSize];
    }
}
 */
- (void)invalidateIntrinsicContentSize NS_AVAILABLE_IOS(6_0); // call this when something changes that affects the intrinsicContentSize.  Otherwise UIKit won't notice that it changed.

//返回放大的視圖布局的軸線(xiàn)
- (UILayoutPriority)contentHuggingPriorityForAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);
//設(shè)置放大的視圖布局的軸線(xiàn)
- (void)setContentHuggingPriority:(UILayoutPriority)priority forAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);
//返回縮小的視圖布局的軸線(xiàn)
- (UILayoutPriority)contentCompressionResistancePriorityForAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);
//設(shè)置縮小的視圖的軸線(xiàn)
- (void)setContentCompressionResistancePriority:(UILayoutPriority)priority forAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);
/*
 上面最后四個(gè)API主要是通過(guò)修改水平或者垂直方向的優(yōu)先級(jí)來(lái)實(shí)現(xiàn)視圖是基于水平縮小(放大)還是垂直縮小(放大)。當(dāng)我們的視圖需要根據(jù)內(nèi)部?jī)?nèi)容進(jìn)行調(diào)整大小時(shí),我們應(yīng)該使用上述方法為當(dāng)前視圖設(shè)置初始值。而不應(yīng)該重寫(xiě)這幾個(gè)方法。*/
@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.
 */
// 滿(mǎn)足約束視圖的布局大小
// 下面這兩個(gè)API可以獲得當(dāng)前使用AutoLayout視圖的size。其中targetSize可以傳入U(xiǎn)ILayoutFittingCompressedSize(最小情況下可能的Size)或者UILayoutFittingExpandedSize(最大情況下可能的Size)
- (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize NS_AVAILABLE_IOS(6_0); // Equivalent to sending -systemLayoutSizeFittingSize:withHorizontalFittingPriority:verticalFittingPriority: with UILayoutPriorityFittingSizeLevel for both priorities.
//
- (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize withHorizontalFittingPriority:(UILayoutPriority)horizontalFittingPriority verticalFittingPriority:(UILayoutPriority)verticalFittingPriority NS_AVAILABLE_IOS(8_0);
@end

@interface UIView (UILayoutGuideSupport)

/* UILayoutGuide objects owned by the receiver.
 */
@property(nonatomic,readonly,copy) NSArray<__kindof UILayoutGuide *> *layoutGuides NS_AVAILABLE_IOS(9_0);

/* Adds layoutGuide to the receiver, passing the receiver in -setOwningView: to layoutGuide.
 */
- (void)addLayoutGuide:(UILayoutGuide *)layoutGuide NS_AVAILABLE_IOS(9_0);

/* Removes layoutGuide from the receiver, passing nil in -setOwningView: to layoutGuide.
 */
- (void)removeLayoutGuide:(UILayoutGuide *)layoutGuide NS_AVAILABLE_IOS(9_0);
@end

@class NSLayoutXAxisAnchor,NSLayoutYAxisAnchor,NSLayoutDimension;
@interface UIView (UIViewLayoutConstraintCreation)
/* Constraint creation conveniences. See NSLayoutAnchor.h for details.
 */
@property(readonly, strong) NSLayoutXAxisAnchor *leadingAnchor NS_AVAILABLE_IOS(9_0);
@property(readonly, strong) NSLayoutXAxisAnchor *trailingAnchor NS_AVAILABLE_IOS(9_0);
@property(readonly, strong) NSLayoutXAxisAnchor *leftAnchor NS_AVAILABLE_IOS(9_0);
@property(readonly, strong) NSLayoutXAxisAnchor *rightAnchor NS_AVAILABLE_IOS(9_0);
@property(readonly, strong) NSLayoutYAxisAnchor *topAnchor NS_AVAILABLE_IOS(9_0);
@property(readonly, strong) NSLayoutYAxisAnchor *bottomAnchor NS_AVAILABLE_IOS(9_0);
@property(readonly, strong) NSLayoutDimension *widthAnchor NS_AVAILABLE_IOS(9_0);
@property(readonly, strong) NSLayoutDimension *heightAnchor NS_AVAILABLE_IOS(9_0);
@property(readonly, strong) NSLayoutXAxisAnchor *centerXAnchor NS_AVAILABLE_IOS(9_0);
@property(readonly, strong) NSLayoutYAxisAnchor *centerYAnchor NS_AVAILABLE_IOS(9_0);
@property(readonly, strong) NSLayoutYAxisAnchor *firstBaselineAnchor NS_AVAILABLE_IOS(9_0);
@property(readonly, strong) NSLayoutYAxisAnchor *lastBaselineAnchor NS_AVAILABLE_IOS(9_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]).
 */
//獲得實(shí)體在不同方向上所有的布局約束
- (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.
 */
//可以知道當(dāng)前視圖的布局是否會(huì)有歧義。這里有一個(gè)私有API _autolayoutTrace可以獲得整個(gè)視圖樹(shù)的字符串。
- (BOOL)hasAmbiguousLayout NS_AVAILABLE_IOS(6_0);

//這個(gè)方法會(huì)隨機(jī)改變視圖的layout到另外一個(gè)有效的layout。這樣我們就可以很清楚的看到哪一個(gè)layout導(dǎo)致了整體的布局約束出現(xiàn)了錯(cuò)誤,或者我們應(yīng)該增加更多的布局約束。
- (void)exerciseAmbiguityInLayout NS_AVAILABLE_IOS(6_0);

// 我們應(yīng)該讓上面的四個(gè)方法只在DEBUG環(huán)境下被調(diào)用。
@end

/* 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 UILayoutGuide (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<__kindof NSLayoutConstraint *> *)constraintsAffectingLayoutForAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(10_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.
 */
#if UIKIT_DEFINE_AS_PROPERTIES
@property(nonatomic, readonly) BOOL hasAmbiguousLayout NS_AVAILABLE_IOS(10_0);
#else
- (BOOL)hasAmbiguousLayout NS_AVAILABLE_IOS(10_0);
#endif
@end

@interface UIView (UIStateRestoration)
//標(biāo)示是否支持保存,恢復(fù)視圖狀態(tài)信息
@property (nonatomic, copy) NSString *restorationIdentifier NS_AVAILABLE_IOS(6_0);
//保存視圖狀態(tài)相關(guān)的信息
- (void) encodeRestorableStateWithCoder:(NSCoder *)coder NS_AVAILABLE_IOS(6_0);
//恢復(fù)和保持視圖狀態(tài)相關(guān)信息
- (void) decodeRestorableStateWithCoder:(NSCoder *)coder NS_AVAILABLE_IOS(6_0);
@end

@interface UIView (UISnapshotting)
//屏幕快照
/*
 * When requesting a snapshot, 'afterUpdates' defines whether the snapshot is representative of what's currently on screen or if you wish to include any recent changes before taking the snapshot.
 
 If called during layout from a committing transaction, snapshots occurring after the screen updates will include all changes made, regardless of when the snapshot is taken and the changes are made. For example:
 
 - (void)layoutSubviews {
 UIView *snapshot = [self snapshotViewAfterScreenUpdates:YES];
 self.alpha = 0.0;
 }
 
 The snapshot will appear to be empty since the change in alpha will be captured by the snapshot. If you need to animate the view during layout, animate the snapshot instead.
 
 * Creating snapshots from existing snapshots (as a method to duplicate, crop or create a resizable variant) is supported. In cases where many snapshots are needed, creating a snapshot from a common superview and making subsequent snapshots from it can be more performant. Please keep in mind that if 'afterUpdates' is YES, the original snapshot is committed and any changes made to it, not the view originally snapshotted, will be included.
 */
/*
 http://www.csdn123.com/html/topnews201408/58/1858.htm
 http://rralun.blog.163.com/blog/static/1039042962014929111334870/
 http://www.cocoachina.com/ios/20141222/10713.html
 // 這個(gè)方法能夠高效的將當(dāng)前顯示的view截取成一個(gè)新的view.你可以用這個(gè)截取的view用來(lái)顯示.例如,也許你只想用一張截圖來(lái)做動(dòng)畫(huà),
 畢竟用原始的view做動(dòng)畫(huà)代價(jià)太高.因?yàn)槭墙厝×艘呀?jīng)存在的內(nèi)容,這個(gè)方法只能反應(yīng)出這個(gè)被截取的view當(dāng)前的狀態(tài)信息,而不能反應(yīng)這個(gè)被截取的view以后要顯示的信息.然而,不管怎么樣,調(diào)用這個(gè)方法都會(huì)比將view做成截圖來(lái)加載效率更高.*/
- (UIView *)snapshotViewAfterScreenUpdates:(BOOL)afterUpdates NS_AVAILABLE_IOS(7_0);
//縮放一個(gè)view默認(rèn)是從中心點(diǎn)進(jìn)行縮放的
- (UIView *)resizableSnapshotViewFromRect:(CGRect)rect afterScreenUpdates:(BOOL)afterUpdates withCapInsets:(UIEdgeInsets)capInsets NS_AVAILABLE_IOS(7_0);  // Resizable snapshots will default to stretching the center
// Use this method to render a snapshot of the view hierarchy into the current context. Returns NO if the snapshot is missing image data, YES if the snapshot is complete. Calling this method from layoutSubviews while the current transaction is committing will capture what is currently displayed regardless if afterUpdates is YES.
// 它允許你截取一個(gè)UIView或者其子類(lèi)中的內(nèi)容
- (BOOL)drawViewHierarchyInRect:(CGRect)rect afterScreenUpdates:(BOOL)afterUpdates NS_AVAILABLE_IOS(7_0);
//屏幕快照
@end

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容