iOS Core Animation

UIView 基本動畫

// 通過指定動畫持續時間、動畫延遲、執行動畫選項和動畫完成后回調的 Block 對象 更改一個或多個視圖的動畫。
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(4_0);

+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^ __nullable)(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)viewDidLoad {
    [super viewDidLoad];
    
    UIView *view1 = [[UIView alloc] initWithFrame:CGRectMake(22, 22, 100, 100)];
    view1.backgroundColor = [UIColor flatMintColor];
    [self.view addSubview:view1];
    
    [UIView animateWithDuration:2.0    // 動畫持續時間
                          delay:1.0    // 動畫執行的延遲時間
                        options:UIViewAnimationOptionLayoutSubviews    // 執行的動畫選項
                     animations:^{
                         // 要執行的動畫代碼
                         view1.center = self.view.center;
                     }
                     completion:^(BOOL finished) {
                         // 動畫執行完畢后的調用

                     }];
}

示例:重復動畫

- (void)viewDidLoad {
    [super viewDidLoad];
    
    UIView *view1 = [[UIView alloc] initWithFrame:CGRectMake(22, 22, 100, 100)];
    view1.backgroundColor = [UIColor flatMintColor];
    [self.view addSubview:view1];
    
    [UIView animateWithDuration:3.0
                          delay:1.0
                        options:UIViewAnimationOptionRepeat |
                                UIViewAnimationOptionAutoreverse |
                                UIViewAnimationOptionCurveEaseInOut
                     animations:^{
                         // 要執行的動畫代碼
                         view1.center = self.view.center;
                         view1.backgroundColor = [UIColor flatSkyBlueColor];
                     }
                     completion:^(BOOL finished) {
                         // 動畫執行完畢后的調用

                     }];
}

示例:旋轉動畫

[UIView animateWithDuration:0.25 animations:^{
   cell.arrow.transform = CGAffineTransformMakeRotation(M_PI);
} completion:^(BOOL finished) {

}];

示例:嵌套動畫

摘自YYText Demo

- (void)showMessage:(NSString *)msg {
    CGFloat padding = 10;
    
    YYLabel *label = [YYLabel new];
    label.text = msg;
    label.font = [UIFont systemFontOfSize:16];
    label.textAlignment = NSTextAlignmentCenter;
    label.textColor = [UIColor whiteColor];
    label.backgroundColor = [UIColor colorWithRed:0.033 green:0.685 blue:0.978 alpha:0.730];
    label.textContainerInset = UIEdgeInsetsMake(padding, padding, padding, padding);
    label.width = self.view.width;
    label.height = [msg heightForFont:label.font width:label.width] + 2 * padding;
    label.bottom = (kiOS7Later ? 64 : 0);
    [self.view addSubview:label];
    
    // 顯示label動畫
    [UIView animateWithDuration:0.3 animations:^{
        label.top = (kiOS7Later ? 64 : 0);
    } completion:^(BOOL finished) {
        
        // 嵌套動畫,2秒后隱藏label動畫
        [UIView animateWithDuration:0.2 delay:2 options:UIViewAnimationOptionCurveEaseInOut animations:^{
            label.bottom = (kiOS7Later ? 64 : 0);
        } completion:^(BOOL finished) {
            [label removeFromSuperview];
        }];
    }];
}

Spring 動畫

/* 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. 

大意:使用彈簧運動描述的時序曲線執行動畫。當 dampingRatio (阻尼比)為1時,動畫將平穩減速到其最終模型沒有振蕩。小于1的阻尼比在達到完全停止之前會越來越波動。你可以使用初始的彈簧速度來指定模擬彈簧在到達終點之前移動的速度有多快。velocity(動畫速率)是一個單位坐標系,其中1定義為在一秒鐘內移動總動畫距離。所以在動畫執行過程中,如果你想改變對象的移動距離為200pt,并且你想要動畫表現得像物體一樣 以100pt / s 的速度運動,那么你應該設置彈簧的速率為0.5。你通常想通過0的速度。*/ 
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay usingSpringWithDamping:(CGFloat)dampingRatio initialSpringVelocity:(CGFloat)velocity options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(7_0);

兩個額外參數:

  • dampingRatio:彈簧動畫中的阻尼比。相當于彈簧的硬度,數值在 0.0 到 1.0 之間,數值越小,彈簧越軟,波動幅度越大;反之相反。
  • velocity:彈簧的速率。數值越小,動力越小,彈簧的拉伸幅度就越小。反之相反。比如:總共的動畫運行距離是200 points,你希望每秒 100pt ,值為 0.5;

示例

- (void)viewDidLoad {
    [super viewDidLoad];
    
    UIView *view1 = [[UIView alloc] initWithFrame:CGRectMake(self.view.frame.size.width / 2 - 50, 22, 100, 100)];
    view1.backgroundColor = [UIColor flatMintColor];
    [self.view addSubview:view1];
    
    [UIView animateWithDuration:3.0
                          delay:1.0
         usingSpringWithDamping:0.4    // 彈簧阻尼比
          initialSpringVelocity:0.3    // 速度
                        options:UIViewAnimationOptionLayoutSubviews
                     animations:^{
                         view1.center = self.view.center;
                     }
                     completion:^(BOOL finished) {
                         
                     }];
}

Transitions 轉場動畫

常用于添加、刪除子視圖或隱藏、顯示子視圖時的動畫。

/** 為指定的容器視圖創建轉換動畫 */  
+ (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^ __nullable)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(4_0);  
  
/** 使用給定的參數在指定視圖之間創建轉換動畫 */  
+ (void)transitionFromView:(UIView *)fromView toView:(UIView *)toView duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(4_0); // toView added to fromView.superview, fromView removed from its superview

示例一:

#pragma mark - Lifecycle

- (void)viewDidLoad {
    [super viewDidLoad];
    [self.view addSubview:self.containerView];
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    [UIView transitionWithView:self.containerView
                      duration:1.0
                       options:UIViewAnimationOptionTransitionFlipFromLeft |
     UIViewAnimationOptionRepeat |
     UIViewAnimationOptionAutoreverse
                    animations:^{
                        [self.containerView addSubview:self.subView];
                    }
                    completion:^(BOOL finished) {
                        
                    }];
}

#pragma mark - Custom Accessors

- (UIView *)containerView {
    if (!_containerView) {
        _containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 250, 250)];
        _containerView.center = self.view.center;
    }
    return _containerView;
}

- (UIView *)subView {
    if (!_subView) {
        _subView = [[UIView alloc] initWithFrame:self.containerView.bounds];
        _subView.backgroundColor = [UIColor flatGreenColor];
    }
    return _subView;
}

示例二:

#pragma mark - Lifecycle

