淺談iOS 11.0中UIView 都更改了什么?

版本記錄

版本號(hào) 時(shí)間
V1.0 2018.01.19

前言

2017年iOS版本更新到了11.0的系統(tǒng),新機(jī)器比如iPhone X都是預(yù)裝11.0的系統(tǒng),而我們的UIKit框架中的UIView類都做了哪些更改?接下來(lái)我們就看一下iOS11.0中UIView類的改變暮芭,都是在分類UIViewHierarchy中有五處更改,下面我們就詳細(xì)的看一下欲低。

@property (nonatomic) NSDirectionalEdgeInsets directionalLayoutMargins API_AVAILABLE(ios(11.0),tvos(11.0));

先看一下谴麦,API給的注釋

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

翻譯過(guò)來(lái)就是

當(dāng)用戶界面方向?yàn)長(zhǎng)TR時(shí),directionalLayoutMargins.leading用于左側(cè)伸头,當(dāng)用戶界面方向?yàn)镽TL時(shí),directionalLayoutMargins用于右側(cè)舷蟀;DirectionLayoutMargins.trailing則反之恤磷。

這里NSDirectionalEdgeInsets 是什么呢?我們繼續(xù)看一下野宜。

/* Specifically for use in methods and functions supporting user interface layout direction
 */
typedef struct NSDirectionalEdgeInsets {
    CGFloat top, leading, bottom, trailing;  // specify amount to inset (positive) for each of the edges. values can be negative to 'outset'
} NSDirectionalEdgeInsets API_AVAILABLE(ios(11.0),tvos(11.0),watchos(4.0));

其實(shí)就是一個(gè)結(jié)構(gòu)體扫步,大家應(yīng)該對(duì)這個(gè)結(jié)構(gòu)很熟悉,雖然也是iOS11.0才出來(lái)匈子,但是順序還是上左下右這個(gè)順序河胎,正數(shù)表示縮進(jìn),負(fù)數(shù)表示外擴(kuò)虎敦。

說(shuō)了這么多游岳,這個(gè)屬性有啥用呢?

這個(gè)屬性一般是在中東的某些國(guó)家有用其徙,與LTR 和 RTL語(yǔ)言有關(guān)胚迫,例子:當(dāng)你設(shè)置了trailing = 30;當(dāng)在一個(gè)right to left 語(yǔ)言下trailing的值會(huì)被設(shè)置在view的左邊唾那,可以通過(guò)layout margins的left屬性讀出該值访锻。如下圖所示:

還有其他一些更新。自從引入layout margins,當(dāng)將一個(gè)view添加到viewController時(shí)期犬, viewController會(huì)修復(fù)view的layoutMargins為UIKit定義的一個(gè)值河哑,這些調(diào)整對(duì)外是封閉的。從iOS11開(kāi)始龟虎,這些不再是一個(gè)固定的值璃谨,它們實(shí)際是最小值,你可以改變你的view的 layoutMargins為任意一個(gè)更大的值遣总。而且睬罗,viewController新增了一個(gè)屬性: viewRespectsSystemMinimumLayoutMargins,如果你設(shè)置該屬性為false旭斥,你就可以改變你的layout margins為任意你想設(shè)置的值容达,包括0,如下圖所示:


@property (nonatomic,readonly) UIEdgeInsets safeAreaInsets API_AVAILABLE(ios(11.0),tvos(11.0));

這是一個(gè)只讀屬性垂券,使用safeAreaLayoutGuidesafeAreaInsets用于獲取安全區(qū)域和邊距花盐。

下面我們繼續(xù)看一段代碼

@implementation ViewController

#pragma mark -  Override Base Function

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    NSString *edgeStr = NSStringFromUIEdgeInsets(self.view.safeAreaInsets);
    NSString *layoutFrmStr = NSStringFromCGRect(self.view.safeAreaLayoutGuide.layoutFrame);
    NSLog(@"viewDidLoad safeAreaInsets = %@, layoutFrame = %@", edgeStr, layoutFrmStr);
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    
    NSString *edgeStr = NSStringFromUIEdgeInsets(self.view.safeAreaInsets);
    NSString *layoutFrmStr = NSStringFromCGRect(self.view.safeAreaLayoutGuide.layoutFrame);
    NSLog(@"viewDidAppear safeAreaInsets = %@, layoutFrame = %@", edgeStr, layoutFrmStr);
}

@end

下面看一下輸出結(jié)果

2018-01-19 12:21:50.615003+0800 JJLayer_demo1[43966:28819180] viewDidLoad safeAreaInsets = {0, 0, 0, 0}, layoutFrame = {{0, 0}, {414, 736}}
2018-01-19 12:21:50.644033+0800 JJLayer_demo1[43966:28819180] viewDidAppear safeAreaInsets = {20, 0, 0, 0}, layoutFrame = {{0, 20}, {414, 716}}

