iOS開發(fā)——ios11匾竿、iphoneX適配實記

編譯器升級xcode9赖草,準(zhǔn)備適配一下iphoneX的布局漏隐,調(diào)試時發(fā)現(xiàn)由于一些ios11新特性或者底層變化的原因,xcode9運(yùn)行出來的項目界面有bug食店,下面做一下新特性適配和iphoneX布局適配的記錄。

ios11新特性

UIScrollView新特性
UITbaleView自動增加了內(nèi)邊距.jpeg
  • 現(xiàn)象:如上圖所示岖瑰,圖中中間部分是一個表格叛买,在ios11手機(jī)上,表格的頭部多出了一部分空隙蹋订。
  • 原因:ios11后率挣,UIScrollView增加了新特性,多了一個屬性:contentInsetAdjustmentBehavior露戒,理解為“調(diào)整內(nèi)邊距的行為”椒功,可選四個參數(shù):
    -- UIScrollViewContentInsetAdjustmentAutomatic : 自動調(diào)整;
    -- UIScrollViewContentInsetAdjustmentScrollableAxes : 在滾動方向上調(diào)整智什;
    -- UIScrollViewContentInsetAdjustmentNever : 從不調(diào)整动漾;
    -- UIScrollViewContentInsetAdjustmentAlways : 總是調(diào)整。
    默認(rèn)是UIScrollViewContentInsetAdjustmentAutomatic荠锭,所以它自動增加了一部分空隙去避免遮擋(自動調(diào)整的判斷旱眯,包括:是否在導(dǎo)航控制器中、是否在tabbarViewController中等等)。
  • 解決方法:
if (@available(iOS 11.0, *))//表示只在ios11以上的版本執(zhí)行
{
    _brandTableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}
正常時效果.png
UISearchBar新特性
UISearchBar的bug.jpeg
  • 現(xiàn)象:如圖所示删豺,ios11這個searchBar莫名肥了一圈共虑,我代碼沒變過,同樣設(shè)的是高度44呀页,在ios10上是下面這個樣子


    正常狀態(tài)的searchBar.jpeg
  • 原因:UISearchBar的底層結(jié)構(gòu)變了妈拌,簡單來看,以前的UISearchBar是下面這個樣子
    searchBar結(jié)構(gòu)示意.png

    簡單來看蓬蝶,它由一個大的紅色view+內(nèi)部輸入框(白色部分)構(gòu)成尘分,在ios11以前,高度設(shè)置控制的是大的紅色view的高度丸氛,內(nèi)部輸入框(白色部分)的高度永遠(yuǎn)固定是28培愁。
    而ios11后,它沒了大的紅色view雪位,只有內(nèi)部輸入框(白色部分)竭钝,給高度的時候,自然就控制的是內(nèi)部輸入框(白色部分)的高度雹洗。
    所以同樣都是44的高香罐,ios11上的UISearchBar會肥一圈。
  • 解決方法:
    如果需要跟以前保持同樣的效果时肿,那么在ios11上把UISearchBar的高度設(shè)為28并重新布局
UITableView使用MJRefreshAutoNormalFooter上拉刷新時頁面會跳動
  • 現(xiàn)象:正常情況:應(yīng)該是觸發(fā)了上拉刷新庇茫,加載數(shù)據(jù),加載完后增加若干cell螃成,但頁面仍保持在原位置旦签。而軟件在xcode9編譯環(huán)境下的ios11手機(jī)上,加載完后頁面會向上跳一截寸宏,尤其在cell的高度是由model的實際數(shù)據(jù)決定宁炫,尤其在cell高度較大的時候,很明顯氮凝。MJRefresh做了更新羔巢,但實測,還是有問題罩阵。
  • 原因:UITableView這兩個代理方法調(diào)用順序變了:cellForRowAtIndexPath和heightForRowAtIndexPath竿秆,直接導(dǎo)致了獲取高度算tableview偏移有問題。
  • 解決辦法:
    實現(xiàn)以下方法:
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return 200;
}

盡量給出較接近實際cell高度的數(shù)值稿壁,跳動問題會消失幽钢。

  • 2018.02.01更新,不需要實現(xiàn)estimatedHeightForRowAtIndexPath這個代理傅是,設(shè)置下面三個參數(shù)即可
    if (@available(iOS 11.0, *))//表示只在ios11以上的版本執(zhí)行
    {
        tableview.estimatedRowHeight = 0;
        tableview.estimatedSectionHeaderHeight = 0;
        tableview.estimatedSectionFooterHeight = 0;
    }
