前天9月21日,手機(jī)更新到iOS 11, 看了一下早期上架 App Store 的應(yīng)用, 啥問(wèn)題都沒(méi)有, 心里正沾沾自喜也松了一口氣......
可昨夜更新到 Xcode9后編譯代碼,發(fā)現(xiàn)還有一些問(wèn)題的, 因?yàn)橥瑫r(shí)管理了好幾個(gè)應(yīng)用,其他應(yīng)用也是需要同步作 iOS 11適配, 所以好記不如賴筆頭, 省得適配其他應(yīng)用的時(shí)候忘記.....
問(wèn)題 1: UINavigationBar 內(nèi)UIBarButtonItem按鈕錯(cuò)位拉伸
問(wèn)題描述:
好在公司的幾個(gè)應(yīng)用的導(dǎo)航欄設(shè)計(jì)并不復(fù)雜, 不需要自定義 titleView,所以不涉及到自定義導(dǎo)航titleView的寬度適配問(wèn)題.
但是,自定義的 MANavigationController里所重寫的UIBarButtonItem返回按鈕 icon 被拉寬,并且各界面導(dǎo)航欄UIBarButtonItem按鈕, 也同樣擠壓和錯(cuò)位,設(shè)置的 title 也看不到了.
以下2張截圖就是Xcode9編譯代碼發(fā)現(xiàn)的iOS 11下UIBarButtonItem按鈕出現(xiàn)的問(wèn)題:
-
圖1: 主界面頂部左右3個(gè)按鈕被拉伸
[圖片加載中,請(qǐng)耐心等待....]
圖2: 頂部導(dǎo)航欄中間的 title 消失, 3個(gè)按鈕錯(cuò)位和被拉伸
[圖片加載中,請(qǐng)耐心等待....]
解決方案:
最簡(jiǎn)單的解決方案: 將 UIbutton 包裝到 UIview 內(nèi), 再通過(guò)initWithCustomView方法傳遞給UIBarButtonItem
//針對(duì) iOS11適配改寫 的關(guān)鍵性代碼, 就這么幾行,完全搞定了
UIView *containVew = [[UIView alloc] initWithFrame:btn.bounds];
[containVew addSubview:btn];
return [[UIBarButtonItem alloc]initWithCustomView:containVew];
以下代碼摘自 MISSAJJ 寫的MAButtonTool工具類,為了節(jié)約時(shí)間,提高創(chuàng)建按鈕控件的效率,特抽出一個(gè)創(chuàng)建各種按鈕的類方法
支持:
1,圖片按鈕 (默認(rèn)居中按鈕底挫,左返回按鈕,右分享按鈕)
2,自定義文字圖片靠左靠右按鈕
3,按項(xiàng)目需求扣癣,設(shè)定了按鈕樣式和位置樣式
4,只要修改一下分享和返回按鈕圖片就可以直接應(yīng)用到項(xiàng)目中了
5,由于美工給的圖片素材尺寸會(huì)不同,所以按鈕的frame和setImageEdgeInsets可根據(jù)項(xiàng)目素材情況在VC層創(chuàng)建后重寫調(diào)整
6,支持block調(diào)用按鈕事件
使用方法請(qǐng)看:https://github.com/MISSAJJ/MAButtonTool
^_^ 我只要在這個(gè)工具類里針對(duì) iOS 11增加幾行包裝代碼,
就解決了全部項(xiàng)目在 iOS 11下導(dǎo)航欄按鈕錯(cuò)位問(wèn)題,
這就是包裝工具類的好處......
#pragma mark ==[自定義 block 導(dǎo)航欄 按鈕]==
+(UIBarButtonItem *)createButtonWithImage:(NSString * __nullable)imageStr position:(MAButtonToolPostion)position type:(MAButtonToolType)type actionBlock:(ButtonItemBlock)block
{
UIButton* btn;
if (position == MAButtonToolPostionLeft) { //位置靠左
if (type ==MAButtonToolTypeBack) { //返回按鈕
btn = [self createLeftBackButton];
}else{
btn = [self createLeftButton:imageStr]; //默認(rèn)靠左按鈕
}
}else if (position == MAButtonToolPostionRight) { //位置靠右
if (type ==MAButtonToolTypeShare) { //分享按鈕
btn = [self createRightShareButton];
}else{
btn = [self createRightButton:imageStr];//默認(rèn)考右按鈕
}
}else { //位置中間
btn = [self createButton:imageStr];
}
[btn addTouchAction:^(UIButton *btn) {
if (block)
{
block(btn);
}
}];
//針對(duì) iOS11適配改寫
UIView *containVew = [[UIView alloc] initWithFrame:btn.bounds];
[containVew addSubview:btn];
return [[UIBarButtonItem alloc]initWithCustomView:containVew];
}
#pragma mark ==[左自定義圖片按鈕]==
+ (UIButton *)createLeftButton:(NSString *)imageStr
{
UIButton* btn= [self createButton:imageStr];
[btn setImageEdgeInsets:UIEdgeInsetsMake(0, -10, 0, 10)];
return btn;
}
#pragma mark ==[右自定義圖片按鈕]==
+ (UIButton*)createRightButton:(NSString*)imageStr
{
UIButton* btn=[self createButton:imageStr];
[btn setImageEdgeInsets:UIEdgeInsetsMake(0, 10, 0, -10)];
return btn;
}
#pragma mark ==[左返回按鈕]==
+ (UIButton*)createLeftBackButton
{
UIButton* btn= [self createButton:@"backarrow_white"];
btn.frame = CGRectMake(0, 0, 50, 50);
[btn setImageEdgeInsets:UIEdgeInsetsMake(0, -20, 0, 20)];
return btn;
}
#pragma mark ==[右分享按鈕]==
+ (UIButton*)createRightShareButton
{
UIButton* btn= [self createButton:@"share_white"];
btn.frame = CGRectMake(0, 0, 35, 35);
[btn setImageEdgeInsets:UIEdgeInsetsMake(0, 10, 0, -10)];
return btn;
}
解決問(wèn)題后的導(dǎo)航欄顯示截圖
-
圖1: 導(dǎo)航欄左右3個(gè)按鈕顯示正常, 中間的標(biāo)題也顯示正常了
[圖片加載中,請(qǐng)耐心等待....]
-
圖2: 主界面頂部左右3個(gè)按鈕顯示正常了
[圖片加載中,請(qǐng)耐心等待....]
問(wèn)題 2 : Xcode9下相冊(cè)等訪問(wèn)權(quán)限問(wèn)題
查了資料說(shuō)iOS11下,蘋果對(duì)相冊(cè)的權(quán)限key做了調(diào)整帮毁,原來(lái)的 NSPhotoLibraryUsageDescription 往声,在iOS11之后,改成了NSPhotoLibraryAddUsageDescription嗜湃。
針對(duì)于此測(cè)試了一下應(yīng)用,果然毫無(wú)懸念, 立即去 info.plist 把 key 改成NSPhotoLibraryAddUsageDescription, 很快解決問(wèn)題了.
圖3: info.plist內(nèi)設(shè)置NSPhotoLibraryAddUsageDescription權(quán)限
[圖片加載中,請(qǐng)耐心等待....]
問(wèn)題 3 : 等我好好睡個(gè)美容覺(jué)之后, 再繼續(xù)寫吧....... : )
昨夜熬到凌晨3點(diǎn),適配發(fā)布好了[AR 掃描器]APP應(yīng)用,已經(jīng)提交審核,
今夜適配另外一個(gè)[樂(lè)游博物館]APP 應(yīng)用, 不知不覺(jué)又已經(jīng)凌晨1:00了,
這兩個(gè)星期幾乎每天都只睡了幾個(gè)小時(shí),
好怕自己迅速變老,
好怕自己腎衰竭猝死,
好怕自己吃東西沒(méi)滋味,
好怕自己神經(jīng)衰落睡不著,
今天可是周末啊! ~周末啊! ~周末啊! ~
.........哎........
問(wèn)題 4 : MJRefresh下拉刷新適配 iOS 11和 iPhone X問(wèn)題
熬夜完成了公司的2個(gè)應(yīng)用的 iOS 11適配之后, 今晚開(kāi)始適配自己的一些項(xiàng)目,打開(kāi)其中一個(gè)項(xiàng)目在不同的模擬器下分別編譯看效果, 底部自定義 tabbar 顯示沒(méi)有問(wèn)題, 但頂部是隱藏了 NavigationBar并采用了MJRefresh下拉刷新,發(fā)現(xiàn)有錯(cuò)位..
圖4: iOS 11下拉刷新出現(xiàn)錯(cuò)位問(wèn)題
[圖片加載中,請(qǐng)耐心等待....]
圖4: iPhone X下拉刷新出現(xiàn)錯(cuò)位問(wèn)題
[圖片加載中,請(qǐng)耐心等待....]
我的解決方案: (灰常簡(jiǎn)單)
因?yàn)槲业牟季质?CollectionView, 所以只要設(shè)置 iOS 11的新特性方法contentInsetAdjustmentBehavior為UIScrollViewContentInsetAdjustmentNever就可以了
以此類推,如果是 UITableView 布局的,也是設(shè)置contentInsetAdjustmentBehavior
判定 iOS 11的方法, 官方建議的方法:
以下是官方的屏幕尺寸, 原本最初的想法就是根據(jù)屏幕的高度812pt來(lái)判定
官方建議的方法 :
if (@available(iOS 11.0, *)) {
}else{
}
我的適配代碼:
if (@available(iOS 11.0, *)) {
_collectionView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
} else {
// Fallback on earlier versions
}
判定iPhoneX的方法 :
#define isIPhoneX ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? [[UIScreen mainScreen] currentMode].size.height==2436 : NO)
其他的一些相關(guān)適配方法:(摘自 MJRefresh討論區(qū)的解決方案)
注:首先這個(gè)下拉刷新的偏移量并不是MJRefresh造成的,但是確實(shí)需要適配澜掩,比如通欄ViewController顯示的時(shí)候购披,劉海會(huì)遮住下拉刷新的組件,解決辦法是對(duì)下拉刷新控件自定義肩榕,調(diào)整內(nèi)部組件的布局刚陡,通欄的ViewController地方使用自定義的下拉控件。
對(duì)于iOS11下的iPhoneX適配下拉刷新有以下幾點(diǎn):
1株汉,首先請(qǐng)配置相應(yīng)的啟動(dòng)圖筐乳,尺寸是1125*2436;
2乔妈,對(duì)于通欄ViewController中的UIScrollView蝙云,系統(tǒng)會(huì)默認(rèn)根據(jù)contentInsetAdjustmentBehavior屬性改變其bounds的y值為-44,導(dǎo)致UIScrollView中的所有子控件下移路召,解決辦法是勃刨,對(duì)于通欄ViewController,請(qǐng)?jiān)O(shè)置其UIScrollView的contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever股淡。
其他適配點(diǎn):
1身隐,iOS11下的iPhoneX的導(dǎo)航欄為高度44,狀態(tài)欄高度也調(diào)整為44唯灵,所以整個(gè)頂部狀態(tài)欄的高度和導(dǎo)航欄的高度一起是88贾铝,自定義導(dǎo)航欄的同學(xué)需要根據(jù)系統(tǒng)機(jī)型控制導(dǎo)航欄高度;
2埠帕,iOS11下的iPhoneX的tabBar的高度調(diào)整為83垢揩,自定義tabBar的同學(xué)建議使用Frame布局;
3敛瓷,iOS11下的iPhoneX下水孩,屏幕底部默認(rèn)顯示了長(zhǎng)條狀的Home鍵指示器,可以通過(guò)UIViewController (UIHomeIndicatorAutoHidden)分類中的prefersHomeIndicatorAutoHidden來(lái)隱藏琐驴,但是官方并不建議這樣做。
適配 iOS 11和 iPhone X 之后的界面效果
我的建議:
在 iPhone X 下還是最好還是有導(dǎo)航欄的設(shè)計(jì)比較美觀, 因?yàn)殡[藏導(dǎo)航欄后, 劉海會(huì)把頂部控件切割掉, 畫面就比較尷尬了....哈哈~~
圖5: 適配后的截圖
[圖片加載中,請(qǐng)耐心等待....]
圖6: 適配后的下拉刷新,同時(shí)隱藏導(dǎo)航欄的截圖
圖7: 界面上滑顯示導(dǎo)航欄的效果
iPhone X 導(dǎo)航欄錯(cuò)位問(wèn)題
iOS11下的iPhoneX的導(dǎo)航欄為高度44秤标,狀態(tài)欄高度也調(diào)整為44绝淡,所以整個(gè)頂部狀態(tài)欄的高度和導(dǎo)航欄的高度一起是88,所以在自定義導(dǎo)航欄里針對(duì) iPhone X 修改的高度
我的解決方法:
我所有的項(xiàng)目都是使用了宏定義參數(shù)的方法來(lái)設(shè)置各種控件的, 所以只要改寫這些相關(guān)宏定義參數(shù), 整個(gè)項(xiàng)目都同步做好了適配, 所以平時(shí)的積累和歸納思維很重要,關(guān)鍵時(shí)刻可以減輕很多不必要的重復(fù)工作量.
/*****宏定義 *****/
//導(dǎo)航欄高度
#define MANavBarHeight isIPhoneX ? 88 : 64
//底部Tabbar 高度
#define MATabBarHeight isIPhoneX ? 83 : 49
//狀態(tài)欄高度
#define MAStatusBarHeight isIPhoneX ? 44 : 20
//一些相關(guān)同步對(duì)應(yīng)的代碼
// set navigationBar backgroundImage
- (void)MA_setBackgroundImage:(UIImage *)image
{
[self.backgroundView removeFromSuperview];
self.backgroundView = nil;
if (self.backgroundImageView == nil)
{
// add a image(nil color) to _UIBarBackground make it clear
[self setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
self.backgroundImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.bounds), MANavBarHeight)];
self.backgroundImageView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
// _UIBarBackground is first subView for navigationBar
[self.subviews.firstObject insertSubview:self.backgroundImageView atIndex:0];
}
self.backgroundImageView.image = image;
}
// set navigationBar barTintColor
- (void)MA_setBackgroundColor:(UIColor *)color
{
[self.backgroundImageView removeFromSuperview];
self.backgroundImageView = nil;
if (self.backgroundView == nil)
{
// add a image(nil color) to _UIBarBackground make it clear
[self setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
self.backgroundView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.bounds), MANavBarHeight)];
self.backgroundView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
// _UIBarBackground is first subView for navigationBar
[self.subviews.firstObject insertSubview:self.backgroundView atIndex:0];
}
self.backgroundView.backgroundColor = color;
}
其他方法:
網(wǎng)絡(luò)里也有相關(guān)這種重寫layoutSubviews的方法,我試過(guò)之后發(fā)現(xiàn)導(dǎo)航欄變透明,并且顏色怪怪的了, 所以最終還是用了上面的方法解決了問(wèn)題, 下面的這種方法大家也可是嘗試一下
自定義的navigationBar,在iOS11上運(yùn)行就可能出現(xiàn)布局錯(cuò)亂的bug苍姜,
解決辦法是重寫UINavigationBar的layoutSubviews方法調(diào)整布局:
- (void)layoutSubviews {
[super layoutSubviews];
//注意導(dǎo)航欄及狀態(tài)欄高度適配
self.frame = CGRectMake(0, 0, CGRectGetWidth(self.frame), MANavBarHeight);
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;
}
}
}
適配 iPhone X 之后的截圖
問(wèn)題 5 : XCode9打包上傳遇到的問(wèn)題和解決方式
問(wèn)題:上傳后返回警告,缺失1024px的圖標(biāo)
原因和解決: 升級(jí)Xcode9后Assets/AppIcon下多了一個(gè)1024pt的icon框,需要補(bǔ)上缺失的圖標(biāo)
問(wèn)題 6 : iPhone X下自定義鍵盤的高度如何增加34px 的高度
iPhone X 的默認(rèn)系統(tǒng)鍵盤 : 底部會(huì)自動(dòng)加上高度
問(wèn)題: 自定義的表情鍵盤的底部在 iPhone X 下沒(méi)有增加高度
將自定義表情emojiToolBarView設(shè)置為 UITextView輸入框的inputAccessoryView,emojiToolBarView會(huì)置頂于系統(tǒng)鍵盤,并且跟隨系統(tǒng)鍵盤向上向下移動(dòng)
self.customTextView.inputAccessoryView = self.emojiToolBarView;
//點(diǎn)擊自定義表情按鈕事件的邏輯
- (IBAction)emotionBtnClicked:(id)sender {
UIButton *button = sender;
if (!isEmotionShow) {
[button setImage:[UIImage imageNamed:@"board_system"] forState:UIControlStateNormal];
isEmotionShow = YES;
isKeyboard = NO;
// self.customEmojiBoardView為自定義表情鍵盤 View
self.customTextView.inputView = self.customEmojiBoardView;
[self.customTextView resignFirstResponder];
}else{
[button setImage:[UIImage imageNamed:@"board_emoji"] forState:UIControlStateNormal];
isEmotionShow = NO;
isKeyboard = YES;
self.customTextView.inputView = nil;
[self.customTextView resignFirstResponder];
}
}
解決辦法: 將你自定義的鍵盤的customEmojiBoardView 的高度加上34就可以了
//自定義表情鍵盤的寬高
CGFloat viewWidth = [UIScreen mainScreen].bounds.size.width - 16;
//原本自定義的高度是 216, 那就判定 iPhone X 下高度 再加上 34 為: 216+34 ;
CGFloat viewHeight = isPhoneX ? 250 : 216;
//自定義表情鍵盤customEmojiBoardView 的初始化
- (instancetype)init {
self = [super initWithFrame:CGRectMake(0, 0,viewWidth, viewHeight)];
if (self) {
以下代碼省略......
}
return self;
}
最后:
Contact 聯(lián)系方式:
希望能有更多的獅子一起共勉探討學(xué)習(xí)牢酵,愉快奔跑!
聯(lián)系方式: QQ 996174446 [驗(yàn)證:iOS 攻城獅]
MISSAJJ網(wǎng)站 : http://www.MISSAJJ.com
Github : https://github.com/MISSAJJ
GitBook : https://www.gitbook.com/@missajj
MISSAJJ琴瑟靜聽(tīng)( Swift 和 Objective-C )iOS 開(kāi)發(fā)項(xiàng)目電子書
https://github.com/MISSAJJ/MISSAJJ_IOS_DEVELOPMENT_BOOK