適配 iOS11

適配 iPhone X 的相關(guān)內(nèi)容詳見(jiàn)我的另一篇文章關(guān)于 SafeArea 和 適配 iPhoneX

前言

又是一波震撼人心的蘋(píng)果秋季新產(chǎn)品發(fā)布會(huì)瘟则,同時(shí)也放出了 OS 的 GM 版诫睬,相信很多果粉已經(jīng)按捺不住內(nèi)心已經(jīng)開(kāi)始了升級(jí)之旅唉堪。當(dāng)然,從 iOS 11 beta1 就已經(jīng)嘗鮮的朋友也不在少數(shù)晨雳。所以撒会,同時(shí)也意味著 iOS 開(kāi)發(fā)者的 iOS11 的適配工作已經(jīng)刻不容緩了。

1蔬啡、適配導(dǎo)航欄(UINavigationBar)

導(dǎo)航欄遇到問(wèn)題

別家 App 早就已經(jīng)適配了 iOS11诲侮,可是原諒我有其他的事情,而且大致在 iOS11 上運(yùn)行了一下 App箱蟆,沒(méi)有發(fā)現(xiàn)什么問(wèn)題沟绪,所以適配工作一直在耽擱,但是近些天更新了 Xcode9 在新的編譯器上編譯運(yùn)行了一下 App顽腾,WTF近零,一眼就看到了下面的丑爆的導(dǎo)航欄,什么鬼抄肖?然后在iOS11以下的設(shè)備上運(yùn)行久信,完全正常。
我們的 App 的導(dǎo)航欄不是用的UINavigationControllernavigationBar漓摩,而是每個(gè)VC都有一個(gè)自己的navigationBar裙士,這樣的話(huà),導(dǎo)航欄的自由度高管毙,而且個(gè)人感覺(jué)系統(tǒng)原生的導(dǎo)航欄的切換效果不好(當(dāng)然腿椎,iOS11 導(dǎo)航欄的大標(biāo)題切換特效還是蠻可以的桌硫,可以參考音樂(lè)、備忘錄等系統(tǒng)應(yīng)用查看效果啃炸,也可以自己添加設(shè)置UINavigationBar的屬性setPrefersLargeTitles來(lái)實(shí)現(xiàn)大標(biāo)題)铆隘。
iOS11 的導(dǎo)航欄:

iOS11_Nav_Bug.png

之前正常的導(dǎo)航欄見(jiàn)下面的 Nav_Normal 截圖

分析問(wèn)題

好的,那就讓我們一探究竟南用,到底是怎么回事膀钠。
經(jīng)過(guò) DebugView,在下圖看出了端倪裹虫。

DebugView_Bar.png

原來(lái) iOS11 的UINavigationBar有兩個(gè)子視圖肿嘲,分別是UIBarBackgroundUINavigationBarContentView,我們重點(diǎn)放在后者身上筑公,因?yàn)?code>BarButtonItem和TitleLabel都被添加到他上面雳窟,可以仔細(xì)看一下上面這張截圖,可以很清楚看出各自之間的關(guān)系匣屡。

知道了圖層之間的關(guān)系封救,那為什么我們的導(dǎo)航欄會(huì)在 iOS11 上產(chǎn)生出如上的元素錯(cuò)亂的問(wèn)題呢?仔細(xì)觀察會(huì)發(fā)現(xiàn)捣作,貌似是往上平移了將近 20 px兴泥,我們接著看一下布局,見(jiàn)下圖

UINavigationBarContent_Constraints_0.png

果然UINavigationBarContentView的midY坐標(biāo)是22虾宇,而這個(gè) contentView 的高度是 44px搓彻,所以到這里已經(jīng)找到了原因,原來(lái)是直接忽略狀態(tài)欄的 20px 直接貼在了屏幕頂部嘱朽,所以布局不錯(cuò)亂才怪旭贬。

解決方案

找到了原因,我們距離成功就不遠(yuǎn)了搪泳,創(chuàng)建一個(gè)UINavigationBar的子類(lèi)稀轨,重寫(xiě)layoutSubviews,重新布局導(dǎo)航欄的子視圖岸军,如下

- (void)layoutSubviews {
    [super layoutSubviews];
    
    self.frame = CGRectMake(0, 0, CGRectGetWidth(self.frame), 64);
    for (UIView *view in self.subviews) {
        if([NSStringFromClass([view class]) containsString:@"Background"]) {
            view.frame = self.bounds;
        }
        else if ([NSStringFromClass([view class]) containsString:@"ContentView"]) {
            CGRect frame = view.frame;
            frame.origin.y = 20;
            frame.size.height = self.bounds.size.height - frame.origin.y;
            view.frame = frame;
        }
    }
}

編譯運(yùn)行一下奋刽,完美解決。


iOS11_Nav_Normal.png

Debug一下艰赞,布局已經(jīng)正確了