導(dǎo)航欄返回按鈕偏移匪燕、自定義按鈕難以點中
返回按鈕偏移bug.jpeg
  • 現(xiàn)象:UINavigationController的navBar的返回按鈕蕾羊,我隱藏了它的文字,結(jié)果它比在ios10上谎懦,明顯向右向下偏移了一截(不隱藏文字時不會有這種問題)肚豺。我自定義了一個左邊按鈕作為返回按鈕,發(fā)現(xiàn)非常難點中界拦。
  • 原因:底層實現(xiàn)機(jī)制改變。
  • 解決辦法:
    自定義左邊按鈕作為返回按鈕
    那么如何解決自定義按鈕難以點中的問題呢梗劫?
    給navBar添加一個單擊手勢享甸,判斷手勢位置,如果在左邊某個范圍梳侨,就調(diào)用按鈕的點擊事件蛉威。
    我是給UIViewController寫了一個分類UIViewController+YYBackBarButton,這樣需要用的頁面里走哺,只需要在viewDidLoad中加下面一句話就行了
[self addCustomBackButtonWithBackButtonColor:UIColorFromRGB(0x979797)];

分類.m文件代碼如下:

#import "UIViewController+YYBackBarButton.h"
#import "UIImage+extend.h"

@implementation UIViewController (YYBackBarButton)

- (void)addCustomBackButtonWithBackButtonColor:(UIColor *)backButtonColor
{
    self.navigationController.navigationBar.tintColor = [UIColor clearColor];//返回按鈕顏色
    self.navigationController.navigationBar.backItem.hidesBackButton = YES;//隱藏返回按鈕
    self.navigationController.interactivePopGestureRecognizer.delegate = (id)self;//開啟手勢右滑返回
    
    //創(chuàng)建返回按鈕
    UIButton *backButton = [[UIButton alloc] init];
    backButton.frame = CGRectMake(0, 0, 13, 22);
    [backButton setImage:[[UIImage imageNamed:@"backButton.png"] imageWithColor:backButtonColor] forState:UIControlStateNormal];//imageWithColor這個方法是UIImage+extend分類里的方法蚯嫌,作用是對圖片的顏色進(jìn)行自定義渲染(說白了就是改圖片顏色)
    backButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
    //返回按鈕偏移值,根據(jù)自己的需要設(shè)置偏移丙躏,已達(dá)到想要的UI效果
    CGFloat insetNumber = 0;
    if (@available(iOS 11.0, *))
    {
        if (kMainScreenHeight == IPHONE_4_SCREEN_HEIGHT) insetNumber = 8;
        else if (kMainScreenHeight == IPHONE_5_SCREEN_HEIGHT) insetNumber = 8;
        else if (kMainScreenHeight == IPHONE_6_SCREEN_HEIGHT) insetNumber = 8;
        else if (kMainScreenHeight == IPHONE_6PLUS_SCREEN_HEIGHT) insetNumber = 12;
        else if (kMainScreenHeight == IPHONE_X_SCREEN_HEIGHT) insetNumber = 8;
    }
    else
    {
        if (kMainScreenHeight == IPHONE_4_SCREEN_HEIGHT) insetNumber = 8;
        else if (kMainScreenHeight == IPHONE_5_SCREEN_HEIGHT) insetNumber = 8;
        else if (kMainScreenHeight == IPHONE_6_SCREEN_HEIGHT) insetNumber = 8;
        else if (kMainScreenHeight == IPHONE_6PLUS_SCREEN_HEIGHT) insetNumber = 12;
        else if (kMainScreenHeight == IPHONE_X_SCREEN_HEIGHT) insetNumber = 8;
    }
    [backButton setImageEdgeInsets:UIEdgeInsetsMake(0, -insetNumber, 0, insetNumber)];
    
    //添加按鈕事件
    [backButton addTarget:self action:@selector(customClickBackButton) forControlEvents:UIControlEventTouchUpInside];

    //添加手勢择示,獲取點擊,避免不容易點中返回按鈕的問題
    [self.navigationController.navigationBar addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(clickNavBar:)]];
    
    //把按鈕設(shè)置為導(dǎo)航欄左邊按鈕
    UIBarButtonItem *leftBarButtonItem = [[UIBarButtonItem alloc]initWithCustomView:backButton];
    self.navigationItem.leftBarButtonItem = leftBarButtonItem;
}

- (void)customClickBackButton
{
    [self.navigationController popViewControllerAnimated:YES];
}