從輸出可以看出來(lái),viewDidAppear里面菇爪,頂部變成了20算芯,也就是向下縮進(jìn)20,也就是頂部狀態(tài)欄凳宙。同樣原理熙揍,如果你的是一個(gè)UINavigationController那在顯示的時(shí)候view.safeAreaInsets就會(huì)變成{64, 0, 0, 0}。注意:在該VC下所有的UIView及其子類獲取到safeAreaInsets的值是相同的氏涩。


- (void)safeAreaInsetsDidChange API_AVAILABLE(ios(11.0),tvos(11.0));

由上面可以看見(jiàn)届囚,邊距的改變是在viewDidAppear方法里面更改的,但是具體是什么時(shí)候更改的呢是尖,其實(shí)就可以在UIView類里面重寫(xiě)safeAreaInsetsDidChange意系,可以獲取邊距發(fā)生改變的時(shí)機(jī)。


@property(nonatomic,readonly,strong) UILayoutGuide *safeAreaLayoutGuide API_AVAILABLE(ios(11.0),tvos(11.0));

這個(gè)也是一個(gè)只讀屬性饺汹,首先看一下英文注釋

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

safeAreaLayoutGuide的頂部指示視圖的不被遮擋的頂部邊緣(例如蛔添,不在狀態(tài)欄或?qū)Ш綑诤竺妫绻嬖诘脑挘?同樣的其他邊緣兜辞。

下面我們看一下這個(gè)UILayoutGuide

#import <CoreGraphics/CoreGraphics.h>
#import <Foundation/Foundation.h>

@class NSLayoutXAxisAnchor, NSLayoutYAxisAnchor, NSLayoutDimension;

NS_ASSUME_NONNULL_BEGIN
@class UIView;
/* UILayoutGuides will not show up in the view hierarchy, but may be used as items in
 an NSLayoutConstraint and represent a rectangle in the layout engine.
 
 Create a UILayoutGuide with -init, and add to a view with -[UIView addLayoutGuide:]
 before using it in a constraint.
 */
NS_CLASS_AVAILABLE_IOS(9_0)
@interface UILayoutGuide : NSObject <NSCoding>

/* The frame of the UILayoutGuide in its owningView's coordinate system.
 Valid by the time the owningView receives -layoutSubviews.
 */
@property(nonatomic,readonly) CGRect layoutFrame;

/* The guide must be added to a view with -[UIView addLayoutGuide:] before being used in a constraint.
 Do not use this property directly to change the owningView of a layout guide. Instead, use 
 -[UIView addLayoutGuide:] and -[UIView removeLayoutGuide:], which will use this property to 
 change the owningView.
 */
@property(nonatomic,weak,nullable) UIView *owningView;

/* For ease of debugging.
 'UI' prefix is reserved for UIKit-created layout guides.
 */
@property(nonatomic,copy) NSString *identifier;


/* Constraint creation conveniences. See NSLayoutAnchor.h for details.
 */
@property(nonatomic,readonly,strong) NSLayoutXAxisAnchor *leadingAnchor;
@property(nonatomic,readonly,strong) NSLayoutXAxisAnchor *trailingAnchor;
@property(nonatomic,readonly,strong) NSLayoutXAxisAnchor *leftAnchor;
@property(nonatomic,readonly,strong) NSLayoutXAxisAnchor *rightAnchor;
@property(nonatomic,readonly,strong) NSLayoutYAxisAnchor *topAnchor;
@property(nonatomic,readonly,strong) NSLayoutYAxisAnchor *bottomAnchor;
@property(nonatomic,readonly,strong) NSLayoutDimension *widthAnchor;
@property(nonatomic,readonly,strong) NSLayoutDimension *heightAnchor;
@property(nonatomic,readonly,strong) NSLayoutXAxisAnchor *centerXAnchor;
@property(nonatomic,readonly,strong) NSLayoutYAxisAnchor *centerYAnchor;

@end
NS_ASSUME_NONNULL_END

下面我們看代碼

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

#pragma mark -  Override Base Function

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    NSString *layoutFrmStr = NSStringFromCGRect(self.view.safeAreaLayoutGuide.layoutFrame);
    NSLog(@"viewDidLoad layoutFrame = %@", layoutFrmStr);
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    
    NSString *layoutFrmStr = NSStringFromCGRect(self.view.safeAreaLayoutGuide.layoutFrame);
    NSLog(@"viewDidLoad layoutFrame = %@", layoutFrmStr);
}

@end

用iphoneX運(yùn)行看結(jié)果迎瞧,下面我們看輸出結(jié)果

2018-01-19 14:34:34.519614+0800 JJLayer_demo1[44903:29054064] viewDidLoad layoutFrame = {{0, 0}, {375, 812}}
2018-01-19 14:34:34.658567+0800 JJLayer_demo1[44903:29054064] viewDidLoad layoutFrame = {{0, 44}, {375, 734}}

