在iOS開發中,我們知道有一個共同的基類——NSObject,但是對於界面視圖而言,UIView是非常重要的一個類,UIView是很多視圖控件的基類,因此,對於UIView的學習閑的非常有必要。在iOS學習——iOS 整體框架及類繼承框架圖中列出了iOS中所有類的繼承框架圖,其中下面這張圖就是iOS開發中的界面相關類的繼承框架圖。
下面主要通過學習UIView.h文件來了解UIView主要提供了那些方法和屬性,從UIView.h的源碼來看,UIView.h的結構主要分為4個部分:
- 常用枚舉類型的定義,主要包括
- 視圖動畫曲線 UIViewAnimationCurve
- 視圖內容填充模式 UIViewContentMode
- 視圖動畫過渡效果 UIViewAnimationTransition
- 視圖自動調整大小方式 UIViewAutoresizing
- 視圖的動畫選項 UIViewAnimationOptions
- 視圖關鍵幀動畫選項 UIViewKeyframeAnimationOptions
- 視圖的系統動畫 UISystemAnimation
- 視圖的外觀色調調整模式 UIViewTintAdjustmentMode
- 語義內容屬性 UISemanticContentAttribute
- 布局約束的軸 UILayoutConstraintAxis(水平還是豎直)(該定義在后面第四部分中間)
- 坐標空間協議UICoordinateSpace的定義,定義了坐標點(CGPoint)、坐標區域(CGRect)在兩個view間的轉換
- UIView的主要方法和屬性的定義
- 類方法 2個
- 初始化方法 2個
- 屬性 8個
- UIView的各類擴展
- 視圖幾何相關的擴展 UIView (UIViewGeometry),主要定義了視圖上位置和區域相關一些屬性和方法
- 視圖層次結構相關的擴展 UIView (UIViewHierarchy),主要定義對子視圖的增刪改以及層次結構調整等操作
- 視圖外觀渲染相關的擴展 UIView (UIViewRendering),主要定義視圖的一些屬性和設置,例如是否隱藏、透明度、背景顏色等
- 視圖動畫相關的擴展 UIView (UIViewAnimation) ,主要定義視圖上自定義一個動畫所需的一系列方法
- 視圖用block快速定義動畫的擴展 UIView (UIViewAnimationWithBlocks),主要提供7個類方法直接用block添加動畫,根據需要選擇不同的類方法進行相關參數的設定
- 視圖關鍵幀動畫相關的擴展 UIView (UIViewKeyframeAnimations) ,主要提供兩個類方法進行關鍵幀動畫的設定,也是直接采用block的方式實現
- 視圖上手勢相關的擴展 UIView (UIViewGestureRecognizers) ,主要提供添加、移除和手勢開始前回調3個方法
- 視圖上運動效果相關的擴展 UIView (UIViewMotionEffects),主要提供添加和移除運動效果兩個方法,還提供一個獲取視圖上所有運動效果的屬性
- 視圖上安裝約束相關的擴展 UIView (UIConstraintBasedLayoutInstallingConstraints) ,主要提供添加單個/多個、移除單個/多個約束的方法
- 視圖上約束相關的擴展 UIView (UIConstraintBasedLayoutCoreMethods),主要提供4種約束更新的方法
- 視圖上約束共存相關的擴展 UIView (UIConstraintBasedCompatibility)
- 視圖約束布局圖層相關的擴展 IView (UIConstraintBasedLayoutLayering),主要是獲取視圖上約束相關的一些屬性,比喻第一視圖、基線視圖、視圖大小等等
- 視圖約束適應尺寸相關的擴展 UIView (UIConstraintBasedLayoutFittingSize),主要用於獲取持有約束的視圖大小及其區域內的視圖大小
- 視圖布局引導相關的擴展 UIView (UILayoutGuideSupport),主要定義了視圖布局所需的一些屬性,類似中心點、上下左右寬高等屬性
- 視圖約束布局調試相關的擴展 UIView (UIConstraintBasedLayoutDebugging)
- 視圖快照相關的擴展 UIView (UISnapshotting)
下面是UIView.h文件的源碼分析,以下內容參考自:ios開發 之 UIView詳解。
1 #import <Foundation/Foundation.h> 2 #import <QuartzCore/QuartzCore.h> 3 #import <UIKit/UIResponder.h> 4 #import <UIKit/UIInterface.h> 5 #import <UIKit/UIKitDefines.h> 6 #import <UIKit/UIAppearance.h> 7 #import <UIKit/UIDynamicBehavior.h> 8 #import <UIKit/NSLayoutConstraint.h> 9 #import <UIKit/UITraitCollection.h> 10 #import <UIKit/UIFocus.h> 11 12 NS_ASSUME_NONNULL_BEGIN 13 14 /** 動畫的曲線枚舉 */ 15 typedef NS_ENUM(NSInteger, UIViewAnimationCurve) { 16 UIViewAnimationCurveEaseInOut, //!< 慢進慢出(默認值). 17 UIViewAnimationCurveEaseIn, //!< 慢進. 18 UIViewAnimationCurveEaseOut, //!< 慢出. 19 UIViewAnimationCurveLinear, //!< 勻速. 20 }; 21 22 //!< UIView內容填充模式. 23 typedef NS_ENUM(NSInteger, UIViewContentMode) { 24 UIViewContentModeScaleToFill, //!< 縮放內容到合適比例大小. 25 UIViewContentModeScaleAspectFit, //!< 縮放內容到合適的大小,邊界多余部分透明. 26 UIViewContentModeScaleAspectFill, //!< 縮放內容填充到指定大小,邊界多余的部分省略. 27 UIViewContentModeRedraw, //!< 重繪視圖邊界 (需調用 -setNeedsDisplay). 28 UIViewContentModeCenter, //!< 視圖保持等比縮放. 29 UIViewContentModeTop, //!< 視圖頂部對齊. 30 UIViewContentModeBottom, //!< 視圖底部對齊. 31 UIViewContentModeLeft, //!< 視圖左側對齊. 32 UIViewContentModeRight, //!< 視圖右側對齊. 33 UIViewContentModeTopLeft, //!< 視圖左上角對齊. 34 UIViewContentModeTopRight, //!< 視圖右上角對齊. 35 UIViewContentModeBottomLeft, //!< 視圖左下角對齊. 36 UIViewContentModeBottomRight, //!< 視圖右下角對齊. 37 }; 38 39 /** UIView動畫過渡效果 */ 40 typedef NS_ENUM(NSInteger, UIViewAnimationTransition) { 41 UIViewAnimationTransitionNone, //!< 無效果. 42 UIViewAnimationTransitionFlipFromLeft, //!< 沿視圖垂直中心軸左到右移動. 43 UIViewAnimationTransitionFlipFromRight, //!< 沿視圖垂直中心軸右到左移動. 44 UIViewAnimationTransitionCurlUp, //!< 由底部向上卷起. 45 UIViewAnimationTransitionCurlDown, //!< 由頂部向下展開. 46 }; 47 48 /** 自動調整大小方式 */ 49 typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) { 50 UIViewAutoresizingNone = 0, //!< 不自動調整. 51 UIViewAutoresizingFlexibleLeftMargin = 1 << 0,//!< 自動調整與superView左邊的距離,保證與superView右邊的距離不變. 52 UIViewAutoresizingFlexibleWidth = 1 << 1,//!< 自動調整自己的寬度,保證與superView左邊和右邊的距離不變. 53 UIViewAutoresizingFlexibleRightMargin = 1 << 2,//!< 自動調整與superView的右邊距離,保證與superView左邊的距離不變. 54 UIViewAutoresizingFlexibleTopMargin = 1 << 3,//!< 自動調整與superView頂部的距離,保證與superView底部的距離不變. 55 UIViewAutoresizingFlexibleHeight = 1 << 4,//!< 自動調整自己的高度,保證與superView頂部和底部的距離不變. 56 UIViewAutoresizingFlexibleBottomMargin = 1 << 5 //!< 自動調整與superView底部的距離,也就是說,與superView頂部的距離不變. 57 }; 58 59 /** UIView動畫選項 */ 60 typedef NS_OPTIONS(NSUInteger, UIViewAnimationOptions) { 61 UIViewAnimationOptionLayoutSubviews = 1 << 0, //!< 動畫過程中保證子視圖跟隨運動. 62 UIViewAnimationOptionAllowUserInteraction = 1 << 1, //!< 動畫過程中允許用戶交互. 63 UIViewAnimationOptionBeginFromCurrentState = 1 << 2, //!< 所有視圖從當前狀態開始運行. 64 UIViewAnimationOptionRepeat = 1 << 3, //!< 重復運行動畫. 65 UIViewAnimationOptionAutoreverse = 1 << 4, //!< 動畫運行到結束點后仍然以動畫方式回到初始點. 66 UIViewAnimationOptionOverrideInheritedDuration = 1 << 5, //!< 忽略嵌套動畫時間設置. 67 UIViewAnimationOptionOverrideInheritedCurve = 1 << 6, //!< 忽略嵌套動畫速度設置. 68 UIViewAnimationOptionAllowAnimatedContent = 1 << 7, //!< 動畫過程中重繪視圖(注意僅僅適用於轉場動畫). 69 UIViewAnimationOptionShowHideTransitionViews = 1 << 8, //!< 視圖切換時直接隱藏舊視圖、顯示新視圖,而不是將舊視圖從父視圖移除(僅僅適用於轉場動畫). 70 UIViewAnimationOptionOverrideInheritedOptions = 1 << 9, //!< 不繼承父動畫設置或動畫類型. 71 72 UIViewAnimationOptionCurveEaseInOut = 0 << 16, //!< 動畫先緩慢,然后逐漸加速. 73 UIViewAnimationOptionCurveEaseIn = 1 << 16, //!< 動畫逐漸變慢. 74 UIViewAnimationOptionCurveEaseOut = 2 << 16, //!< 動畫逐漸加速. 75 UIViewAnimationOptionCurveLinear = 3 << 16, //!< 動畫勻速執行,默認值. 76 77 UIViewAnimationOptionTransitionNone = 0 << 20, //!< 沒有轉場動畫效果. 78 UIViewAnimationOptionTransitionFlipFromLeft = 1 << 20, //!< 從左側翻轉效果. 79 UIViewAnimationOptionTransitionFlipFromRight = 2 << 20, //!< 從右側翻轉效果. 80 UIViewAnimationOptionTransitionCurlUp = 3 << 20, //!< 向后翻頁的動畫過渡效果. 81 UIViewAnimationOptionTransitionCurlDown = 4 << 20, //!< 向前翻頁的動畫過渡效果. 82 UIViewAnimationOptionTransitionCrossDissolve = 5 << 20, //!< 舊視圖溶解消失顯示下一個新視圖的效果. 83 UIViewAnimationOptionTransitionFlipFromTop = 6 << 20, //!< 從上方翻轉效果. 84 UIViewAnimationOptionTransitionFlipFromBottom = 7 << 20, //!< 從底部翻轉效果. 85 86 UIViewAnimationOptionPreferredFramesPerSecondDefault = 0 << 24, //!< 默認的幀每秒. 87 UIViewAnimationOptionPreferredFramesPerSecond60 = 3 << 24, //!< 60幀每秒的幀速率. 88 UIViewAnimationOptionPreferredFramesPerSecond30 = 7 << 24, //!< 30幀每秒的幀速率. 89 90 } NS_ENUM_AVAILABLE_IOS(4_0); 91 92 typedef NS_OPTIONS(NSUInteger, UIViewKeyframeAnimationOptions) { 93 UIViewKeyframeAnimationOptionLayoutSubviews = UIViewAnimationOptionLayoutSubviews, //!< 動畫過程中保證子視圖跟隨運動. 94 UIViewKeyframeAnimationOptionAllowUserInteraction = UIViewAnimationOptionAllowUserInteraction, //!< 動畫過程中允許用戶交互. 95 UIViewKeyframeAnimationOptionBeginFromCurrentState = UIViewAnimationOptionBeginFromCurrentState, //!< 所有視圖從當前狀態開始運行. 96 UIViewKeyframeAnimationOptionRepeat = UIViewAnimationOptionRepeat, //!< 重復運行動畫. 97 UIViewKeyframeAnimationOptionAutoreverse = UIViewAnimationOptionAutoreverse, //!< 動畫運行到結束點后仍然以動畫方式回到初始點. 98 UIViewKeyframeAnimationOptionOverrideInheritedDuration = UIViewAnimationOptionOverrideInheritedDuration, //!< 忽略嵌套動畫時間設置. 99 UIViewKeyframeAnimationOptionOverrideInheritedOptions = UIViewAnimationOptionOverrideInheritedOptions, //!< 不繼承父動畫設置或動畫類型. 100 101 UIViewKeyframeAnimationOptionCalculationModeLinear = 0 << 10, //!< 連續運算模式, 默認. 102 UIViewKeyframeAnimationOptionCalculationModeDiscrete = 1 << 10, //!< 離散運算模式. 103 UIViewKeyframeAnimationOptionCalculationModePaced = 2 << 10, //!< 均勻執行運算模式. 104 UIViewKeyframeAnimationOptionCalculationModeCubic = 3 << 10, //!< 平滑運算模式. 105 UIViewKeyframeAnimationOptionCalculationModeCubicPaced = 4 << 10 //!< 平滑均勻運算模式. 106 } NS_ENUM_AVAILABLE_IOS(7_0); 107 108 typedef NS_ENUM(NSUInteger, UISystemAnimation) { 109 UISystemAnimationDelete, //!< 系統刪除動畫 110 } NS_ENUM_AVAILABLE_IOS(7_0); 111 112 typedef NS_ENUM(NSInteger, UIViewTintAdjustmentMode) { 113 UIViewTintAdjustmentModeAutomatic, //!< 自動的,與父視圖相同. 114 115 UIViewTintAdjustmentModeNormal, //!< 未經修改的. 116 UIViewTintAdjustmentModeDimmed, //!< 飽和、暗淡的原始色. 117 } NS_ENUM_AVAILABLE_IOS(7_0); 118 119 typedef NS_ENUM(NSInteger, UISemanticContentAttribute) { 120 UISemanticContentAttributeUnspecified = 0, //!< 未指定,默認值 121 UISemanticContentAttributePlayback, //!< 打開/ RW / FF等播放控制按鈕 122 UISemanticContentAttributeSpatial, //!< 控制導致某種形式的定向改變UI中,如分段控制文本對齊方式或在游戲中方向鍵 123 UISemanticContentAttributeForceLeftToRight, //!< 視圖總是從左向右布局. 124 UISemanticContentAttributeForceRightToLeft //!< 視圖總是從右向左布局. 125 } NS_ENUM_AVAILABLE_IOS(9_0); 126 127 @protocol UICoordinateSpace <NSObject> 128 129 /** 將像素point由point所在視圖轉換到目標視圖view中,返回在目標視圖view中的像素值 */ 130 - (CGPoint)convertPoint:(CGPoint)point toCoordinateSpace:(id <UICoordinateSpace>)coordinateSpace NS_AVAILABLE_IOS(8_0); 131 /** 將像素point由point所在視圖轉換到目標視圖view中,返回在目標視圖view中的像素值 */ 132 - (CGPoint)convertPoint:(CGPoint)point fromCoordinateSpace:(id <UICoordinateSpace>)coordinateSpace NS_AVAILABLE_IOS(8_0); 133 /** 將rect由rect所在視圖轉換到目標視圖view中,返回在目標視圖view中的rect */ 134 - (CGRect)convertRect:(CGRect)rect toCoordinateSpace:(id <UICoordinateSpace>)coordinateSpace NS_AVAILABLE_IOS(8_0); 135 /** 將rect從view中轉換到當前視圖中,返回在當前視圖中的rect */ 136 - (CGRect)convertRect:(CGRect)rect fromCoordinateSpace:(id <UICoordinateSpace>)coordinateSpace NS_AVAILABLE_IOS(8_0); 137 138 /** 獲取bounds */ 139 @property (readonly, nonatomic) CGRect bounds NS_AVAILABLE_IOS(8_0); 140 141 @end 142 143 @class UIBezierPath, UIEvent, UIWindow, UIViewController, UIColor, UIGestureRecognizer, UIMotionEffect, CALayer, UILayoutGuide; 144 145 NS_CLASS_AVAILABLE_IOS(2_0) @interface UIView : UIResponder <NSCoding, UIAppearance, UIAppearanceContainer, UIDynamicItem, UITraitEnvironment, UICoordinateSpace, UIFocusItem, CALayerDelegate> 146 147 /** 返回主layer所使用的類 */ 148 #if UIKIT_DEFINE_AS_PROPERTIES 149 @property(class, nonatomic, readonly) Class layerClass; 150 #else 151 + (Class)layerClass; 152 #endif 153 154 /** 通過Frame初始化UI對象 */ 155 - (instancetype)initWithFrame:(CGRect)frame NS_DESIGNATED_INITIALIZER; 156 /** 用於xib初始化 */ 157 - (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER; 158 159 /** 設置用戶交互,默認YES允許用戶交互 */ 160 @property(nonatomic,getter=isUserInteractionEnabled) BOOL userInteractionEnabled; 161 /** 控件標記(父控件可以通過tag找到對應的子控件),默認為0 */ 162 @property(nonatomic) NSInteger tag; 163 /** 視圖圖層(可以用來設置圓角效果/陰影效果) */ 164 @property(nonatomic,readonly,strong) CALayer *layer; 165 166 /** 返回是否可以成為焦點, 默認NO */ 167 #if UIKIT_DEFINE_AS_PROPERTIES 168 @property(nonatomic,readonly) BOOL canBecomeFocused NS_AVAILABLE_IOS(9_0); 169 #else 170 - (BOOL)canBecomeFocused NS_AVAILABLE_IOS(9_0); 171 #endif 172 /** 是否可以被聚焦 */ 173 @property (readonly, nonatomic, getter=isFocused) BOOL focused NS_AVAILABLE_IOS(9_0); 174 175 /** 左右滑動翻轉效果 */ 176 @property (nonatomic) UISemanticContentAttribute semanticContentAttribute NS_AVAILABLE_IOS(9_0); 177 178 /** 獲取視圖的方向 */ 179 + (UIUserInterfaceLayoutDirection)userInterfaceLayoutDirectionForSemanticContentAttribute:(UISemanticContentAttribute)attribute NS_AVAILABLE_IOS(9_0); 180 181 /** 獲取相對於指定視圖的界面方向 */ 182 + (UIUserInterfaceLayoutDirection)userInterfaceLayoutDirectionForSemanticContentAttribute:(UISemanticContentAttribute)semanticContentAttribute relativeToLayoutDirection:(UIUserInterfaceLayoutDirection)layoutDirection NS_AVAILABLE_IOS(10_0); 183 184 /** 返回即時內容的布局的方向 */ 185 @property (readonly, nonatomic) UIUserInterfaceLayoutDirection effectiveUserInterfaceLayoutDirection NS_AVAILABLE_IOS(10_0); 186 187 @end 188 189 @interface UIView(UIViewGeometry) 190 191 /** 位置和尺寸(以父控件的左上角為坐標原點(0, 0)) */ 192 @property(nonatomic) CGRect frame; 193 194 /** 位置和尺寸(以自己的左上角為坐標原點(0, 0)) */ 195 @property(nonatomic) CGRect bounds; 196 /** 中心點(以父控件的左上角為坐標原點(0, 0)) */ 197 @property(nonatomic) CGPoint center; 198 /** 變形屬性(平移\縮放\旋轉) */ 199 @property(nonatomic) CGAffineTransform transform; 200 /** 視圖內容的縮放比例 */ 201 @property(nonatomic) CGFloat contentScaleFactor NS_AVAILABLE_IOS(4_0); 202 203 /** 是否支持多點觸摸,默認NO */ 204 @property(nonatomic,getter=isMultipleTouchEnabled) BOOL multipleTouchEnabled __TVOS_PROHIBITED; 205 /** 是否獨占整個Touch事件,默認NO */ 206 @property(nonatomic,getter=isExclusiveTouch) BOOL exclusiveTouch __TVOS_PROHIBITED; 207 208 /** 在指定點上點擊測試指定事件 */ 209 - (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event; 210 /** 判斷當前的點擊或者觸摸事件的點是否在當前的view中,默認返回YES */ 211 - (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event; 212 213 /** 將像素point由point所在視圖轉換到目標視圖view中,返回在目標視圖view中的像素值 */ 214 - (CGPoint)convertPoint:(CGPoint)point toView:(nullable UIView *)view; 215 /** 將像素point由point所在視圖轉換到目標視圖view中,返回在目標視圖view中的像素值 */ 216 - (CGPoint)convertPoint:(CGPoint)point fromView:(nullable UIView *)view; 217 /** 將rect由rect所在視圖轉換到目標視圖view中,返回在目標視圖view中的rect */ 218 - (CGRect)convertRect:(CGRect)rect toView:(nullable UIView *)view; 219 /** 將rect從view中轉換到當前視圖中,返回在當前視圖中的rect */ 220 - (CGRect)convertRect:(CGRect)rect fromView:(nullable UIView *)view; 221 222 /** 自動調整子視圖尺寸,默認YES則會根據autoresizingMask屬性自動調整子視圖尺寸 */ 223 @property(nonatomic) BOOL autoresizesSubviews; 224 /** 自動調整子視圖與父視圖的位置,默認UIViewAutoresizingNone */ 225 @property(nonatomic) UIViewAutoresizing autoresizingMask; 226 227 /** 返回“最佳”大小適合給定的大小 */ 228 - (CGSize)sizeThatFits:(CGSize)size; 229 /** 調整為剛好合適子視圖大小 */ 230 - (void)sizeToFit; 231 232 @end 233 234 @interface UIView(UIViewHierarchy) 235 236 /** 獲取父視圖 */ 237 @property(nullable, nonatomic,readonly) UIView *superview; 238 /** 獲取所有子視圖 */ 239 @property(nonatomic,readonly,copy) NSArray<__kindof UIView *> *subviews; 240 /** 獲取視圖所在的Window */ 241 @property(nullable, nonatomic,readonly) UIWindow *window; 242 243 /** 從父視圖中移除控件 */ 244 - (void)removeFromSuperview; 245 /** 插入子視圖(將子視圖插入到subviews數組中index這個位置) */ 246 - (void)insertSubview:(UIView *)view atIndex:(NSInteger)index; 247 /** 交換subviews數組中所存放子視圖的位置 */ 248 - (void)exchangeSubviewAtIndex:(NSInteger)index1 withSubviewAtIndex:(NSInteger)index2; 249 250 /** 添加子視圖(新添加的視圖在subviews數組的后面, 顯示在最上面) */ 251 - (void)addSubview:(UIView *)view; 252 /** 插入子視圖(將子視圖插到siblingSubview之下) */ 253 - (void)insertSubview:(UIView *)view belowSubview:(UIView *)siblingSubview; 254 /** 插入子視圖(將子視圖插到siblingSubview之上) */ 255 - (void)insertSubview:(UIView *)view aboveSubview:(UIView *)siblingSubview; 256 257 /** 將子視圖拉到最上面來顯示 */ 258 - (void)bringSubviewToFront:(UIView *)view; 259 /** 將子視圖拉到最下面來顯示 */ 260 - (void)sendSubviewToBack:(UIView *)view; 261 262 ##pragma mark - 系統自動調用(留給子類去實現) 263 /** 添加自視圖完成后調用 */ 264 - (void)didAddSubview:(UIView *)subview; 265 /** 將要移除自視圖時調用 */ 266 - (void)willRemoveSubview:(UIView *)subview; 267 268 /** 將要移動到新父視圖時調用 */ 269 - (void)willMoveToSuperview:(nullable UIView *)newSuperview; 270 /** 移動到新父視圖完成后調用 */ 271 - (void)didMoveToSuperview; 272 /** 將要移動到新Window時調用 */ 273 - (void)willMoveToWindow:(nullable UIWindow *)newWindow; 274 /** 移動到新Window完成后調用 */ 275 - (void)didMoveToWindow; 276 277 /** 判斷view是否為子類 */ 278 - (BOOL)isDescendantOfView:(UIView *)view; 279 /** 通過tag獲得對應的子視圖 */ 280 - (nullable __kindof UIView *)viewWithTag:(NSInteger)tag; 281 282 /** 對現在有布局有調整更改后,使用這個方法進行更新 */ 283 - (void)setNeedsLayout; 284 /** 強制進行更新layout */ 285 - (void)layoutIfNeeded; 286 287 /** 控件的frame發生改變的時候就會調用,一般在這里重寫布局子控件的位置和尺寸 */ 288 - (void)layoutSubviews; 289 290 /** 設置view之間的間距,該屬性只對autolayout布局有效 */ 291 @property (nonatomic) UIEdgeInsets layoutMargins NS_AVAILABLE_IOS(8_0); 292 /** 是否將當前視圖的間距和父視圖相同,默認是NO */ 293 @property (nonatomic) BOOL preservesSuperviewLayoutMargins NS_AVAILABLE_IOS(8_0); 294 /** 改變view的layoutMargins這個屬性時,會觸發這個方法 */ 295 - (void)layoutMarginsDidChange NS_AVAILABLE_IOS(8_0); 296 297 /** 視圖間距引導 */ 298 @property(readonly,strong) UILayoutGuide *layoutMarginsGuide NS_AVAILABLE_IOS(9_0); 299 300 /** 獲取此區域的內的布局引導 */ 301 @property (nonatomic, readonly, strong) UILayoutGuide *readableContentGuide NS_AVAILABLE_IOS(9_0); 302 @end 303 304 @interface UIView(UIViewRendering) 305 306 /** 重寫drawRect方法,在可以這里進行繪圖操作。*/ 307 - (void)drawRect:(CGRect)rect; 308 309 /** 標記整個視圖的邊界矩形需要重繪, 調用這個方法會自動調用drawRect方法 */ 310 - (void)setNeedsDisplay; 311 /** 標記在指定區域內的視圖的邊界需要重繪, 調用這個方法會自動調用drawRect方法 */ 312 - (void)setNeedsDisplayInRect:(CGRect)rect; 313 314 /** 是否裁剪超出Bounds范圍的子控件,默認NO */ 315 @property(nonatomic) BOOL clipsToBounds; 316 /** 設置背景顏色,默認nil */ 317 @property(nullable, nonatomic,copy) UIColor *backgroundColor UI_APPEARANCE_SELECTOR; 318 /** 設置透明度(范圍0.0~1.0),默認1.0 */ 319 @property(nonatomic) CGFloat alpha; 320 /** 設置是否不透明,默認YES不透明 */ 321 @property(nonatomic,getter=isOpaque) BOOL opaque; 322 /** 視圖重繪前是否先清理以前的內容,默認YES */ 323 @property(nonatomic) BOOL clearsContextBeforeDrawing; 324 /** 設置是否隱藏,默認NO不隱藏 */ 325 @property(nonatomic,getter=isHidden) BOOL hidden; 326 /** 內容顯示的模式,默認UIViewContentModeScaleToFill */ 327 @property(nonatomic) UIViewContentMode contentMode; 328 /** 拉伸屬性,如圖片拉伸 */ 329 @property(nonatomic) CGRect contentStretch NS_DEPRECATED_IOS(3_0,6_0) __TVOS_PROHIBITED; 330 331 /** 蒙板view */ 332 @property(nullable, nonatomic,strong) UIView *maskView NS_AVAILABLE_IOS(8_0); 333 334 /** 改變應用程序的外觀的顏色。默認為nil */ 335 @property(null_resettable, nonatomic, strong) UIColor *tintColor NS_AVAILABLE_IOS(7_0); 336 337 /** 可以使tintColor變暗,因此整個視圖層次變暗 */ 338 @property(nonatomic) UIViewTintAdjustmentMode tintAdjustmentMode NS_AVAILABLE_IOS(7_0); 339 340 /** 覆蓋這個方法的目的是為了當tintColor改變的時候自定義一些行為 */ 341 - (void)tintColorDidChange NS_AVAILABLE_IOS(7_0); 342 343 @end 344 345 @interface UIView(UIViewAnimation) 346 347 /** 開始動畫 */ 348 + (void)beginAnimations:(nullable NSString *)animationID context:(nullable void *)context; 349 /** 提交動畫 */ 350 + (void)commitAnimations; 351 352 /** 設置動畫代理, 默認nil */ 353 + (void)setAnimationDelegate:(nullable id)delegate; 354 /** 動畫將要開始時執行方法(必須要先設置動畫代理), 默認NULL */ 355 + (void)setAnimationWillStartSelector:(nullable SEL)selector; 356 /** 動畫已結束時執行方法(必須要先設置動畫代理), 默認NULL */ 357 + (void)setAnimationDidStopSelector:(nullable SEL)selector; 358 /** 設置動畫時長, 默認0.2秒 */ 359 + (void)setAnimationDuration:(NSTimeInterval)duration; 360 /** 動畫延遲執行時間, 默認0.0秒 */ 361 + (void)setAnimationDelay:(NSTimeInterval)delay; 362 /** 設置在動畫塊內部動畫屬性改變的開始時間, 默認now ([NSDate date]) */ 363 + (void)setAnimationStartDate:(NSDate *)startDate; 364 /** 設置動畫曲線, 默認UIViewAnimationCurveEaseInOut */ 365 + (void)setAnimationCurve:(UIViewAnimationCurve)curve; 366 /** 動畫的重復播放次數, 默認0 */ 367 + (void)setAnimationRepeatCount:(float)repeatCount; 368 /** 設置是否自定翻轉當前的動畫效果, 默認NO */ 369 + (void)setAnimationRepeatAutoreverses:(BOOL)repeatAutoreverses; 370 /** 設置動畫從當前狀態開始播放, 默認NO */ 371 + (void)setAnimationBeginsFromCurrentState:(BOOL)fromCurrentState; 372 373 /** 在動畫塊中為視圖設置過渡動畫 */ 374 + (void)setAnimationTransition:(UIViewAnimationTransition)transition forView:(UIView *)view cache:(BOOL)cache; 375 376 /** 設置是否激活動畫 */ 377 + (void)setAnimationsEnabled:(BOOL)enabled; 378 /** 返回一個布爾值表示動畫是否結束 */ 379 #if UIKIT_DEFINE_AS_PROPERTIES 380 @property(class, nonatomic, readonly) BOOL areAnimationsEnabled; 381 #else 382 + (BOOL)areAnimationsEnabled; 383 #endif 384 /** 先檢查動畫當前是否啟用,然后禁止動畫,執行block內的方法,最后重新啟用動畫,而且這個方法不會阻塞基於CoreAnimation的動畫 */ 385 + (void)performWithoutAnimation:(void (NS_NOESCAPE ^)(void))actionsWithoutAnimation NS_AVAILABLE_IOS(7_0); 386 387 /** 當前動畫的持續時間 */ 388 #if UIKIT_DEFINE_AS_PROPERTIES 389 @property(class, nonatomic, readonly) NSTimeInterval inheritedAnimationDuration NS_AVAILABLE_IOS(9_0); 390 #else 391 + (NSTimeInterval)inheritedAnimationDuration NS_AVAILABLE_IOS(9_0); 392 #endif 393 394 @end 395 396 @interface UIView(UIViewAnimationWithBlocks) 397 398 /** 用於對一個或多個視圖的改變的持續時間、延時、選項動畫完成時的操作 */ 399 + (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); 400 401 /** 用於對一個或多個視圖的改變的持續時間、選項動畫完成時的操作,默認:delay = 0.0, options = 0 */ 402 + (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(4_0); 403 404 /** 用於對一個或多個視圖的改變的持續時間內動畫完成時的操作,默認:delay = 0.0, options = 0, completion = NULL */ 405 + (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations NS_AVAILABLE_IOS(4_0); 406 407 /** 使用與物理彈簧運動相對應的定時曲線執行視圖動畫 */ 408 + (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); 409 410 /** 為指定的容器視圖創建轉換動畫 */ 411 + (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); 412 413 /** 使用給定的參數在指定視圖之間創建轉換動畫 */ 414 + (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 415 416 /** 在一個或多個視圖上執行指定的系統提供的動畫,以及定義的可選並行動畫 */ 417 + (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); 418 419 @end 420 421 /** UIView的關鍵幀動畫 */ 422 @interface UIView (UIViewKeyframeAnimations) 423 424 /** 創建一個動畫塊對象,可用於為當前視圖設置基於關鍵幀的動畫 */ 425 + (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); 426 /** 添加指定開始時間、持續時間的關鍵幀動畫(起始和持續時間是0.0和1.0之間的值) */ 427 + (void)addKeyframeWithRelativeStartTime:(double)frameStartTime relativeDuration:(double)frameDuration animations:(void (^)(void))animations NS_AVAILABLE_IOS(7_0); 428 429 @end 430 431 @interface UIView (UIViewGestureRecognizers) 432 433 /** 當前視圖所附加的所有手勢識別器 */ 434 @property(nullable, nonatomic,copy) NSArray<__kindof UIGestureRecognizer *> *gestureRecognizers NS_AVAILABLE_IOS(3_2); 435 436 /** 添加一個手勢識別器 */ 437 - (void)addGestureRecognizer:(UIGestureRecognizer*)gestureRecognizer NS_AVAILABLE_IOS(3_2); 438 /** 移除一個手勢識別器 */ 439 - (void)removeGestureRecognizer:(UIGestureRecognizer*)gestureRecognizer NS_AVAILABLE_IOS(3_2); 440 441 /** 開始一個手勢識別器 */ 442 - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer NS_AVAILABLE_IOS(6_0); 443 444 @end 445 446 @interface UIView (UIViewMotionEffects) 447 448 /** 添加運動效果,當傾斜設備時視圖稍微改變其位置 */ 449 - (void)addMotionEffect:(UIMotionEffect *)effect NS_AVAILABLE_IOS(7_0); 450 451 /** 移除運動效果 */ 452 - (void)removeMotionEffect:(UIMotionEffect *)effect NS_AVAILABLE_IOS(7_0); 453 454 /** 所有添加的運動效果 */ 455 @property (copy, nonatomic) NSArray<__kindof UIMotionEffect *> *motionEffects NS_AVAILABLE_IOS(7_0); 456 457 @end 458 459 460 typedef NS_ENUM(NSInteger, UILayoutConstraintAxis) { 461 UILayoutConstraintAxisHorizontal = 0, //!< 水平約束. 462 UILayoutConstraintAxisVertical = 1 //!< 豎直約束. 463 }; 464 465 466 @interface UIView (UIConstraintBasedLayoutInstallingConstraints) 467 468 /** 獲取所有約束 */ 469 @property(nonatomic,readonly) NSArray<__kindof NSLayoutConstraint *> *constraints NS_AVAILABLE_IOS(6_0); 470 471 /** 添加一個約束 */ 472 - (void)addConstraint:(NSLayoutConstraint *)constraint NS_AVAILABLE_IOS(6_0); 473 /** 添加多個約束 */ 474 - (void)addConstraints:(NSArray<__kindof NSLayoutConstraint *> *)constraints NS_AVAILABLE_IOS(6_0); 475 /** 移除一個約束 */ 476 - (void)removeConstraint:(NSLayoutConstraint *)constraint NS_AVAILABLE_IOS(6_0); 477 /** 移除多個約束 */ 478 - (void)removeConstraints:(NSArray<__kindof NSLayoutConstraint *> *)constraints NS_AVAILABLE_IOS(6_0); 479 @end 480 481 482 @interface UIView (UIConstraintBasedLayoutCoreMethods) 483 /** 更新視圖和其子視圖的約束 */ 484 - (void)updateConstraintsIfNeeded NS_AVAILABLE_IOS(6_0); 485 /** 為視圖更新約束,可以重寫這個方法來設置當前view局部的布局約束 */ 486 - (void)updateConstraints NS_AVAILABLE_IOS(6_0) NS_REQUIRES_SUPER; 487 /** 視圖的約束是否需要更新 */ 488 - (BOOL)needsUpdateConstraints NS_AVAILABLE_IOS(6_0); 489 /** 設置視圖的約束需要更新,調用這個方法,系統會調用updateConstraints去更新布局 */ 490 - (void)setNeedsUpdateConstraints NS_AVAILABLE_IOS(6_0); 491 @end 492 493 494 @interface UIView (UIConstraintBasedCompatibility) 495 496 /** 是否啟用自動布局約束,默認YES. IB默認是NO */ 497 @property(nonatomic) BOOL translatesAutoresizingMaskIntoConstraints NS_AVAILABLE_IOS(6_0); 498 499 /** 是否使用約束布局 */ 500 #if UIKIT_DEFINE_AS_PROPERTIES 501 @property(class, nonatomic, readonly) BOOL requiresConstraintBasedLayout NS_AVAILABLE_IOS(6_0); 502 #else 503 + (BOOL)requiresConstraintBasedLayout NS_AVAILABLE_IOS(6_0); 504 #endif 505 506 @end 507 508 509 @interface UIView (UIConstraintBasedLayoutLayering) 510 511 /** 返回給定框架的視圖的對齊矩陣 */ 512 - (CGRect)alignmentRectForFrame:(CGRect)frame NS_AVAILABLE_IOS(6_0); 513 /** 返回給定對齊矩形的視圖的frame */ 514 - (CGRect)frameForAlignmentRect:(CGRect)alignmentRect NS_AVAILABLE_IOS(6_0); 515 516 /** 返回從視圖的frame上定義的對齊矩陣的邊框 */ 517 #if UIKIT_DEFINE_AS_PROPERTIES 518 @property(nonatomic, readonly) UIEdgeInsets alignmentRectInsets NS_AVAILABLE_IOS(6_0); 519 #else 520 - (UIEdgeInsets)alignmentRectInsets NS_AVAILABLE_IOS(6_0); 521 #endif 522 523 /** 返回滿足基線約束條件的視圖 */ 524 - (UIView *)viewForBaselineLayout NS_DEPRECATED_IOS(6_0, 9_0, "Override -viewForFirstBaselineLayout or -viewForLastBaselineLayout as appropriate, instead") __TVOS_PROHIBITED; 525 526 /** 返回用於滿足第一基線約束的視圖 */ 527 @property(readonly,strong) UIView *viewForFirstBaselineLayout NS_AVAILABLE_IOS(9_0); 528 529 /** 返回用於滿足上次基線約束的視圖 */ 530 @property(readonly,strong) UIView *viewForLastBaselineLayout NS_AVAILABLE_IOS(9_0); 531 532 533 UIKIT_EXTERN const CGFloat UIViewNoIntrinsicMetric NS_AVAILABLE_IOS(6_0); // -1 534 /** 返回接收對象的原本大小 */ 535 #if UIKIT_DEFINE_AS_PROPERTIES 536 @property(nonatomic, readonly) CGSize intrinsicContentSize NS_AVAILABLE_IOS(6_0); 537 #else 538 - (CGSize)intrinsicContentSize NS_AVAILABLE_IOS(6_0); 539 #endif 540 /** 廢除視圖原本內容的size */ 541 - (void)invalidateIntrinsicContentSize NS_AVAILABLE_IOS(6_0); 542 543 /** 設置當視圖要變大時,視圖的壓縮改變方式,返回一個優先權(確定view有多大的優先級阻止自己變大) */ 544 - (UILayoutPriority)contentHuggingPriorityForAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0); 545 /** 設置放先權 */ 546 - (void)setContentHuggingPriority:(UILayoutPriority)priority forAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0); 547 548 /** 設置當視圖要變小時,視圖的壓縮改變方式,是水平縮小還是垂直縮小,並返回一個優先權(確定有多大的優先級阻止自己變小) */ 549 - (UILayoutPriority)contentCompressionResistancePriorityForAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0); 550 /** 設置優先權 */ 551 - (void)setContentCompressionResistancePriority:(UILayoutPriority)priority forAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0); 552 @end 553 554 // Size To Fit 555 556 UIKIT_EXTERN const CGSize UILayoutFittingCompressedSize NS_AVAILABLE_IOS(6_0); 557 UIKIT_EXTERN const CGSize UILayoutFittingExpandedSize NS_AVAILABLE_IOS(6_0); 558 559 @interface UIView (UIConstraintBasedLayoutFittingSize) 560 /** 返回滿足持有約束的視圖的size */ 561 - (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize NS_AVAILABLE_IOS(6_0); 562 /** 返回滿足它所包含的約束的視圖的大小 */ 563 - (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize withHorizontalFittingPriority:(UILayoutPriority)horizontalFittingPriority verticalFittingPriority:(UILayoutPriority)verticalFittingPriority NS_AVAILABLE_IOS(8_0); 564 @end 565 566 @interface UIView (UILayoutGuideSupport) 567 568 /** 此視圖擁有布局向導對象的數組 */ 569 @property(nonatomic,readonly,copy) NSArray<__kindof UILayoutGuide *> *layoutGuides NS_AVAILABLE_IOS(9_0); 570 571 /** 向視圖中添加布局向導 */ 572 - (void)addLayoutGuide:(UILayoutGuide *)layoutGuide NS_AVAILABLE_IOS(9_0); 573 574 /** 向視圖中添加布局向導 */ 575 - (void)removeLayoutGuide:(UILayoutGuide *)layoutGuide NS_AVAILABLE_IOS(9_0); 576 @end 577 578 @class NSLayoutXAxisAnchor,NSLayoutYAxisAnchor,NSLayoutDimension; 579 @interface UIView (UIViewLayoutConstraintCreation) 580 /** 布局視圖的前緣框的布局錨點 */ 581 @property(readonly, strong) NSLayoutXAxisAnchor *leadingAnchor NS_AVAILABLE_IOS(9_0); 582 /** 布局視圖的后緣邊框的布局錨點 */ 583 @property(readonly, strong) NSLayoutXAxisAnchor *trailingAnchor NS_AVAILABLE_IOS(9_0); 584 /** 布局視圖的左邊框的布局錨點 */ 585 @property(readonly, strong) NSLayoutXAxisAnchor *leftAnchor NS_AVAILABLE_IOS(9_0); 586 /** 布局視圖的右邊框的布局錨點 */ 587 @property(readonly, strong) NSLayoutXAxisAnchor *rightAnchor NS_AVAILABLE_IOS(9_0); 588 /** 布局視圖的頂邊框的布局錨點 */ 589 @property(readonly, strong) NSLayoutYAxisAnchor *topAnchor NS_AVAILABLE_IOS(9_0); 590 /** 布局視圖的底邊框的布局錨點 */ 591 @property(readonly, strong) NSLayoutYAxisAnchor *bottomAnchor NS_AVAILABLE_IOS(9_0); 592 /** 布局視圖的寬度 */ 593 @property(readonly, strong) NSLayoutDimension *widthAnchor NS_AVAILABLE_IOS(9_0); 594 /** 布局視圖的高度 */ 595 @property(readonly, strong) NSLayoutDimension *heightAnchor NS_AVAILABLE_IOS(9_0); 596 /** 布局視圖的水平中心軸 */ 597 @property(readonly, strong) NSLayoutXAxisAnchor *centerXAnchor NS_AVAILABLE_IOS(9_0); 598 /** 布局視圖的垂直中心軸 */ 599 @property(readonly, strong) NSLayoutYAxisAnchor *centerYAnchor NS_AVAILABLE_IOS(9_0); 600 /** 一個代表對視圖中的文本的最高線基線布置錨 */ 601 @property(readonly, strong) NSLayoutYAxisAnchor *firstBaselineAnchor NS_AVAILABLE_IOS(9_0); 602 /** 一個代表對視圖中的文本的最低線基線布置錨 */ 603 @property(readonly, strong) NSLayoutYAxisAnchor *lastBaselineAnchor NS_AVAILABLE_IOS(9_0); 604 605 @end 606 607 @interface UIView (UIConstraintBasedLayoutDebugging) 608 609 /** 獲得實體在不同方向上所有的布局約束 */ 610 - (NSArray<__kindof NSLayoutConstraint *> *)constraintsAffectingLayoutForAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0); 611 612 /** 可以知道當前視圖的布局是否會有歧義 */ 613 #if UIKIT_DEFINE_AS_PROPERTIES 614 @property(nonatomic, readonly) BOOL hasAmbiguousLayout NS_AVAILABLE_IOS(6_0); 615 #else 616 - (BOOL)hasAmbiguousLayout NS_AVAILABLE_IOS(6_0); 617 #endif 618 619 /** 這個方法會隨機改變視圖的layout到另外一個有效的layout。這樣我們就可以很清楚的看到哪一個layout導致了整體的布局約束出現了錯誤,或者我們應該增加更多的布局約束 */ 620 - (void)exerciseAmbiguityInLayout NS_AVAILABLE_IOS(6_0); 621 @end 622 623 /** 約束調試,只在DEBUG環境下被調用 */ 624 @interface UILayoutGuide (UIConstraintBasedLayoutDebugging) 625 626 /** 獲得實體在不同方向上所有的布局約束 */ 627 - (NSArray<__kindof NSLayoutConstraint *> *)constraintsAffectingLayoutForAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(10_0); 628 629 /** 可以知道當前視圖的布局是否會有歧義 */ 630 #if UIKIT_DEFINE_AS_PROPERTIES 631 @property(nonatomic, readonly) BOOL hasAmbiguousLayout NS_AVAILABLE_IOS(10_0); 632 #else 633 - (BOOL)hasAmbiguousLayout NS_AVAILABLE_IOS(10_0); 634 #endif 635 @end 636 637 #pragma mark - View狀態保存恢復 638 @interface UIView (UIStateRestoration) 639 /** 標示是否支持保存,恢復視圖狀態信息 */ 640 @property (nullable, nonatomic, copy) NSString *restorationIdentifier NS_AVAILABLE_IOS(6_0); 641 /** 保存視圖狀態相關的信息 */ 642 - (void) encodeRestorableStateWithCoder:(NSCoder *)coder NS_AVAILABLE_IOS(6_0); 643 /** 恢復和保持視圖狀態相關信息 */ 644 - (void) decodeRestorableStateWithCoder:(NSCoder *)coder NS_AVAILABLE_IOS(6_0); 645 @end 646 647 #pragma mark - View快照 648 @interface UIView (UISnapshotting) 649 /** 將當前顯示的view截取成一個新的view */ 650 - (nullable UIView *)snapshotViewAfterScreenUpdates:(BOOL)afterUpdates NS_AVAILABLE_IOS(7_0); 651 /** 縮放一個view默認是從中心點進行縮放的 */ 652 - (nullable UIView *)resizableSnapshotViewFromRect:(CGRect)rect afterScreenUpdates:(BOOL)afterUpdates withCapInsets:(UIEdgeInsets)capInsets NS_AVAILABLE_IOS(7_0); 653 /** 屏幕快照 */ 654 - (BOOL)drawViewHierarchyInRect:(CGRect)rect afterScreenUpdates:(BOOL)afterUpdates NS_AVAILABLE_IOS(7_0); 655 @end 656 657 NS_ASSUME_NONNULL_END