- (void)viewDidLoad {
    [super viewDidLoad];
    [self.view addSubview:self.view1];
    [self.view addSubview:self.button];
}

#pragma mark - Custom Accessors

- (UIView *)view1 {
    if (!_view1) {
        _view1 = [[UIView alloc] initWithFrame:CGRectMake(0, [UIScreen mainScreen].bounds.size.height - 450, [UIScreen mainScreen].bounds.size.width, 450)];
        _view1.backgroundColor = [UIColor flatWatermelonColor];
    }
    return _view1;
}

- (UIView *)view2 {
    if (!_view2) {
        _view2 = [[UIView alloc] initWithFrame:CGRectMake(0, [UIScreen mainScreen].bounds.size.height - 450, [UIScreen mainScreen].bounds.size.width, 450)];
        _view2.backgroundColor = [UIColor flatGreenColor];
    }
    return _view2;
}

#pragma mark - IBActions

- (void)startAnimation:(id)sender {    
    // 轉場動畫
    [UIView transitionFromView:self.view1
                        toView:self.view2
                      duration:0.25
                       options:UIViewAnimationOptionTransitionFlipFromRight
                    completion:^(BOOL finished) {
                        
                    }];
}

另外,關于 UINavigationController 的 push、pop 動畫:

天天品嘗iOS7甜點 :: Day 10 :: Custom UIViewController Transitions


Keyframe 動畫

/** UIView 的關鍵幀動畫 */
@interface UIView (UIViewKeyframeAnimations)

/** 創建一個動畫塊對象,可用于為當前視圖設置基于關鍵幀的動畫 */ 
+ (void)animateKeyframesWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewKeyframeAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(7_0);

/** 添加指定開始時間、持續時間的關鍵幀動畫(起始和持續時間是0.0和1.0之間的值) */ 
+ (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
// 開始時間和持續時間是相對于關鍵幀動畫的總時間的位于0和1之間的值 

@end

示例一:

#pragma mark - Lifecycle

- (void)viewDidLoad {
    [super viewDidLoad];
    [self.view addSubview:self.view1];
    
    [UIView animateKeyframesWithDuration:4.0
                                   delay:1.0
                                 options:UIViewKeyframeAnimationOptionRepeat
                              animations:^{
                                  
      [UIView addKeyframeWithRelativeStartTime:0.0
                              relativeDuration:0.25
                                    animations:^{
                                        self.view1.frame = CGRectMake(50, 250, 100, 100);
                                    }];
      [UIView addKeyframeWithRelativeStartTime:0.25
                              relativeDuration:0.25
                                    animations:^{
                                        self.view1.frame = CGRectMake(250, 250, 100, 100);
                                    }];
      [UIView addKeyframeWithRelativeStartTime:0.5
                              relativeDuration:0.25
                                    animations:^{
                                        self.view1.frame = CGRectMake(250, 50, 100, 100);
                                    }];
      [UIView addKeyframeWithRelativeStartTime:0.75
                              relativeDuration:0.25
                                    animations:^{
                                        self.view1.frame = CGRectMake(50, 50, 100, 100);
                                    }];
                              }
                              completion:^(BOOL finished) {
        
    }];
}

#pragma mark - Custom Accessors

- (UIView *)view1 {
    if (!_view1) {
        _view1 = [[UIView alloc] initWithFrame:CGRectMake(50, 50, 100, 100)];
        _view1.backgroundColor = [UIColor flatWatermelonColor];
    }
    return _view1;
}

關鍵幀動畫的其他示例:

天天品嘗iOS7甜點 :: Day 11 :: UIView Key-frame Animations


Layer 動畫

示例一:CABasicAnimation

CABasicAnimation *basicAnimation = [CABasicAnimation animationWithKeyPath:@"position.x"];
basicAnimation.fromValue = @10;
basicAnimation.toValue = @200;
basicAnimation.duration = 2.0;
// 在動畫執行過程中保留最后一幀
basicAnimation.fillMode = kCAFillModeForwards;
basicAnimation.removedOnCompletion = NO;
[self.view1.layer addAnimation:basicAnimation forKey:nil];

示例二:CAKeyframeAnimation

UILabel 的跑馬燈效果:

摘自:Wonderful

- (void)moveAction {
    // 以 Label 的中心點運動
    // 貝塞爾曲線 起點
    CGPoint fromPoint = CGPointMake(self.frame.size.width + self.marqueeLbl.frame.size.width/2, self.frame.size.height/2);
    // 貝塞爾曲線 終點
    CGPoint toPoint = CGPointMake(-self.marqueeLbl.frame.size.width/2, self.frame.size.height/2);
    
    self.marqueeLbl.center = fromPoint;
    UIBezierPath *movePath = [UIBezierPath bezierPath];
    [movePath moveToPoint:fromPoint];
    [movePath addLineToPoint:toPoint];
    
    // 創建動畫實例
    CAKeyframeAnimation *moveAnim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    // 設置動畫路徑
    moveAnim.path = movePath.CGPath;
    // 設置動畫時長
    moveAnim.duration = self.marqueeLbl.frame.size.width * self.speedLevel * 0.01;
    // 委托協議,動畫完成后重復該動畫
    moveAnim.delegate = self;
    // 在圖層上添加動畫
    [self.marqueeLbl.layer addAnimation:moveAnim forKey:nil];
}

#pragma mark - CAAnimationDelegate

- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
    if (flag) {
        [self moveAction];
    }
}

UIView.h 源碼解析注釋

摘自:ios開發 之 UIView詳解,部分修改。

//  UIView.h
//  UIKit
//
//  Copyright (c) 2005-2016 Apple Inc. All rights reserved.
//  Created by ZengZhiming on 2017/5/22.  
//

#import <Foundation/Foundation.h>  
#import <QuartzCore/QuartzCore.h>  
#import <UIKit/UIResponder.h>  
#import <UIKit/UIInterface.h>  
#import <UIKit/UIKitDefines.h>  
#import <UIKit/UIAppearance.h>  
#import <UIKit/UIDynamicBehavior.h>  
#import <UIKit/NSLayoutConstraint.h>  
#import <UIKit/UITraitCollection.h>  
#import <UIKit/UIFocus.h>  
  
NS_ASSUME_NONNULL_BEGIN  
  
/** 動畫的曲線枚舉 */  
typedef NS_ENUM(NSInteger, UIViewAnimationCurve) {  
    UIViewAnimationCurveEaseInOut,  //!< 慢進慢出(默認值).  
    UIViewAnimationCurveEaseIn,     //!< 慢進.  
    UIViewAnimationCurveEaseOut,    //!< 慢出.  
    UIViewAnimationCurveLinear,     //!< 勻速.  
};  
  