UINavigationBarContent_Constraints_1.png
導(dǎo)航欄適配總結(jié)

也有一些童鞋也到了titleView布局錯(cuò)亂問(wèn)題佣谐,iOS10 及以下自定義titleView會(huì)添加在navigationBar上,而 iOS11 添加在UINavigationBarContentView上方妖,之前的UINavigationItemView在 iOS11 替換成了UINavigationBarContentView狭魂。使用上面的解決思路應(yīng)該很快就能解決。
為了實(shí)現(xiàn) iOS11 新系統(tǒng)的大標(biāo)題新UI效果,蘋(píng)果部分重構(gòu)了UINavigationBar的代碼及元素布局邏輯雌澄,從 iOS7 到 iOS10 階段內(nèi)導(dǎo)航欄都沒(méi)有大的變動(dòng)斋泄,而這個(gè)
iOS11 帶來(lái)的變動(dòng)或多或少會(huì)影響到我們的 App 導(dǎo)航欄的布局效果。而且在[Apple Developer Forums]也有相關(guān)的討論镐牺,像sizeThatFits not working炫掐,像There has a problem with UINavigationbar(maybe is bug),可能在這部分代碼蘋(píng)果還會(huì)相繼修改完善睬涧。但不管怎么說(shuō)卒废,現(xiàn)階段還是應(yīng)該找一套可行的適配方案來(lái)應(yīng)對(duì)導(dǎo)航欄變化帶來(lái)的影響。

2宙地、適配 UITableViewController(UIScrollView)

ScrollView 自動(dòng)適配 Insets 的方式變化automaticallyAdjustsScrollViewInsetscontentInsetAdjustmentBehavior
  • automaticallyAdjustsScrollViewInsets是控制器ViewController的屬性,默認(rèn)是true逆皮,一般來(lái)說(shuō)如果ScrollView直接添加在控制器視圖上時(shí)宅粥,會(huì)自動(dòng)設(shè)置ScrollViewInset屬性來(lái)空出status bar, search bar, navigation bar, toolbar, or tab bar的位置來(lái)。在日常開(kāi)發(fā)中為了程序的穩(wěn)定性與自由度一般我們是將這個(gè)屬性設(shè)置為false电谣。但是秽梅,這個(gè)屬性在iOS11失效了,所以導(dǎo)致了我們 App 的下面的問(wèn)題剿牺。
    iOS11_Insets_Bug.png

    問(wèn)題很好解決企垦,在文檔中標(biāo)注很明白
@property(nonatomic,assign) BOOL automaticallyAdjustsScrollViewInsets API_DEPRECATED_WITH_REPLACEMENT("Use UIScrollView's contentInsetAdjustmentBehavior instead", ios(7.0,11.0),tvos(7.0,11.0)); // Defaults to YES
  • contentInsetAdjustmentBehavior對(duì)于我們現(xiàn)在來(lái)說(shuō)是個(gè)陌生面孔。這是在 iOS11 為ScrollView新定義的一個(gè)枚舉屬性晒来。注意钞诡,上面談到的automaticallyAdjustsScrollViewInsets是控制器的屬性。
typedef NS_ENUM(NSInteger, UIScrollViewContentInsetAdjustmentBehavior) {
    UIScrollViewContentInsetAdjustmentAutomatic, // Similar to .scrollableAxes, but for backward compatibility will also adjust the top & bottom contentInset when the scroll view is owned by a view controller with automaticallyAdjustsScrollViewInsets = YES inside a navigation controller, regardless of whether the scroll view is scrollable
    UIScrollViewContentInsetAdjustmentScrollableAxes, // Edges for scrollable axes are adjusted (i.e., contentSize.width/height > frame.size.width/height or alwaysBounceHorizontal/Vertical = YES)
    UIScrollViewContentInsetAdjustmentNever, // contentInset is not adjusted
    UIScrollViewContentInsetAdjustmentAlways, // contentInset is always adjusted by the scroll view's safeAreaInsets
} API_AVAILABLE(ios(11.0),tvos(11.0));

所以我們將這個(gè)屬性設(shè)置為.AdjustmentNever即可解決Insets異常問(wèn)題湃崩。

if (@available(iOS 11.0, *)) {
        aboutMeTableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
    }

如下圖


iOS11_Insets_Normal.png
  • 每個(gè)需要修改的地方都寫(xiě)令人討厭的ifelse代碼有些不爽荧降,為了方面,我寫(xiě)了一個(gè)宏定義攒读,如下朵诫,設(shè)置起來(lái)就簡(jiǎn)單過(guò)了
    MCDisbaleAutoAdjustScrollViewInsets(_tableView, self)
/**
 取消自動(dòng)適配 ScrollView 的 Insets 行為
 @param scrollView 滑動(dòng)視圖
 @param vc 所在控制器
 */