- (void)clickNavBar:(UITapGestureRecognizer *)tap
{
    //獲取手勢的點
    CGPoint tapPoint = [tap locationInView:self.navigationController.navigationBar];
    if (tapPoint.x <= kMainScreenWidth * 0.15)//如果手勢的點在左邊15%晒旅,就讓它出發(fā)返回按鈕事件
    {
        [self customClickBackButton];
    }
}

@end

其中有個圖片重新渲染顏色的方法栅盲,我寫在了UIImage+extend這個分類中,可以改一張圖片的整體顏色废恋,方法實現(xiàn)如下:

- (UIImage *)imageWithColor:(UIColor *)color
{
    UIGraphicsBeginImageContextWithOptions(self.size, NO, self.scale);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextTranslateCTM(context, 0, self.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);
    CGContextSetBlendMode(context, kCGBlendModeNormal);
    CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height);
    CGContextClipToMask(context, rect, self.CGImage);
    [color setFill];
    CGContextFillRect(context, rect);
    UIImage*newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return newImage;
}

這樣處理之后的效果谈秫,就跟以前一樣了:


解決后效果.jpeg
鍵盤新特性
IQKeyboardManager鍵盤工具欄bug.jpeg
  • 現(xiàn)象:我在項目里使用IQKeyboardManager框架,正常情況下鱼鼓,紅圈處左邊應(yīng)該有上下跳轉(zhuǎn)輸入框的按鈕拟烫、右邊應(yīng)該有完成按鈕。
  • 原因:ios11鍵盤window底層布局變化迄本。
  • 解決辦法:
    更新IQKeyboardManager框架(研究了半天原因才發(fā)現(xiàn)人家已經(jīng)更新了做好適配了)硕淑。


    正常鍵盤工具欄.jpeg
XCode9運(yùn)行訪問系統(tǒng)相冊崩潰問題
保存圖片崩潰.jpeg
  • 現(xiàn)象:如圖保存圖片功能,在XCode9下運(yùn)行會崩潰
  • 原因:info.plist新增了權(quán)限配置
  • 解決:info.plist新增一條權(quán)限:Privacy - Photo Library Additions Usage Description


    新增權(quán)限.jpeg

iphoneX適配

主要是UI方面的適配岸梨,但也發(fā)現(xiàn)了一個不明原因的bug喜颁。

bug的解決

iphoneX上的bug.gif
  • 現(xiàn)象:注意觀察上圖中tabbar的位置。從帶tabbar的控制器push到其它控制器(hidesBottomBarWhenPushed = YES)曹阔,tabbar在push的時候會突然向上移動一截半开,但是pop的時候又是正常的,并且同樣是ios11的iphone8上都是正常的赃份。
  • 原因:目前不清楚是不是xcode9模擬器的問題寂拆,也不知道真機(jī)上會不會有奢米。
  • 解決:重寫- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated方法,自己控制push時tabbar的frame
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    // 重寫super
    [super pushViewController:viewController animated:animated];

    // 修改tabBra的frame
    if (isIPhoneX)//解決push時tabbar瞬間上移的問題
    {
        CGRect frame = self.tabBarController.tabBar.frame;
        frame.origin.y = [UIScreen mainScreen].bounds.size.height - frame.size.height;
        self.tabBarController.tabBar.frame = frame;
    }
}

即可恢復(fù)正常狀態(tài)纠永。

UI適配

主要是statusBar(頂部狀態(tài)欄)的高度不一樣了鬓长、底部增加了一個安全距離。適配思路就是避開這些地方尝江,具體思路下文分開介紹涉波。

頂部狀態(tài)欄的問題
頂部遮擋.png
  • 現(xiàn)象:如圖所示,頂部的searchView被擋住了一塊炭序。
  • 原因:這個頁面的頂部白色部分是一個view啤覆,它的高度我寫死為64(普通手機(jī)里導(dǎo)航欄+狀態(tài)欄整體高度),所以在普通手機(jī)里看起就是一個正常的導(dǎo)航欄惭聂,而在這里就發(fā)生了遮擋窗声,因為普通手機(jī)的狀態(tài)欄高度是20而iphoneX是44辜纲。
  • 解決:所有這種頂部的view笨觅,都不應(yīng)該寫死64的高度,而應(yīng)該寫成導(dǎo)航欄高度+狀態(tài)欄高度耕腾。
    導(dǎo)航欄高度所有都是44见剩,沒有變化,而狀態(tài)欄高度分為20和44幽邓,布局時判斷一下是不是iphoneX炮温,數(shù)值也隨之變化,最好是寫成宏牵舵。
    頂部遮擋的解決.png