/** UIView 內容填充模式 */
typedef NS_ENUM(NSInteger, UIViewContentMode) {  
    UIViewContentModeScaleToFill,       //!< 縮放內容到合適比例大小.  
    UIViewContentModeScaleAspectFit,    //!< 縮放內容到合適的大小,邊界多余部分透明.  
    UIViewContentModeScaleAspectFill,   //!< 縮放內容填充到指定大小,邊界多余的部分省略.  
    UIViewContentModeRedraw,            //!< 重繪視圖邊界 (需調用 -setNeedsDisplay).  
    UIViewContentModeCenter,            //!< 視圖保持等比縮放.  
    UIViewContentModeTop,               //!< 視圖頂部對齊.  
    UIViewContentModeBottom,            //!< 視圖底部對齊.  
    UIViewContentModeLeft,              //!< 視圖左側對齊.  
    UIViewContentModeRight,             //!< 視圖右側對齊.  
    UIViewContentModeTopLeft,           //!< 視圖左上角對齊.  
    UIViewContentModeTopRight,          //!< 視圖右上角對齊.  
    UIViewContentModeBottomLeft,        //!< 視圖左下角對齊.  
    UIViewContentModeBottomRight,       //!< 視圖右下角對齊.  
};  
  
/** UIView 動畫過渡效果 */  
typedef NS_ENUM(NSInteger, UIViewAnimationTransition) {  
    UIViewAnimationTransitionNone,          //!< 無效果.  
    UIViewAnimationTransitionFlipFromLeft,  //!< 沿視圖垂直中心軸左到右移動.  
    UIViewAnimationTransitionFlipFromRight, //!< 沿視圖垂直中心軸右到左移動.  
    UIViewAnimationTransitionCurlUp,        //!< 由底部向上卷起.  
    UIViewAnimationTransitionCurlDown,      //!< 由頂部向下展開.  
};  
  
/** 自動調整大小方式 */  
typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {  
    UIViewAutoresizingNone                 = 0,     //!< 不自動調整.  
    UIViewAutoresizingFlexibleLeftMargin   = 1 << 0,//!< 自動調整與superView左邊的距離,保證與superView右邊的距離不變.  
    UIViewAutoresizingFlexibleWidth        = 1 << 1,//!< 自動調整自己的寬度,保證與superView左邊和右邊的距離不變.  
    UIViewAutoresizingFlexibleRightMargin  = 1 << 2,//!< 自動調整與superView的右邊距離,保證與superView左邊的距離不變.  
    UIViewAutoresizingFlexibleTopMargin    = 1 << 3,//!< 自動調整與superView頂部的距離,保證與superView底部的距離不變.  
    UIViewAutoresizingFlexibleHeight       = 1 << 4,//!< 自動調整自己的高度,保證與superView頂部和底部的距離不變.  
    UIViewAutoresizingFlexibleBottomMargin = 1 << 5 //!< 自動調整與superView底部的距離,也就是說,與superView頂部的距離不變.  
};  
  
/** UIView動畫選項 */  
typedef NS_OPTIONS(NSUInteger, UIViewAnimationOptions) {
    
    // ??----------------------------------------------------------------------------
    // 1.常規動畫屬性設置(可以同時選擇多個進行設置)
    UIViewAnimationOptionLayoutSubviews            = 1 <<  0, // 動畫過程中保證子視圖跟隨運動。**提交動畫的時候布局子控件,表示子控件將和父控件一同動畫。**
    UIViewAnimationOptionAllowUserInteraction      = 1 <<  1, // 動畫過程中允許用戶交互。
    UIViewAnimationOptionBeginFromCurrentState     = 1 <<  2, // 所有視圖從當前狀態開始運行,而不是從初始狀態開始運行。
    UIViewAnimationOptionRepeat                    = 1 <<  3, // 無限重復動畫
    UIViewAnimationOptionAutoreverse               = 1 <<  4, // 動畫運行到結束點后仍然以動畫方式回到初始點。**來回運行動畫,前提是設置動畫無限重復**
    UIViewAnimationOptionOverrideInheritedDuration = 1 <<  5, // 忽略嵌套動畫時間設置。**忽略外層動畫嵌套的時間變化曲線**
    UIViewAnimationOptionOverrideInheritedCurve    = 1 <<  6, // 忽略嵌套動畫速度設置。**通過改變屬性和重繪實現動畫效果,如果key沒有提交動畫將使用快照**
    UIViewAnimationOptionAllowAnimatedContent      = 1 <<  7, // 動畫過程中重繪視圖(注意僅僅適用于轉場動畫)。
    UIViewAnimationOptionShowHideTransitionViews   = 1 <<  8, // 視圖切換時直接隱藏舊視圖、顯示新視圖,而不是將舊視圖從父視圖移除(僅僅適用于轉場動畫)**用顯隱的方式替代添加移除圖層的動畫效果**
    UIViewAnimationOptionOverrideInheritedOptions  = 1 <<  9, // 不繼承父動畫設置或動畫類型。**忽略嵌套繼承的選項**
    
    // ??----------------------------------------------------------------------------
    // 2.動畫速度控制(可從其中選擇一個設置)時間函數曲線相關**時間曲線函數**
    UIViewAnimationOptionCurveEaseInOut            = 0 << 16, // 默認,動畫先緩慢,然后逐漸加速。
    UIViewAnimationOptionCurveEaseIn               = 1 << 16, // 動畫逐漸變慢。
    UIViewAnimationOptionCurveEaseOut              = 2 << 16, // 動畫逐漸加速。
    UIViewAnimationOptionCurveLinear               = 3 << 16, // 動畫勻速執行。
    
    // ??-----------------------------------------------------------------------------
    // 3.轉場類型(僅適用于轉場動畫設置,可以從中選擇一個進行設置,基本動畫、關鍵幀動畫不需要設置)**轉場動畫相關**
    UIViewAnimationOptionTransitionNone            = 0 << 20, // 默認,沒有轉場動畫效果。
    UIViewAnimationOptionTransitionFlipFromLeft    = 1 << 20, // 從左側翻轉效果。
    UIViewAnimationOptionTransitionFlipFromRight   = 2 << 20, // 從右側翻轉效果。
    UIViewAnimationOptionTransitionCurlUp          = 3 << 20, // 向后翻頁的動畫過渡效果。
    UIViewAnimationOptionTransitionCurlDown        = 4 << 20, // 向前翻頁的動畫過渡效果。
    UIViewAnimationOptionTransitionCrossDissolve   = 5 << 20, // 舊視圖溶解消失顯示下一個新視圖的效果。
    UIViewAnimationOptionTransitionFlipFromTop     = 6 << 20, // 從上方翻轉效果。
    UIViewAnimationOptionTransitionFlipFromBottom  = 7 << 20, // 從底部翻轉效果。
    
    // ??-----------------------------------------------------------------------------
    // 4.設置幀速率
    UIViewAnimationOptionPreferredFramesPerSecondDefault     = 0 << 24, // 默認的幀每秒.
    UIViewAnimationOptionPreferredFramesPerSecond60          = 3 << 24, // 60幀每秒的幀速率.
    UIViewAnimationOptionPreferredFramesPerSecond30          = 7 << 24, // 30幀每秒的幀速率.
    
    /*
      補充:關于轉場動畫,它一般是用在這個方法中的:
     
     [UIView transitionFromView: toView: duration: options:  completion:^(****BOOL****finished) {}];
     該方法效果是插入一面視圖移除一面視圖,期間可以使用一些轉場動畫效果。
     */
} NS_ENUM_AVAILABLE_IOS(4_0);