#define MCDisbaleAutoAdjustScrollViewInsets(scrollView, vc)\
do { \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") \
if (@available(iOS 11.0,*))  {\
    scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;\
} else {\
    vc.automaticallyAdjustsScrollViewInsets = NO;\
}\
_Pragma("clang diagnostic pop")\
} while (0);
預(yù)估高度estimatedXXHeight

iOS11 中的estimatedXXHeight由默認(rèn)的 0 變成了現(xiàn)在的默認(rèn).AutomaticDimension,導(dǎo)致高度計(jì)算出錯(cuò)薄扁,最后導(dǎo)致的現(xiàn)象就是上拉加載更多的時(shí)候 UI 錯(cuò)亂剪返、TableView視圖的高度異常等一系列問(wèn)題。重新置 0 即可邓梅。

_tableView.estimatedRowHeight = 0;
_tableView.estimatedSectionFooterHeight = 0;
_tableView.estimatedSectionHeaderHeight = 0;

3脱盲、其他

  • info.plist新添Privacy - Photo Library Additions Usage Description鍵,跟Privacy - Photo Library Usage Description的不同之處在于日缨,前者允許你只寫(xiě)入圖庫(kù)宾毒,不需要讀取。這樣使得隱私權(quán)限更加細(xì)化。對(duì)這個(gè)鍵官方描述如下:

    Although this keys governs read and write access to the user’s photo library, it’s best to use NSPhotoLibraryAddUsageDescription if your app needs only to add assets to the library and does not need to read any assets.

在查閱資料的時(shí)候發(fā)現(xiàn)了一些好文章

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末诈铛,一起剝皮案震驚了整個(gè)濱河市乙各,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌幢竹,老刑警劉巖耳峦,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異焕毫,居然都是意外死亡蹲坷,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)邑飒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)循签,“玉大人,你說(shuō)我怎么就攤上這事疙咸∠亟常” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵撒轮,是天一觀的道長(zhǎng)乞旦。 經(jīng)常有香客問(wèn)我,道長(zhǎng)题山,這世上最難降的妖魔是什么兰粉? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮顶瞳,結(jié)果婚禮上玖姑,老公的妹妹穿的比我還像新娘。我一直安慰自己慨菱,他們只是感情好客峭,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著抡柿,像睡著了一般舔琅。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上洲劣,一...
    開(kāi)封第一講書(shū)人閱讀 48,970評(píng)論 1 284
  • 那天备蚓,我揣著相機(jī)與錄音,去河邊找鬼囱稽。 笑死郊尝,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的战惊。 我是一名探鬼主播流昏,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了况凉?” 一聲冷哼從身側(cè)響起谚鄙,我...
    開(kāi)封第一講書(shū)人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎刁绒,沒(méi)想到半個(gè)月后闷营,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡知市,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年傻盟,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嫂丙。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡娘赴,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出跟啤,到底是詐尸還是另有隱情诽表,我是刑警寧澤,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布腥光,位于F島的核電站,受9級(jí)特大地震影響糊秆,放射性物質(zhì)發(fā)生泄漏武福。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一痘番、第九天 我趴在偏房一處隱蔽的房頂上張望捉片。 院中可真熱鬧,春花似錦汞舱、人聲如沸伍纫。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)莹规。三九已至,卻和暖如春泌神,著一層夾襖步出監(jiān)牢的瞬間良漱,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來(lái)泰國(guó)打工欢际, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留母市,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓损趋,卻偏偏與公主長(zhǎng)得像患久,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

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

  • 本文為作者原創(chuàng)蒋失,未經(jīng)作者允許不得轉(zhuǎn)載返帕。該文同時(shí)發(fā)表在騰訊bugly公眾號(hào):https://mp.weixin.qq...
    sonialiu閱讀 101,590評(píng)論 74 283
  • 導(dǎo)航欄 導(dǎo)航欄高度的變化 iOS11之前導(dǎo)航欄默認(rèn)高度為64pt(這里高度指statusBar + Navigat...
    xukuangbo_閱讀 1,043評(píng)論 0 3
  • 導(dǎo)航欄 導(dǎo)航欄高度的變化 iOS11之前導(dǎo)航欄默認(rèn)高度為64pt(這里高度指statusBar + Navigat...
    西門(mén)淋雨閱讀 724評(píng)論 0 0
  • 1. 升級(jí)后,發(fā)現(xiàn)某個(gè)擁有tableView的界面錯(cuò)亂高镐,組間距和contentInset錯(cuò)亂溉旋,因?yàn)閕OS11中 U...
    SadMine閱讀 498評(píng)論 0 1
  • 濯顏看著手中明晃晃的銀刀,輕輕撥弄著面前朱紅幾案上的燭光嫉髓。那燭亮得奇特观腊,不像火焰,直灼眼睛算行,而是青暗暗的梧油,一副弱不...
    不如咸魚(yú)閱讀 276評(píng)論 0 0