底部安全距離的問題
iphoneX上tabbar.png
  • 現(xiàn)象:如上圖所示柒啤,tabbar的高度明顯比普通手機(jī)里高得多,增加的區(qū)域大概是下圖紅圈的區(qū)域:
    自動增加的區(qū)域.jpeg

    這部分的高度畸颅,即底部安全距離的高度是34
    總所周知担巩,底部出現(xiàn)安全距離,是為了給系統(tǒng)的手勢讓路没炒,用戶在底部黑條附近進(jìn)行拖動時涛癌,可以達(dá)到原來home鍵的效果。
    然而送火,通過我在模擬器上的反復(fù)實驗拳话,系統(tǒng)手勢的觸發(fā)范圍,并沒有34這么高种吸,而是從黑條頂部到屏幕底部這個范圍弃衍,這部分的高度,以下稱作系統(tǒng)手勢有效范圍坚俗,高度為13镜盯。
  • 實際問題:上圖是系統(tǒng)處理的tabbar高度岸裙。在自己寫的頁面里,就會出現(xiàn)遮擋的問題:


    底部遮擋效果.jpeg
  • 解決:底部兩個按鈕背后有個白色view速缆,它的高度是寫死為54降允,應(yīng)該改為54+手勢有效范圍高度,手勢有效范圍高度根據(jù)是不是iphoneX賦值為13或0艺糜,這樣就完美適配了iphoneX和普通手機(jī)剧董,解決效果如下:


    底部遮擋問題解決.jpeg

備注

1、干貨分享:對于手機(jī)型號的判斷倦踢、底部高度送滞、頂部高度等,我都寫成了宏辱挥,需要的朋友拿走不謝:

//是否是手機(jī)
#define isIPhone (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
//是否是iphoneX
#define isIPhoneX (kMainScreenWidth >= 375.0f && kMainScreenHeight >= 812.0f && isIPhone)
//蘋果X寬高
#define IPHONE_X_SCREEN_WIDTH 375
#define IPHONE_X_SCREEN_HEIGHT 812
//底部安全高度
#define BOTTOM_SAFE_HEIGHT (isIPhoneX ? 34 : 0)
//系統(tǒng)手勢高度
#define SYSTEM_GESTURE_HEIGHT (isIPhoneX ? 13 : 0)
//tabbar高度
#define TABBAR_HEIGHT (49 + BOTTOM_SAFE_HEIGHT)
//狀態(tài)欄高度
#define STATUS_HEIGHT (isIPhoneX ? 44 : 20)
//導(dǎo)航欄高
#define NAVBAR_HEIGHT 44
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市边涕,隨后出現(xiàn)的幾起案子晤碘,更是在濱河造成了極大的恐慌,老刑警劉巖功蜓,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件园爷,死亡現(xiàn)場離奇詭異,居然都是意外死亡式撼,警方通過查閱死者的電腦和手機(jī)童社,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來著隆,“玉大人扰楼,你說我怎么就攤上這事∶榔郑” “怎么了弦赖?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長浦辨。 經(jīng)常有香客問我蹬竖,道長,這世上最難降的妖魔是什么流酬? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任币厕,我火速辦了婚禮,結(jié)果婚禮上芽腾,老公的妹妹穿的比我還像新娘旦装。我一直安慰自己,他們只是感情好晦嵌,可當(dāng)我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布同辣。 她就那樣靜靜地躺著拷姿,像睡著了一般。 火紅的嫁衣襯著肌膚如雪旱函。 梳的紋絲不亂的頭發(fā)上响巢,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天,我揣著相機(jī)與錄音棒妨,去河邊找鬼踪古。 笑死,一個胖子當(dāng)著我的面吹牛券腔,可吹牛的內(nèi)容都是我干的伏穆。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼纷纫,長吁一口氣:“原來是場噩夢啊……” “哼枕扫!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起辱魁,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤烟瞧,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后染簇,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體参滴,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年锻弓,在試婚紗的時候發(fā)現(xiàn)自己被綠了砾赔。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡青灼,死狀恐怖暴心,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情聚至,我是刑警寧澤酷勺,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站扳躬,受9級特大地震影響脆诉,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜贷币,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一击胜、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧役纹,春花似錦偶摔、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽策州。三九已至,卻和暖如春宫仗,著一層夾襖步出監(jiān)牢的瞬間够挂,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工藕夫, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留孽糖,地道東北人。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓毅贮,卻偏偏與公主長得像办悟,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子滩褥,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,611評論 2 353

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