/** UIView 關鍵幀動畫 */ 
typedef NS_OPTIONS(NSUInteger, UIViewKeyframeAnimationOptions) {  
    UIViewKeyframeAnimationOptionLayoutSubviews            = UIViewAnimationOptionLayoutSubviews, //!< 動畫過程中保證子視圖跟隨運動.  
    UIViewKeyframeAnimationOptionAllowUserInteraction      = UIViewAnimationOptionAllowUserInteraction, //!< 動畫過程中允許用戶交互.  
    UIViewKeyframeAnimationOptionBeginFromCurrentState     = UIViewAnimationOptionBeginFromCurrentState, //!< 所有視圖從當前狀態開始運行.  
    UIViewKeyframeAnimationOptionRepeat                    = UIViewAnimationOptionRepeat, //!< 重復運行動畫.  
    UIViewKeyframeAnimationOptionAutoreverse               = UIViewAnimationOptionAutoreverse, //!< 動畫運行到結束點后仍然以動畫方式回到初始點.  
    UIViewKeyframeAnimationOptionOverrideInheritedDuration = UIViewAnimationOptionOverrideInheritedDuration, //!< 忽略嵌套動畫時間設置.  
    UIViewKeyframeAnimationOptionOverrideInheritedOptions  = UIViewAnimationOptionOverrideInheritedOptions, //!< 不繼承父動畫設置或動畫類型.  
      
    UIViewKeyframeAnimationOptionCalculationModeLinear     = 0 << 10, //!< 連續運算模式, 默認.  
    UIViewKeyframeAnimationOptionCalculationModeDiscrete   = 1 << 10, //!< 離散運算模式.  
    UIViewKeyframeAnimationOptionCalculationModePaced      = 2 << 10, //!< 均勻執行運算模式.  
    UIViewKeyframeAnimationOptionCalculationModeCubic      = 3 << 10, //!< 平滑運算模式.  
    UIViewKeyframeAnimationOptionCalculationModeCubicPaced = 4 << 10  //!< 平滑均勻運算模式.  
} NS_ENUM_AVAILABLE_IOS(7_0);  
  
typedef NS_ENUM(NSUInteger, UISystemAnimation) {  
    UISystemAnimationDelete,    //!< 系統刪除動畫  
} NS_ENUM_AVAILABLE_IOS(7_0);  
  
typedef NS_ENUM(NSInteger, UIViewTintAdjustmentMode) {  
    UIViewTintAdjustmentModeAutomatic,  //!< 自動的,與父視圖相同.  
      
    UIViewTintAdjustmentModeNormal,     //!< 未經修改的.  
    UIViewTintAdjustmentModeDimmed,     //!< 飽和、暗淡的原始色.  
} NS_ENUM_AVAILABLE_IOS(7_0);  
  
typedef NS_ENUM(NSInteger, UISemanticContentAttribute) {  
    UISemanticContentAttributeUnspecified = 0,  //!< 未指定,默認值  
    UISemanticContentAttributePlayback,         //!< 打開/ RW / FF等播放控制按鈕  
    UISemanticContentAttributeSpatial,          //!< 控制導致某種形式的定向改變UI中,如分段控制文本對齊方式或在游戲中方向鍵  
    UISemanticContentAttributeForceLeftToRight, //!< 視圖總是從左向右布局.  
    UISemanticContentAttributeForceRightToLeft  //!< 視圖總是從右向左布局.  
} NS_ENUM_AVAILABLE_IOS(9_0);  
  
@protocol UICoordinateSpace <NSObject>  
  
/** 將像素point由point所在視圖轉換到目標視圖view中,返回在目標視圖view中的像素值 */  
- (CGPoint)convertPoint:(CGPoint)point toCoordinateSpace:(id <UICoordinateSpace>)coordinateSpace NS_AVAILABLE_IOS(8_0);  
/** 將像素point由point所在視圖轉換到目標視圖view中,返回在目標視圖view中的像素值 */  
- (CGPoint)convertPoint:(CGPoint)point fromCoordinateSpace:(id <UICoordinateSpace>)coordinateSpace NS_AVAILABLE_IOS(8_0);  
/** 將rect由rect所在視圖轉換到目標視圖view中,返回在目標視圖view中的rect */  
- (CGRect)convertRect:(CGRect)rect toCoordinateSpace:(id <UICoordinateSpace>)coordinateSpace NS_AVAILABLE_IOS(8_0);  
/** 將rect從view中轉換到當前視圖中,返回在當前視圖中的rect */  
- (CGRect)convertRect:(CGRect)rect fromCoordinateSpace:(id <UICoordinateSpace>)coordinateSpace NS_AVAILABLE_IOS(8_0);  
  
/** 獲取bounds */  
@property (readonly, nonatomic) CGRect bounds NS_AVAILABLE_IOS(8_0);  
  
@end  
  
@class UIBezierPath, UIEvent, UIWindow, UIViewController, UIColor, UIGestureRecognizer, UIMotionEffect, CALayer, UILayoutGuide;  

// ??----------------------------------------------------------------------------
// UIView 
NS_CLASS_AVAILABLE_IOS(2_0) @interface UIView : UIResponder <NSCoding, UIAppearance, UIAppearanceContainer, UIDynamicItem, UITraitEnvironment, UICoordinateSpace, UIFocusItem, CALayerDelegate>  
  
/** 返回主 layer 所使用的類 */  
#if UIKIT_DEFINE_AS_PROPERTIES  
@property(class, nonatomic, readonly) Class layerClass;  
#else  
+ (Class)layerClass;  
#endif  
  
/** 通過設置 Frame 初始化 UIView 對象 */  
- (instancetype)initWithFrame:(CGRect)frame NS_DESIGNATED_INITIALIZER;  
/** 用于xib初始化 */  
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER;  
  
/** 設置用戶交互,默認YES允許用戶交互 */  
@property(nonatomic,getter=isUserInteractionEnabled) BOOL userInteractionEnabled;  
/** 控件標記(父控件可以通過tag找到對應的子控件),默認為0 */  
@property(nonatomic)                                 NSInteger tag;  
/** 視圖圖層(可以用來設置圓角效果/陰影效果) */  
@property(nonatomic,readonly,strong)                 CALayer  *layer;  
  
