適配 iOS11

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

前言

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

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

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

別家 App 早就已經(jīng)適配了 iOS11,可是原諒我有其他的事情,而且大致在 iOS11 上運行了一下 App,沒有發(fā)現(xiàn)什么問題,所以適配工作一直在耽擱,但是近些天更新了 Xcode9 在新的編譯器上編譯運行了一下 App,WTF,一眼就看到了下面的丑爆的導(dǎo)航欄,什么鬼?然后在iOS11以下的設(shè)備上運行,完全正常。
我們的 App 的導(dǎo)航欄不是用的UINavigationControllernavigationBar,而是每個VC都有一個自己的navigationBar,這樣的話,導(dǎo)航欄的自由度高,而且個人感覺系統(tǒng)原生的導(dǎo)航欄的切換效果不好(當然,iOS11 導(dǎo)航欄的大標題切換特效還是蠻可以的,可以參考音樂、備忘錄等系統(tǒng)應(yīng)用查看效果,也可以自己添加設(shè)置UINavigationBar的屬性setPrefersLargeTitles來實現(xiàn)大標題)。
iOS11 的導(dǎo)航欄:

iOS11_Nav_Bug.png

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

分析問題

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

DebugView_Bar.png

原來 iOS11 的UINavigationBar有兩個子視圖,分別是UIBarBackgroundUINavigationBarContentView,我們重點放在后者身上,因為BarButtonItemTitleLabel都被添加到他上面,可以仔細看一下上面這張截圖,可以很清楚看出各自之間的關(guān)系。

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

UINavigationBarContent_Constraints_0.png

果然UINavigationBarContentView的midY坐標是22,而這個 contentView 的高度是 44px,所以到這里已經(jīng)找到了原因,原來是直接忽略狀態(tài)欄的 20px 直接貼在了屏幕頂部,所以布局不錯亂才怪。

解決方案

找到了原因,我們距離成功就不遠了,創(chuàng)建一個UINavigationBar的子類,重寫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;
        }
    }
}

編譯運行一下,完美解決。


iOS11_Nav_Normal.png

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


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

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

2、適配 UITableViewController(UIScrollView)

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

    問題很好解決,在文檔中標注很明白
@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對于我們現(xiàn)在來說是個陌生面孔。這是在 iOS11 為ScrollView新定義的一個枚舉屬性。注意,上面談到的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));

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

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

如下圖


iOS11_Insets_Normal.png
  • 每個需要修改的地方都寫令人討厭的ifelse代碼有些不爽,為了方面,我寫了一個宏定義,如下,設(shè)置起來就簡單過了
    MCDisbaleAutoAdjustScrollViewInsets(_tableView, self)
/**
 取消自動適配 ScrollView 的 Insets 行為
 @param scrollView 滑動視圖
 @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由默認的 0 變成了現(xiàn)在的默認.AutomaticDimension,導(dǎo)致高度計算出錯,最后導(dǎo)致的現(xiàn)象就是上拉加載更多的時候 UI 錯亂、TableView視圖的高度異常等一系列問題。重新置 0 即可。

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

3、其他

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

    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.

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 本文為作者原創(chuàng),未經(jīng)作者允許不得轉(zhuǎn)載。該文同時發(fā)表在騰訊bugly公眾號:https://mp.weixin.qq...
    sonialiu閱讀 101,881評論 74 283
  • 導(dǎo)航欄 導(dǎo)航欄高度的變化 iOS11之前導(dǎo)航欄默認高度為64pt(這里高度指statusBar + Navigat...
    xukuangbo_閱讀 1,140評論 0 3
  • 導(dǎo)航欄 導(dǎo)航欄高度的變化 iOS11之前導(dǎo)航欄默認高度為64pt(這里高度指statusBar + Navigat...
    西門淋雨閱讀 844評論 0 0
  • 1. 升級后,發(fā)現(xiàn)某個擁有tableView的界面錯亂,組間距和contentInset錯亂,因為iOS11中 U...
    SadMine閱讀 533評論 0 1
  • 濯顏看著手中明晃晃的銀刀,輕輕撥弄著面前朱紅幾案上的燭光。那燭亮得奇特,不像火焰,直灼眼睛,而是青暗暗的,一副弱不...
    不如咸魚閱讀 342評論 0 0

友情鏈接更多精彩內(nèi)容