前陣子項目開發忙成狗,就一直沒作iOS11的適配,直到XcodeGM版發佈後,我成竹在胸的在iPhoneX上跑起項目,整我的都涼透了...下面總結一下我遇到的坑,不是很全面,往後補充。安全
導航欄佈局
導航欄高度的變化3d
iOS11以前導航欄默認高度爲64pt(這裏高度指statusBar + NavigationBar),iOS11以後若是設置了prefersLargeTitles = YES則爲96pt,默認狀況下仍是64pt,但在iPhoneX上因爲劉海的出現statusBar由之前的20pt變成了44pt,因此iPhoneX上高度變爲88pt,若是項目裏隱藏了導航欄加了自定義按鈕之類的,這裏須要注意適配一下。code
導航欄圖層及對titleView佈局的影響orm
iOS11以前導航欄的title是添加在UINavigationItemView上面,而navigationBarButton則直接添加在UINavigationBar上面,若是設置了titleView,則titleView也是直接添加在UINavigationBar上面。iOS11以後,大概由於largeTitle的緣由,視圖層級發生了變化,若是沒有給titleView賦值,則titleView會直接添加在_UINavigationBarContentView上面,若是賦值了titleView,則會把titleView添加在_UITAMICAdaptorView上,而navigationBarButton被加在了_UIButtonBarStackView上,而後他們都被加在了_UINavigationBarContentView上,如圖:blog
因此若是你的項目是自定義的navigationBar,那麼在iOS11上運行就可能出現佈局錯亂的bug,解決辦法是重寫UINavigationBar的layoutSubviews方法,調整佈局,上代碼:開發
- (void)layoutSubviews { [super layoutSubviews]; //注意導航欄及狀態欄高度適配 self.frame = CGRectMake(0, 0, CGRectGetWidth(self.frame), naviBarHeight); 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 = statusBarHeight; frame.size.height = self.bounds.size.height - frame.origin.y; view.frame = frame; } } }
再補充一點,看了簡書App適配iOS11發現titleView支持autolayout,這要求titleView必須是可以自撐開的或實現了- intrinsicContentSize方法get
- (CGSize)intrinsicContentSize { return UILayoutFittingExpandedSize; }
UIScrollView、UITableView、UICollectionViewit
你們在iOS11設備上運行出現最多問題應該就是tableview莫名奇妙的偏移20pt或者64pt了。。緣由是iOS11棄用了automaticallyAdjustsScrollViewInsets屬性,取而代之的是UIScrollView新增了contentInsetAdjustmentBehavior屬性,這一切的罪魁禍首都是新引入的safeArea,關於safeArea適配這篇文章iOS 11 安全區域適配總結講的很詳細,感興趣的能夠看下,我直接貼適配代碼,由於低版本直接用contentInsetAdjustmentBehavior會報警告,全部定義了以下的宏(感謝@炒雞範的指正,以前的宏犯了個低級錯誤...現改成)io
#define adjustsScrollViewInsets(scrollView)\ do {\ _Pragma("clang diagnostic push")\ _Pragma("clang diagnostic ignored \"-Warc-performSelector-leaks\"")\ if ([scrollView respondsToSelector:NSSelectorFromString(@"setContentInsetAdjustmentBehavior:")]) {\ NSMethodSignature *signature = [UIScrollView instanceMethodSignatureForSelector:@selector(setContentInsetAdjustmentBehavior:)];\ NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];\ NSInteger argument = 2;\ invocation.target = scrollView;\ invocation.selector = @selector(setContentInsetAdjustmentBehavior:);\ [invocation setArgument:&argument atIndex:2];\ [invocation retainArguments];\ [invocation invoke];\ }\ _Pragma("clang diagnostic pop")\ } while (0)
還有的發現某些界面tableView的sectionHeader、sectionFooter高度與設置不符的問題,在iOS11中若是不實現 -tableView: viewForHeaderInSection:和-tableView: viewForFooterInSection: ,則-tableView: heightForHeaderInSection:和- tableView: heightForFooterInSection:不會被調用,致使它們都變成了默認高度,這是由於tableView在iOS11默認使用Self-Sizing,tableView的estimatedRowHeight、estimatedSectionHeaderHeight、 estimatedSectionFooterHeight三個高度估算屬性由默認的0變成了UITableViewAutomaticDimension,解決辦法簡單粗暴,就是實現對應方法或把這三個屬性設爲0。
若是你使用了Masonry,那麼你須要適配safeArea
if (@available(iOS 11.0, *)) { make.edges.equalTo()(self.view.safeAreaInsets) } else { make.edges.equalTo()(self.view) }
iPhoneX
LaunchImage
關於iPhoneX(我就不吐槽劉海了...),若是你的APP在iPhoneX上運行發現沒有充滿屏幕,上下有黑色區域,那麼你應該也像我同樣LaunchImage沒有用storyboard而是用的Assets,解決辦法如圖,啓動圖的尺寸爲1125x2436,or you can iOS開發時如何使用 Launch Screen Storyboard。
TabBarController
由於咱們的項目用了第三方的TabBarController,在iPhoneX運行,tabBar看起來怪怪的...估計做者要等到猴年馬月才適配iPhoneX,項目又着急上線,就本身修改了第三方,主要是tabBar高度及tabBarItem偏移適配,iPhoneX因爲底部安全區的緣由UITabBar高度由49pt變成了83pt,能夠經過判斷機型來修改相關界面代碼
#define kDevice_Is_iPhoneX ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1125, 2436), [[UIScreen mainScreen] currentMode].size) : NO)
目前遇到的就這些坑,歡迎你們指正補充~
做爲一名iOS開發人員,想到當年嘲笑Android開發蛋疼的適配各類機型心情如圖...