/** 返回是否可以成為焦點, 默認NO */  
#if UIKIT_DEFINE_AS_PROPERTIES  
@property(nonatomic,readonly) BOOL canBecomeFocused NS_AVAILABLE_IOS(9_0);  
#else  
- (BOOL)canBecomeFocused NS_AVAILABLE_IOS(9_0);  
#endif  
/** 是否可以被聚焦 */  
@property (readonly, nonatomic, getter=isFocused) BOOL focused NS_AVAILABLE_IOS(9_0);  
  
/** 左右滑動翻轉效果 */  
@property (nonatomic) UISemanticContentAttribute semanticContentAttribute NS_AVAILABLE_IOS(9_0);  
  
/** 獲取視圖的方向 */  
+ (UIUserInterfaceLayoutDirection)userInterfaceLayoutDirectionForSemanticContentAttribute:(UISemanticContentAttribute)attribute NS_AVAILABLE_IOS(9_0);  
  
/** 獲取相對于指定視圖的界面方向 */  
+ (UIUserInterfaceLayoutDirection)userInterfaceLayoutDirectionForSemanticContentAttribute:(UISemanticContentAttribute)semanticContentAttribute relativeToLayoutDirection:(UIUserInterfaceLayoutDirection)layoutDirection NS_AVAILABLE_IOS(10_0);  
  
/** 返回即時內容的布局的方向 */  
@property (readonly, nonatomic) UIUserInterfaceLayoutDirection effectiveUserInterfaceLayoutDirection NS_AVAILABLE_IOS(10_0);  
  
@end  

// ??----------------------------------------------------------------------------
// UIView 范疇類,幾何 
@interface UIView(UIViewGeometry)  
  
/** 位置和尺寸(以父控件的左上角為坐標原點(0, 0)) */  
@property(nonatomic) CGRect            frame;  
  
/** 位置和尺寸(以自己的左上角為坐標原點(0, 0)) */  
@property(nonatomic) CGRect            bounds;  
/** 中心點(以父控件的左上角為坐標原點(0, 0)) */  
@property(nonatomic) CGPoint           center;  
/** 變形屬性(平移\縮放\旋轉) */  
@property(nonatomic) CGAffineTransform transform;  
/** 視圖內容的縮放比例 */  
@property(nonatomic) CGFloat           contentScaleFactor NS_AVAILABLE_IOS(4_0);  
  
/** 是否支持多點觸摸,默認NO */  
@property(nonatomic,getter=isMultipleTouchEnabled) BOOL multipleTouchEnabled __TVOS_PROHIBITED;  
/** 是否獨占整個Touch事件,默認NO */  
@property(nonatomic,getter=isExclusiveTouch) BOOL       exclusiveTouch __TVOS_PROHIBITED;  
  
/** 在指定點上點擊測試指定事件 */  
- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event;  
/** 判斷當前的點擊或者觸摸事件的點是否在當前的view中,默認返回YES */  
- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event;  
  
/** 將像素point由point所在視圖轉換到目標視圖view中,返回在目標視圖view中的像素值 */  
- (CGPoint)convertPoint:(CGPoint)point toView:(nullable UIView *)view;  
/** 將像素point由point所在視圖轉換到目標視圖view中,返回在目標視圖view中的像素值 */  
- (CGPoint)convertPoint:(CGPoint)point fromView:(nullable UIView *)view;  
/** 將rect由rect所在視圖轉換到目標視圖view中,返回在目標視圖view中的rect */  
- (CGRect)convertRect:(CGRect)rect toView:(nullable UIView *)view;  
/** 將rect從view中轉換到當前視圖中,返回在當前視圖中的rect */  
- (CGRect)convertRect:(CGRect)rect fromView:(nullable UIView *)view;  
  
/** 自動調整子視圖尺寸,默認YES,如果 self.bounds 改變了,則會根據 autoresizingMask 屬性自動調整子視圖尺寸 */  
@property(nonatomic) BOOL               autoresizesSubviews;  
/** 自動調整子視圖與父視圖的位置,默認 UIViewAutoresizingNone */  
@property(nonatomic) UIViewAutoresizing autoresizingMask;  
  
/** 返回“最佳”尺寸以適應給定尺寸。不實際調整視圖大小。默認為返回現有視圖大小。*/  
- (CGSize)sizeThatFits:(CGSize)size;  
/** 調整為剛好合適子視圖大小 */  
- (void)sizeToFit;  
  
@end  

// ??----------------------------------------------------------------------------
// UIView 范疇類,視圖層次結構
@interface UIView(UIViewHierarchy)  
  
/** 獲取父視圖 */  
@property(nullable, nonatomic,readonly) UIView       *superview;  
/** 獲取所有子視圖 */  
@property(nonatomic,readonly,copy) NSArray<__kindof UIView *> *subviews;  
/** 獲取視圖所在的Window */  
@property(nullable, nonatomic,readonly) UIWindow     *window;  
  
/** 從父視圖中移除控件 */  
- (void)removeFromSuperview;  
/** 插入子視圖(將子視圖插入到subviews數組中index這個位置) */  
- (void)insertSubview:(UIView *)view atIndex:(NSInteger)index;  
/** 交換subviews數組中所存放子視圖的位置 */  
- (void)exchangeSubviewAtIndex:(NSInteger)index1 withSubviewAtIndex:(NSInteger)index2;  
  
/** 添加子視圖(新添加的視圖在subviews數組的后面, 顯示在最上面) */  
- (void)addSubview:(UIView *)view;  
/** 插入子視圖(將子視圖插到siblingSubview之下) */  
- (void)insertSubview:(UIView *)view belowSubview:(UIView *)siblingSubview;  
/** 插入子視圖(將子視圖插到siblingSubview之上) */  
- (void)insertSubview:(UIView *)view aboveSubview:(UIView *)siblingSubview;  
  
/** 將子視圖拉到最上面來顯示 */  
- (void)bringSubviewToFront:(UIView *)view;  
/** 將子視圖拉到最下面來顯示 */  
- (void)sendSubviewToBack:(UIView *)view;  
  
#pragma mark - 系統自動調用(留給子類去實現)  
/** 添加子視圖完成后調用 */  
- (void)didAddSubview:(UIView *)subview;  
/** 將要移除子視圖時調用 */  
- (void)willRemoveSubview:(UIView *)subview;  
  
/** 將要移動到新父視圖時調用 */  
- (void)willMoveToSuperview:(nullable UIView *)newSuperview;  
/** 移動到新父視圖完成后調用 */  
- (void)didMoveToSuperview;  
/** 將要移動到新 Window 時調用 */  
- (void)willMoveToWindow:(nullable UIWindow *)newWindow;  
/** 移動到新 Window 完成后調用 */  
- (void)didMoveToWindow;  
  