iphoneX的狀態(tài)欄是44.0,安全區(qū)域高度是812 - 44 - 34.0 = 734.0(頂部預(yù)留觸控區(qū)域)逸吵,這個(gè)代碼沒(méi)有導(dǎo)航和底部tabBar夹攒。


@property (nonatomic) BOOL insetsLayoutMarginsFromSafeArea API_AVAILABLE(ios(11.0),tvos(11.0)); // Default: YES

這是個(gè)BOOL屬性,默認(rèn)為YES胁塞。

如果你不想讓safeAreaInsets影響你的視圖布局咏尝,則可以將insetsLayoutMarginsFromSafeArea設(shè)置為NO压语,所有的視圖布局將會(huì)忽略safeAreaInsets這個(gè)屬性了。要注意的是编检,insetsLayoutMarginsFromSafeArea僅用于使用代碼實(shí)現(xiàn)AutoLayout(如果你是使用Xib或者SB布局你的視圖胎食,那么對(duì)該屬性的設(shè)置是無(wú)效的,至少我沒(méi)有發(fā)現(xiàn)怎么可以讓布局產(chǎn)生變化)允懂,即使該屬性為NO厕怜,視圖的safeAreaInsets還是一樣有值,而且安全區(qū)域變更方法safeAreaInsetsDidChange一樣被調(diào)用蕾总。

看下面這段代碼

#import "ViewController.h"

@interface ViewController ()

@property (nonatomic, strong) UITableView *tableView;

@end

@implementation ViewController

#pragma mark -  Override Base Function

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor blueColor];
    
    //insetsLayoutMarginsFromSafeArea默認(rèn)為YES粥航,所有的視圖布局將會(huì)受到safeAreaInsets這個(gè)屬性影響
    self.view.insetsLayoutMarginsFromSafeArea = YES;
    
    self.tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
    self.tableView.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:self.tableView];
    
    NSArray<__kindof NSLayoutConstraint *> *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[tableView]-|" options:0 metrics:nil views:@{@"tableView" : self.tableView}];
    [self.view addConstraints:constraints];
    
    constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[tableView]|" options:0 metrics:nil views:@{@"tableView" : self.tableView}];
    [self.view addConstraints:constraints];
}

@end

這里面self.view.insetsLayoutMarginsFromSafeArea = YES;取默認(rèn)值,所有的視圖布局將會(huì)受到safeAreaInsets這個(gè)屬性影響生百,如下圖所示递雀。

下面self.view.insetsLayoutMarginsFromSafeArea = NO;,這么設(shè)置后看一下效果蚀浆,這個(gè)時(shí)候布局就不會(huì)受到safeAreaInsets這個(gè)屬性影響缀程。

可以看見(jiàn)不受上下邊距的影響了。

后記

這篇就結(jié)束了市俊,后面還會(huì)持續(xù)介紹別的方面的知識(shí)杨凑。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市摆昧,隨后出現(xiàn)的幾起案子撩满,更是在濱河造成了極大的恐慌,老刑警劉巖绅你,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鹦牛,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡勇吊,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門(mén)窍仰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)汉规,“玉大人,你說(shuō)我怎么就攤上這事驹吮≌胧罚” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵碟狞,是天一觀的道長(zhǎng)啄枕。 經(jīng)常有香客問(wèn)我,道長(zhǎng)族沃,這世上最難降的妖魔是什么频祝? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任泌参,我火速辦了婚禮,結(jié)果婚禮上常空,老公的妹妹穿的比我還像新娘沽一。我一直安慰自己,他們只是感情好漓糙,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布铣缠。 她就那樣靜靜地躺著,像睡著了一般昆禽。 火紅的嫁衣襯著肌膚如雪蝗蛙。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,292評(píng)論 1 301
  • 那天醉鳖,我揣著相機(jī)與錄音捡硅,去河邊找鬼。 笑死辐棒,一個(gè)胖子當(dāng)著我的面吹牛病曾,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播漾根,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼泰涂,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了辐怕?” 一聲冷哼從身側(cè)響起逼蒙,我...
    開(kāi)封第一講書(shū)人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎寄疏,沒(méi)想到半個(gè)月后是牢,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡陕截,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年驳棱,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片农曲。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡社搅,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出乳规,到底是詐尸還是另有隱情形葬,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布暮的,位于F島的核電站笙以,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏冻辩。R本人自食惡果不足惜猖腕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一拆祈、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧谈息,春花似錦缘屹、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至逻炊,卻和暖如春互亮,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背余素。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工豹休, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人桨吊。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓威根,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親视乐。 傳聞我的和親對(duì)象是個(gè)殘疾皇子洛搀,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容