這篇文章主要為大家展示了“IOS11新特性與兼容適配的示例分析”,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“IOS11新特性與兼容適配的示例分析”這篇文章吧。
為平谷等地區(qū)用戶提供了全套網(wǎng)頁設(shè)計(jì)制作服務(wù),及平谷網(wǎng)站建設(shè)行業(yè)解決方案。主營業(yè)務(wù)為成都網(wǎng)站建設(shè)、網(wǎng)站建設(shè)、平谷網(wǎng)站設(shè)計(jì),以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠的服務(wù)。我們深信只要達(dá)到每一位用戶的要求,就會(huì)得到認(rèn)可,從而選擇與我們長期合作。這樣,我們也可以走得更遠(yuǎn)!1. UIView變化
1.1. 更加方便的RTL邊距設(shè)置
在之前的系統(tǒng)中我們會(huì)使用layoutMargins來獲取和設(shè)置控件顯示內(nèi)容部分的邊緣與控件邊緣的距離。在iOS 11中,新增directionalLayoutMargins屬性來指定邊距。這兩個(gè)屬性的結(jié)構(gòu)定義如下:
typedef struct UIEdgeInsets { CGFloat top, left, bottom, right; } UIEdgeInsets; //// typedef struct NSDirectionalEdgeInsets { CGFloat top, leading, bottom, trailing; } NSDirectionalEdgeInsets
從結(jié)構(gòu)上看主要是將UIEdgeInsets結(jié)構(gòu)的left和right調(diào)整為NSDirectionalEdgeInsets結(jié)構(gòu)的leading和trailing。這一調(diào)整主要是為了Right To Left(RTL)語言下可以進(jìn)行自動(dòng)適配,例如:要實(shí)現(xiàn)文本每行尾部邊距設(shè)置為30px,在以前做法則需要判斷語言來區(qū)分哪些是RTL語言,然后再做設(shè)置,如:
if ([UIView userInterfaceLayoutDirectionForSemanticContentAttribute:self.view.semanticContentAttribute] == UIUserInterfaceLayoutDirectionRightToLeft) { // Right to left 語言下每行尾部在左邊 self.view.layoutMargins.left = 30; } else { self.view.layoutMargins.right = 30; }
iOS 11 后則可以一步到位,如:
self.view.directionalLayoutMargins = NSDirectionalEdgeInsetsMake(0, 0, 0, 30);
注:測試時(shí)需要添加RTL本地化語言才能看到效果
1.2. 安全區(qū)域
在iOS 11中新增了安全區(qū)域的概念,目的是告訴開發(fā)者在這個(gè)區(qū)域下繪制的內(nèi)容的顯示才是有效的,否則會(huì)存在被遮擋的情況(特別是iPhoneX那帥氣的劉海)。在UIView中新增safeAreaLayoutGuide和safeAreaInsets來獲取屏幕的安全區(qū)域(對于frame布局時(shí)是很有用的)。如圖所示:
SafeArea示意圖
舉個(gè)例子,在一個(gè)空白的UIViewController中,分別在viewDidLoad和viewDidAppear方法中輸出view.safeAreaInsets觀察邊距情況,代碼如下:
- (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); }
可以看到其輸出為:
2017-09-19 14:45:50.246095+0800 Sample[5608:1365070] viewDidLoad safeAreaInsets = {0, 0, 0, 0}, layoutFrame = {{0, 0}, {375, 667}} 2017-09-19 14:45:50.257807+0800 Sample[5608:1365070] viewDidAppear safeAreaInsets = {20, 0, 0, 0}, layoutFrame = {{0, 20}, {375, 603}}
可見,在視圖顯示完成的時(shí)候View的頂部邊距變?yōu)榱?0px,而這20px正是狀態(tài)欄的高度。同樣原理,如果你的是一個(gè)
UINavigationController那在顯示的時(shí)候view.safeAreaInsets就會(huì)變成{64, 0, 0, 0}。注意:在該VC下所有的UIView及其子類獲取到safeAreaInsets的值是相同的。
如果你想準(zhǔn)確地知道安全區(qū)域是什么時(shí)候被改變的,可以重寫UIView的safeAreaInsetsDidChange方法,在這個(gè)方法里面可以監(jiān)聽安全區(qū)域的邊距調(diào)整的事件(如果使用的是UIViewController,其也提供相應(yīng)方法來實(shí)現(xiàn)監(jiān)聽,下一章節(jié)會(huì)講述該部分內(nèi)容),代碼如下:
- (void)safeAreaInsetsDidChange { //寫入變更安全區(qū)域后的代碼... }
如果你不想讓safeAreaInsets影響你的視圖布局,則可以將insetsLayoutMarginsFromSafeArea設(shè)置為NO,所有的視圖布局將會(huì)忽略safeAreaInsets這個(gè)屬性了。要注意的是,insetsLayoutMarginsFromSafeArea僅用于AutoLayout,即使該屬性為NO,視圖的safeAreaInsets還是一樣有值,而且安全區(qū)域變更方法safeAreaInsetsDidChange一樣被調(diào)用。
2. UIViewController變化
2.1. 廢除API
2.1.1. automaticallyAdjustsScrollViewInsets方法
iOS 7中使用該方法來自動(dòng)調(diào)整UIScrollView的contentInset。在iOS 11之后將會(huì)使用UIScrollView的
contentInsetAdjustmentBehavior屬性來代替該方法。
2.1.2. topLayoutGuide和bottomLayoutGuide屬性
iOS 7中使用這兩個(gè)屬性來指導(dǎo)帶有導(dǎo)航欄(NaviagtionBar)和頁簽欄(TabBar)的視圖排版。其作用如下圖所示
topLayoutGuide & bottomLayoutGuide
在iOS 11之后將使用安全區(qū)域(Safe Area)來代替該部分功能的實(shí)現(xiàn)。
2.2. 排版
2.2.1. additionalSafeAreaInsets屬性
iOS 11加入安全區(qū)域后,對于VC則可以通過該屬性來對該區(qū)域附加一個(gè)邊距信息。如:
self.additionalSafeAreaInsets = UIEdgeInsetsMake(30, 0, 0, 30);
注意:這里是附加邊距,意思就是在原有的safeAreaInsets值中增加對應(yīng)的邊距值。如果原來的是{10, 0, 0, 10}, 則最后得出的邊距是{40, 0, 0, 40}。
2.2.2. systemMinimumLayoutMargins和viewRespectsSystemMinimumLayoutMargins屬性
該屬性表示了一個(gè)系統(tǒng)最小的邊距信息,所有的視圖排版都應(yīng)該遵循這個(gè)邊距信息的。除非將viewRespectsSystemMinimumLayoutMargins設(shè)置為NO。
2.2.3. viewLayoutMarginsDidChange方法
根視圖的邊距變更時(shí)會(huì)觸發(fā)該方法的回調(diào)??梢酝ㄟ^該方法來處理當(dāng)邊距改變時(shí)子視圖的布局。
2.2.4. viewSafeAreaInsetsDidChange方法
當(dāng)視圖的安全區(qū)域發(fā)生變更時(shí)會(huì)觸發(fā)該方法的回調(diào)??梢酝ㄟ^該方法來處理安全區(qū)域變更時(shí)的子視圖布局。
3. UINavigationBar變化
iOS 11中加入了大標(biāo)題模式,其顯示效果如下所示:
大標(biāo)題效果圖
實(shí)現(xiàn)該效果需要將導(dǎo)航欄的prefersLargeTitles設(shè)置為YES,如:
self.navigationController.navigationBar.prefersLargeTitles = YES;
4. UINavigationItem變化
4.1 控制大標(biāo)題的顯示
如果你想控制每個(gè)視圖的大標(biāo)題是否顯示,這需要使用UINavigationItem的largeTitleDisplayMode屬性來控制大標(biāo)題的顯示。該屬性為枚舉類型,定義如下:
typedef NS_ENUM(NSInteger, UINavigationItemLargeTitleDisplayMode) { /// 自動(dòng)模式,會(huì)繼承前一個(gè)NavigationItem所設(shè)置的模式 UINavigationItemLargeTitleDisplayModeAutomatic, /// 當(dāng)前 Navigationitem 總是啟用大標(biāo)題模式 UINavigationItemLargeTitleDisplayModeAlways, /// 當(dāng)前 Navigationitem 總是禁用大標(biāo)題模式 UINavigationItemLargeTitleDisplayModeNever, }
根據(jù)上面的描述,可以在VC初始化init或者awakeFromNib方法中設(shè)置顯示圖標(biāo)模式:
self.navigationItem.largeTitleDisplayMode = UINavigationItemLargeTitleDisplayModeAlways;
4.2 控制搜索控制器
iOS 11 中新增了兩個(gè)屬性searchController和hidesSearchBarWhenScrolling。這兩個(gè)屬性主要用于簡化VC對UISearchController的集成以及視覺優(yōu)化。其中searchController屬性用于指定當(dāng)前VC的一個(gè)搜索控制器。而hidesSearchBarWhenScrolling屬性則用于控制當(dāng)視圖滾動(dòng)時(shí)是否隱藏搜索欄的UI,當(dāng)該值為YES時(shí),搜索欄只有在內(nèi)容視圖(UIScrollView及其子類)頂部是才會(huì)顯示,在滾動(dòng)過程中會(huì)隱藏起來;當(dāng)該值為NO時(shí),則不受滾動(dòng)影響一直顯示在導(dǎo)航欄中。具體的代碼實(shí)現(xiàn)如下:
- (void)awakeFromNib { [super awakeFromNib]; //設(shè)置SearchController到navigationItem self.searchController = [[UISearchController alloc] initWithSearchResultsController:self]; self.navigationItem.searchController = self.searchController; self.navigationItem.hidesSearchBarWhenScrolling = YES; }
搜索欄隱藏后效果
5. UIScrollView變化
之前的系統(tǒng)中,如果你的滾動(dòng)視圖包含在一個(gè)導(dǎo)航控制器下,系統(tǒng)會(huì)自動(dòng)地調(diào)整你的滾動(dòng)視圖的contentInset。而iOS 11新增adjustedContentInset屬性取替之前contentInset的處理方式。這兩者之間的關(guān)系如下圖所示:
adjustedContentInset & contentInset
通過一個(gè)例子來驗(yàn)證這說法,代碼如下:
- (void)viewDidLoad { [super viewDidLoad]; NSLog(@"viewDidLoad"); NSLog(@"self.tableView.contentInset = %@", NSStringFromUIEdgeInsets(self.tableView.contentInset)); NSLog(@"self.tableView.adjustedContentInset = %@", NSStringFromUIEdgeInsets(self.tableView.adjustedContentInset)); } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; NSLog(@"viewDidAppear"); NSLog(@"self.tableView.contentInset = %@", NSStringFromUIEdgeInsets(self.tableView.contentInset)); NSLog(@"self.tableView.adjustedContentInset = %@", NSStringFromUIEdgeInsets(self.tableView.adjustedContentInset)); }
執(zhí)行后輸出下面信息:
2017-09-20 11:54:09.361348+0800 Sample[1276:375286] viewDidLoad 2017-09-20 11:54:09.361432+0800 Sample[1276:375286] self.tableView.contentInset = {0, 0, 0, 0} 2017-09-20 11:54:09.361462+0800 Sample[1276:375286] self.tableView.adjustedContentInset = {0, 0, 0, 0} 2017-09-20 11:54:09.420000+0800 Sample[1276:375286] viewDidAppear 2017-09-20 11:54:09.420378+0800 Sample[1276:375286] self.tableView.contentInset = {0, 0, 0, 0} 2017-09-20 11:54:09.420554+0800 Sample[1276:375286] self.tableView.adjustedContentInset = {20, 0, 0, 0}
可見,tableView的adjustedContentInset自動(dòng)改變了,但是contentInset的值是保持不變的。注:一定要是VC的根視圖為UIScrollView或者其子類才能夠得到adjustedContentInset的值,否則獲取到的是空值。而且非根視圖的滾動(dòng)視圖就會(huì)被安全區(qū)域所裁剪,看到的樣式如下圖所示:
樣式效果對比
通過使用contentInsetAdjustmentBehavior屬性可以控制 adjustedContentInset的變化。該屬性為枚舉類型,其定義如下:
typedef NS_ENUM(NSInteger, UIScrollViewContentInsetAdjustmentBehavior) { UIScrollViewContentInsetAdjustmentAutomatic, UIScrollViewContentInsetAdjustmentScrollableAxes, UIScrollViewContentInsetAdjustmentNever, UIScrollViewContentInsetAdjustmentAlways, }
其中UIScrollViewContentInsetAdjustmentAutomatic與UIScrollViewContentInsetAdjustmentScrollableAxes一樣,ScrollView會(huì)自動(dòng)計(jì)算和適應(yīng)頂部和底部的內(nèi)邊距并且在scrollView 不可滾動(dòng)時(shí),也會(huì)設(shè)置內(nèi)邊距;
UIScrollViewContentInsetAdjustmentNever表示不計(jì)算內(nèi)邊距;UIScrollViewContentInsetAdjustmentAlways則根據(jù)視圖的安全區(qū)域來計(jì)算內(nèi)邊距。
如果需要感知adjustedContentInset的變化,然后根據(jù)變化進(jìn)行不同操作則可以通過重寫新增的adjustedContentInsetDidChange方法或者實(shí)現(xiàn)UIScrollViewDelegate中的scrollViewDidChangeAdjustedContentInset方法來實(shí)現(xiàn)。如:
//重寫方法 - (void)adjustedContentInsetDidChange { [super adjustedContentInsetDidChange]; //執(zhí)行操作... } //實(shí)現(xiàn)委托 - (void)scrollViewDidChangeAdjustedContentInset:(UIScrollView *)scrollView { //執(zhí)行操作... }
除了新增上述所說的邊距相關(guān)屬性外,還新增了contentLayoutGuide和frameLayoutGuide屬性,用于描述內(nèi)容布局和整體布局信息。
6. UI主線程操作日志提醒
之前的系統(tǒng)中如果你不小心將UI放入非主線程操作時(shí),Debug日志是沒有任何信息反饋的,導(dǎo)致有時(shí)候在排錯(cuò)時(shí)非常困難。在新的Xcode 9中,如果你處于調(diào)試狀態(tài),將UI放入非主線程操作,如:
dispatch_async(dispatch_get_global_queue(0, 0), ^{ self.tv = [[UITableView alloc] initWithFrame:self.view.bounds]; [self.view addSubview:self.tv]; NSLog(@"self.tv.adjustedContentInset = %@", NSStringFromUIEdgeInsets(self.tv.adjustedContentInset)); });
Log中會(huì)出現(xiàn)下面提示:
================================================================= Main Thread Checker: UI API called on a background thread: -[UIView bounds] PID: 16919, TID: 2972321, Thread name: (none), Queue name: com.apple.root.default-qos, QoS: 21 Backtrace: 4 Sample 0x00000001004885dc __29-[ViewController viewDidLoad]_block_invoke + 112 5 libdispatch.dylib 0x000000010077149c _dispatch_call_block_and_release + 24 6 libdispatch.dylib 0x000000010077145c _dispatch_client_callout + 16 7 libdispatch.dylib 0x000000010077d56c _dispatch_queue_override_invoke + 980 8 libdispatch.dylib 0x0000000100782b54 _dispatch_root_queue_drain + 616 9 libdispatch.dylib 0x0000000100782880 _dispatch_worker_thread3 + 136 10 libsystem_pthread.dylib 0x000000018300b130 _pthread_wqthread + 1268 11 libsystem_pthread.dylib 0x000000018300ac30 start_wqthread + 4
從日志中了解到一個(gè)Main Thread Checker的東西,根據(jù)蘋果官方文檔來看他是作用在AppKit(OSX中)、UIKit還有一些相關(guān)API上的后臺(tái)線程,主要是用來監(jiān)控這些框架中的接口是否在主線程中進(jìn)行調(diào)用,如果沒有則發(fā)出警告日志。因此,利用這個(gè)功能可以讓我們快速地定位那些地方存在問題。
以上是“IOS11新特性與兼容適配的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注創(chuàng)新互聯(lián)網(wǎng)站建設(shè)公司行業(yè)資訊頻道!
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)建站www.cdcxhl.com,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。