/** 判斷view是否為子類 */  
- (BOOL)isDescendantOfView:(UIView *)view;  
/** 通過tag獲得對應的子視圖 */  
- (nullable __kindof UIView *)viewWithTag:(NSInteger)tag;  
  
/** 對現在有布局有調整更改后,使用這個方法進行更新 */  
- (void)setNeedsLayout;  
/** 強制進行更新layout */  
- (void)layoutIfNeeded;  
  
/** 控件的frame發生改變的時候就會調用,一般在這里重寫布局子控件的位置和尺寸 */  
- (void)layoutSubviews;  
  
/** 設置view之間的間距,該屬性只對autolayout布局有效 */  
@property (nonatomic) UIEdgeInsets layoutMargins NS_AVAILABLE_IOS(8_0);  
/** 是否將當前視圖的間距和父視圖相同,默認是NO */  
@property (nonatomic) BOOL preservesSuperviewLayoutMargins NS_AVAILABLE_IOS(8_0);  
/** 改變view的layoutMargins這個屬性時,會觸發這個方法 */  
- (void)layoutMarginsDidChange NS_AVAILABLE_IOS(8_0);  
  
/** 視圖間距引導 */  
@property(readonly,strong) UILayoutGuide *layoutMarginsGuide NS_AVAILABLE_IOS(9_0);  
  
/** 獲取此區域的內的布局引導 */  
@property (nonatomic, readonly, strong) UILayoutGuide *readableContentGuide  NS_AVAILABLE_IOS(9_0);  
@end  

// ??----------------------------------------------------------------------------
// UIView 范疇類,視圖渲染
@interface UIView(UIViewRendering)  
  
/** 重寫drawRect方法,在可以這里進行繪圖操作。*/  
- (void)drawRect:(CGRect)rect;  
  
/** 標記整個視圖的邊界矩形需要重繪, 調用這個方法會自動調用drawRect方法 */  
- (void)setNeedsDisplay;  
/** 標記在指定區域內的視圖的邊界需要重繪, 調用這個方法會自動調用drawRect方法 */  
- (void)setNeedsDisplayInRect:(CGRect)rect;  
  
/** 是否裁剪超出Bounds范圍的子控件,默認NO */  
@property(nonatomic)                 BOOL              clipsToBounds;  
/** 設置背景顏色,默認nil */  
@property(nullable, nonatomic,copy)  UIColor          *backgroundColor UI_APPEARANCE_SELECTOR;  
/** 設置透明度(范圍0.0~1.0),默認1.0 */  
@property(nonatomic)                 CGFloat           alpha;  
/** 設置是否不透明,默認YES不透明 */  
@property(nonatomic,getter=isOpaque) BOOL              opaque;  
/** 視圖重繪前是否先清理以前的內容,默認YES */  
@property(nonatomic)                 BOOL              clearsContextBeforeDrawing;  
/** 設置是否隱藏,默認NO不隱藏 */  
@property(nonatomic,getter=isHidden) BOOL              hidden;  
/** 內容顯示的模式,默認UIViewContentModeScaleToFill */  
@property(nonatomic)                 UIViewContentMode contentMode;  
/** 拉伸屬性,如圖片拉伸 */  
@property(nonatomic)                 CGRect            contentStretch NS_DEPRECATED_IOS(3_0,6_0) __TVOS_PROHIBITED;  
  
/** 蒙板view */  
@property(nullable, nonatomic,strong)          UIView           *maskView NS_AVAILABLE_IOS(8_0);  
  
/** 改變應用程序的外觀的顏色。默認為nil */  
@property(null_resettable, nonatomic, strong) UIColor *tintColor NS_AVAILABLE_IOS(7_0);  
  
/** 可以使tintColor變暗,因此整個視圖層次變暗 */  
@property(nonatomic) UIViewTintAdjustmentMode tintAdjustmentMode NS_AVAILABLE_IOS(7_0);  
  
/** 覆蓋這個方法的目的是為了當tintColor改變的時候自定義一些行為 */  
- (void)tintColorDidChange NS_AVAILABLE_IOS(7_0);  
  
@end  

// ??----------------------------------------------------------------------------
// UIView 范疇類,視圖動畫
@interface UIView(UIViewAnimation)  
  
/** 開始動畫 */  
+ (void)beginAnimations:(nullable NSString *)animationID context:(nullable voidvoid *)context;  
/** 提交動畫 */  
+ (void)commitAnimations;  
  
/** 設置動畫代理, 默認nil */  
+ (void)setAnimationDelegate:(nullable id)delegate;  
/** 動畫將要開始時執行方法(必須要先設置動畫代理), 默認NULL */  
+ (void)setAnimationWillStartSelector:(nullable SEL)selector;  
/** 動畫已結束時執行方法(必須要先設置動畫代理), 默認NULL */  
+ (void)setAnimationDidStopSelector:(nullable SEL)selector;  
/** 設置動畫時長, 默認0.2秒 */  
+ (void)setAnimationDuration:(NSTimeInterval)duration;  
/** 動畫延遲執行時間, 默認0.0秒 */  
+ (void)setAnimationDelay:(NSTimeInterval)delay;  
/** 設置在動畫塊內部動畫屬性改變的開始時間, 默認now ([NSDate date]) */  
+ (void)setAnimationStartDate:(NSDate *)startDate;  
/** 設置動畫曲線, 默認UIViewAnimationCurveEaseInOut */  
+ (void)setAnimationCurve:(UIViewAnimationCurve)curve;  
/** 動畫的重復播放次數, 默認0 */  
+ (void)setAnimationRepeatCount:(float)repeatCount;  
/** 設置是否自定翻轉當前的動畫效果, 默認NO */  
+ (void)setAnimationRepeatAutoreverses:(BOOL)repeatAutoreverses;  
/** 設置動畫從當前狀態開始播放, 默認NO */  
+ (void)setAnimationBeginsFromCurrentState:(BOOL)fromCurrentState;  
  
/** 在動畫塊中為視圖設置過渡動畫 */  
+ (void)setAnimationTransition:(UIViewAnimationTransition)transition forView:(UIView *)view cache:(BOOL)cache;  
  
/** 設置是否激活動畫 */  
+ (void)setAnimationsEnabled:(BOOL)enabled;  
/** 返回一個布爾值表示動畫是否結束 */  
#if UIKIT_DEFINE_AS_PROPERTIES  
@property(class, nonatomic, readonly) BOOL areAnimationsEnabled;  
#else  
+ (BOOL)areAnimationsEnabled;  
#endif  
/** 先檢查動畫當前是否啟用,然后禁止動畫,執行block內的方法,最后重新啟用動畫,而且這個方法不會阻塞基于CoreAnimation的動畫 */  
+ (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  

// ??----------------------------------------------------------------------------
// UIView 范疇類,用 Blocks 方式實現視圖動畫
@interface UIView(UIViewAnimationWithBlocks)  

/** 
  通過指定動畫持續時間、動畫延遲、執行動畫選項和動畫完成后回調的 Block 對象,更改一個或多個視圖的動畫。
*/
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(4_0);  
  
/** 
  通過指定動畫持續時間、動畫完成后回調的 Block 對象,更改一個或多個視圖的動畫。
  
  默認:delay = 0.0, options = 0 
*/  
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(4_0);  
  
/** 
  通過指定動畫持續時間更改一個或多個視圖的動畫。
  
  默認:delay = 0.0, options = 0, completion = NULL 
*/
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations NS_AVAILABLE_IOS(4_0);  
  
/** 使用與物理彈簧運動相對應的定時曲線執行視圖動畫 */  
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay usingSpringWithDamping:(CGFloat)dampingRatio initialSpringVelocity:(CGFloat)velocity options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(7_0);  
  
/** 為指定的容器視圖創建轉換動畫 */  
+ (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^ __nullable)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(4_0);  
  
/** 使用給定的參數在指定視圖之間創建轉換動畫 */  
+ (void)transitionFromView:(UIView *)fromView toView:(UIView *)toView duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(4_0); // toView added to fromView.superview, fromView removed from its superview  
  
/** 在一個或多個視圖上執行指定的系統提供的動畫,以及定義的可選并行動畫 */  
+ (void)performSystemAnimation:(UISystemAnimation)animation onViews:(NSArray<__kindof UIView *> *)views options:(UIViewAnimationOptions)options animations:(void (^ __nullable)(void))parallelAnimations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(7_0);  
  
@end  
  
// ??----------------------------------------------------------------------------
// UIView 范疇類,UIView 的關鍵幀動畫
@interface UIView (UIViewKeyframeAnimations)  
  
/** 創建一個動畫塊對象,可用于為當前視圖設置基于關鍵幀的動畫 */  
+ (void)animateKeyframesWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewKeyframeAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(7_0);  

/** 添加指定開始時間、持續時間的關鍵幀動畫(起始和持續時間是0.0和1.0之間的值) */  
+ (void)addKeyframeWithRelativeStartTime:(double)frameStartTime relativeDuration:(double)frameDuration animations:(void (^)(void))animations NS_AVAILABLE_IOS(7_0);  
  
@end  

// ??----------------------------------------------------------------------------
// UIView 范疇類,手勢識別
@interface UIView (UIViewGestureRecognizers)  
  
/** 當前視圖所附加的所有手勢識別器 */  
@property(nullable, nonatomic,copy) NSArray<__kindof UIGestureRecognizer *> *gestureRecognizers NS_AVAILABLE_IOS(3_2);  
  
/** 添加一個手勢識別器 */  
- (void)addGestureRecognizer:(UIGestureRecognizer*)gestureRecognizer NS_AVAILABLE_IOS(3_2);  
/** 移除一個手勢識別器 */  
- (void)removeGestureRecognizer:(UIGestureRecognizer*)gestureRecognizer NS_AVAILABLE_IOS(3_2);  
  
/** 是否開始一個手勢識別器 */  
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer NS_AVAILABLE_IOS(6_0);  
  
@end  

// ??----------------------------------------------------------------------------
// UIView 范疇類,UIView 運動效果
@interface UIView (UIViewMotionEffects)  
  
/** 添加運動效果,當傾斜設備時視圖稍微改變其位置 */  
- (void)addMotionEffect:(UIMotionEffect *)effect NS_AVAILABLE_IOS(7_0);  
  
/** 移除運動效果 */  
- (void)removeMotionEffect:(UIMotionEffect *)effect NS_AVAILABLE_IOS(7_0);  
  
/** 所有添加的運動效果 */  
@property (copy, nonatomic) NSArray<__kindof UIMotionEffect *> *motionEffects NS_AVAILABLE_IOS(7_0);  
  
@end  
  
  
typedef NS_ENUM(NSInteger, UILayoutConstraintAxis) {  
    UILayoutConstraintAxisHorizontal = 0,   //!< 水平約束.  
    UILayoutConstraintAxisVertical = 1      //!< 豎直約束.  
};  
  
// ??----------------------------------------------------------------------------
// UIView 范疇類,UIView 布局約束設置  
@interface UIView (UIConstraintBasedLayoutInstallingConstraints)  
  
/** 獲取所有約束 */  
@property(nonatomic,readonly) NSArray<__kindof NSLayoutConstraint *> *constraints NS_AVAILABLE_IOS(6_0);  
  
/** 添加一個約束 */  
- (void)addConstraint:(NSLayoutConstraint *)constraint NS_AVAILABLE_IOS(6_0);  
/** 添加多個約束 */  
- (void)addConstraints:(NSArray<__kindof NSLayoutConstraint *> *)constraints NS_AVAILABLE_IOS(6_0);  
/** 移除一個約束 */  
- (void)removeConstraint:(NSLayoutConstraint *)constraint NS_AVAILABLE_IOS(6_0);  
/** 移除多個約束 */  
- (void)removeConstraints:(NSArray<__kindof NSLayoutConstraint *> *)constraints NS_AVAILABLE_IOS(6_0);  
@end  

// ??----------------------------------------------------------------------------
// UIView 范疇類,UIView 基于約束的布局核心方法
@interface UIView (UIConstraintBasedLayoutCoreMethods)  
/** 更新視圖和其子視圖的約束 */  
- (void)updateConstraintsIfNeeded NS_AVAILABLE_IOS(6_0);  
/** 為視圖更新約束,可以重寫這個方法來設置當前view局部的布局約束 */  
- (void)updateConstraints NS_AVAILABLE_IOS(6_0) NS_REQUIRES_SUPER;  
/** 視圖的約束是否需要更新 */  
- (BOOL)needsUpdateConstraints NS_AVAILABLE_IOS(6_0);  
/** 設置視圖的約束需要更新,調用這個方法,系統會調用updateConstraints去更新布局 */  
- (void)setNeedsUpdateConstraints NS_AVAILABLE_IOS(6_0);  
@end  

// ??----------------------------------------------------------------------------
// UIView 范疇類,UIView 約束兼容性設置
@interface UIView (UIConstraintBasedCompatibility)  
  
/** 是否啟用自動布局約束,默認YES. IB默認是NO */  
@property(nonatomic) BOOL translatesAutoresizingMaskIntoConstraints NS_AVAILABLE_IOS(6_0);  
  
/** 是否使用約束布局 */  
#if UIKIT_DEFINE_AS_PROPERTIES  
@property(class, nonatomic, readonly) BOOL requiresConstraintBasedLayout NS_AVAILABLE_IOS(6_0);  
#else  
+ (BOOL)requiresConstraintBasedLayout NS_AVAILABLE_IOS(6_0);  
#endif  
  
@end  

// ??----------------------------------------------------------------------------
// UIView 范疇類,UIView 布局圖層約束  
@interface UIView (UIConstraintBasedLayoutLayering)  
  
/** 返回給定框架的視圖的對齊矩陣 */  
- (CGRect)alignmentRectForFrame:(CGRect)frame NS_AVAILABLE_IOS(6_0);  
/** 返回給定對齊矩形的視圖的frame */  
- (CGRect)frameForAlignmentRect:(CGRect)alignmentRect NS_AVAILABLE_IOS(6_0);  
  
/** 返回從視圖的frame上定義的對齊矩陣的邊框 */  
#if UIKIT_DEFINE_AS_PROPERTIES  
@property(nonatomic, readonly) UIEdgeInsets alignmentRectInsets NS_AVAILABLE_IOS(6_0);  
#else  
- (UIEdgeInsets)alignmentRectInsets NS_AVAILABLE_IOS(6_0);  
#endif  
  
/** 返回滿足基線約束條件的視圖 */  
- (UIView *)viewForBaselineLayout NS_DEPRECATED_IOS(6_0, 9_0, "Override -viewForFirstBaselineLayout or -viewForLastBaselineLayout as appropriate, instead") __TVOS_PROHIBITED;  
  
/** 返回用于滿足第一基線約束的視圖 */  
@property(readonly,strong) UIView *viewForFirstBaselineLayout NS_AVAILABLE_IOS(9_0);  
  
/** 返回用于滿足上次基線約束的視圖 */  
@property(readonly,strong) UIView *viewForLastBaselineLayout NS_AVAILABLE_IOS(9_0);  
  
  
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  
- (CGSize)intrinsicContentSize NS_AVAILABLE_IOS(6_0);  
#endif  
/** 廢除視圖原本內容的size */  
- (void)invalidateIntrinsicContentSize NS_AVAILABLE_IOS(6_0);  
  
/** 設置當視圖要變大時,視圖的壓縮改變方式,返回一個優先權(確定view有多大的優先級阻止自己變大) */  
- (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);  

// ??----------------------------------------------------------------------------
// UIView 范疇類,UIView 布局擬合尺寸 
@interface UIView (UIConstraintBasedLayoutFittingSize)  
/** 返回滿足持有約束的視圖的size */  
- (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize NS_AVAILABLE_IOS(6_0);  
/** 返回滿足它所包含的約束的視圖的大小 */  
- (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize withHorizontalFittingPriority:(UILayoutPriority)horizontalFittingPriority verticalFittingPriority:(UILayoutPriority)verticalFittingPriority NS_AVAILABLE_IOS(8_0);  
@end  

// ??----------------------------------------------------------------------------
// UIView 范疇類,UIView 布局指南支持 
@interface UIView (UILayoutGuideSupport)  
  
/** 此視圖擁有布局向導對象的數組 */  
@property(nonatomic,readonly,copy) NSArray<__kindof UILayoutGuide *> *layoutGuides NS_AVAILABLE_IOS(9_0);  
  
/** 向視圖中添加布局向導 */  
- (void)addLayoutGuide:(UILayoutGuide *)layoutGuide NS_AVAILABLE_IOS(9_0);  
  
/** 向視圖中添加布局向導 */  
- (void)removeLayoutGuide:(UILayoutGuide *)layoutGuide NS_AVAILABLE_IOS(9_0);  
@end  
  
@class NSLayoutXAxisAnchor,NSLayoutYAxisAnchor,NSLayoutDimension;  
@interface UIView (UIViewLayoutConstraintCreation)  
/** 布局視圖的前緣框的布局錨點 */  
@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  


// ??----------------------------------------------------------------------------
// UIView 范疇類,UIView 布局調試   
@interface UIView (UIConstraintBasedLayoutDebugging)  
  
/** 獲得實體在不同方向上所有的布局約束 */  
- (NSArray<__kindof NSLayoutConstraint *> *)constraintsAffectingLayoutForAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);  
  
/** 可以知道當前視圖的布局是否會有歧義 */  
#if UIKIT_DEFINE_AS_PROPERTIES  
@property(nonatomic, readonly) BOOL hasAmbiguousLayout NS_AVAILABLE_IOS(6_0);  
#else  
- (BOOL)hasAmbiguousLayout NS_AVAILABLE_IOS(6_0);  
#endif  
  
/** 這個方法會隨機改變視圖的layout到另外一個有效的layout。這樣我們就可以很清楚的看到哪一個layout導致了整體的布局約束出現了錯誤,或者我們應該增加更多的布局約束 */  
- (void)exerciseAmbiguityInLayout NS_AVAILABLE_IOS(6_0);  
@end  

// ??----------------------------------------------------------------------------
/** 約束調試,只在DEBUG環境下被調用 */  
@interface UILayoutGuide (UIConstraintBasedLayoutDebugging)  
  
/** 獲得實體在不同方向上所有的布局約束 */  
- (NSArray<__kindof NSLayoutConstraint *> *)constraintsAffectingLayoutForAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(10_0);  
  
/** 可以知道當前視圖的布局是否會有歧義 */  
#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  

// ??----------------------------------------------------------------------------
#pragma mark - View狀態保存恢復  
@interface UIView (UIStateRestoration)  
/** 標示是否支持保存,恢復視圖狀態信息 */  
@property (nullable, 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  

// ??----------------------------------------------------------------------------  
#pragma mark - View快照  
@interface UIView (UISnapshotting)  
/** 將當前顯示的view截取成一個新的view */  
- (nullable UIView *)snapshotViewAfterScreenUpdates:(BOOL)afterUpdates NS_AVAILABLE_IOS(7_0);  
/** 縮放一個view默認是從中心點進行縮放的 */  
- (nullable UIView *)resizableSnapshotViewFromRect:(CGRect)rect afterScreenUpdates:(BOOL)afterUpdates withCapInsets:(UIEdgeInsets)capInsets NS_AVAILABLE_IOS(7_0);  
/** 屏幕快照 */  
- (BOOL)drawViewHierarchyInRect:(CGRect)rect afterScreenUpdates:(BOOL)afterUpdates NS_AVAILABLE_IOS(7_0);  
@end  
  
NS_ASSUME_NONNULL_END  

參考

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,563評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,694評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,672評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,965評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,690評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,019評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,013評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,188評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,718評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,438評論 3 360
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,667評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,149評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,845評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,252評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,590評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,384評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,635評論 2 380

推薦閱讀更多精彩內容