iOS11魔慷、iPhoneX以及XCode9適配總結(jié)

iOS11正式發(fā)布后只锭,尤其隨著新機(jī)型iPhoneX的即將發(fā)售。iOS開發(fā)面臨很多新的的兼容性問題需要適配和修復(fù)院尔。經(jīng)過一段時間的適配蜻展,大部分暴露的問題已經(jīng)得到解決。這里把這些問題作一個統(tǒng)一的匯總邀摆,方便其他同學(xué)再遇到類似的問題時纵顾,進(jìn)行查閱。
這些問題栋盹,大致分為下面幾類:

一施逾、iOS11適配相關(guān)
1、iOS11系統(tǒng)版本號判斷:

(1)擴(kuò)展原有的宏判斷,增加

#define IOS11_OR_LATER      ( [[[UIDevice currentDevice] systemVersion] compare:@"11.0" options:NSNumericSearch] != NSOrderedAscending )
#define IOS10_OR_LATER      ( [[[UIDevice currentDevice] systemVersion] compare:@"10.0" options:NSNumericSearch] != NSOrderedAscending )

#define IOS10_OR_EARLIER    ( !IOS11_OR_LATER )
#define IOS9_OR_EARLIER     ( !IOS10_OR_LATER )

(2)通過宏進(jìn)行判斷

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_11_0
...
#else
...
#endif

(3)使用iOS11新的語法接口:

if (@available(iOS 11.0, *))
{
    NSLog(@"%@", [[UIDevice currentDevice] systemVersion]);
}
2汉额、新增face ID人臉識別JS組件:

具體的代碼實(shí)現(xiàn)其實(shí)和指紋識別就是同一個系統(tǒng)接口曹仗,也就是說之前的TouchID實(shí)現(xiàn)在iPhoneX上可以不作任何適配,直接無縫切換到FaceID闷愤。
詳細(xì)的代碼參考如下:

// 返回是否支持faceid人臉識別
- (void)isSupportFaceIDVerify:(NSDictionary *)dict
{
    NSString *callBack = [dict objectForKey:@"success"];
    
    NSString *resultValue = nil;
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_11_0
    
    LAContext *myContext = [[LAContext alloc] init];
    NSError *authError = nil;
    NSString *myLocalizedReasonString = @"刷臉認(rèn)證";
    
    if ([myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authError]) {
        resultValue = @"支持";
        [myContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
                  localizedReason:myLocalizedReasonString
                            reply:^(BOOL success, NSError *error) {
                                if (success) {
                                    // User authenticated successfully, take appropriate action
                                    dispatch_async(dispatch_get_main_queue(), ^{
                                        
                                        [FireflyAlertView showWithTitle:nil
                                                                message:@"驗(yàn)證成功"
                                                            buttonTitle:@"確定"];
                                    });
                                } else {
                                    // User did not authenticate successfully, look at error and take appropriate action
                                    if (error.code == kLAErrorUserFallback)
                                    {
                                        WebJSLog_i(@"User tapped Enter Password");
                                        dispatch_async(dispatch_get_main_queue(), ^{
                                            
                                            [FireflyAlertView showWithTitle:nil
                                                                    message:@"手動輸入密碼"
                                                                buttonTitle:@"確定"];
                                        });
                                    }
                                    else if (error.code == kLAErrorUserCancel)
                                    {
                                        WebJSLog_i(@"User tapped Cancel");
                                    }
                                    else
                                    {
                                        dispatch_async(dispatch_get_main_queue(), ^{
                                            
                                            [FireflyAlertView showWithTitle:nil
                                                                    message:@"驗(yàn)證失敗"
                                                                buttonTitle:@"確定"];
                                        });
                                    }
                                }
                            }];
    }
    else
    {
        WebJSLog_i(@"error:%@", [authError.userInfo description]);
        [FireflyAlertView showWithTitle:nil
                                message:[authError.userInfo description]
                            buttonTitle:@"確定"];
        resultValue = @"不支持";
    }
#else
    {
        resultValue = @"不支持";
    }
#endif
    NSDictionary *returnDict = @{@"success" : resultValue,
                                 @"errorMsg" : @""
                                 };
    NSString *returnString = [[NSString alloc] initWithData:[returnDict toJSON]
                                                   encoding:NSUTF8StringEncoding];
    NSString *fullCallback = [NSString stringWithFormat:@"%@('%@')",callBack, returnString];
    [self.webController.webView stringByEvaluatingJavaScriptFromString:fullCallback];
}
3整葡、保存圖片權(quán)限導(dǎo)致的閃退問題:

試用保存圖片到相冊時,可能會發(fā)生下面的閃退問題:

This app has crashed because it attempted to access privacy-sensitive data without a usage description. The app's Info.plist must contain an NSPhotoLibraryAddUsageDescription key with a string value explaining to the user how the app uses this data.

原因:
權(quán)限隱私提示語沒有導(dǎo)致的讥脐。
解決
info.plist增加提示語:

屏幕快照 2017-11-08 上午10.32.59.png

二遭居、iPhoneX適配相關(guān)

iPhoneX最重要的改動是屏幕分辨率發(fā)生了變化。
并且取消了物理按鍵旬渠,由手勢取而代之俱萍。對于開發(fā)人員而言,多了個safearea(安全區(qū)域)的概念告丢。

1枪蘑、iPhoneX屏幕尺寸介紹
  • 豎屏尺寸:1125px × 2436px(375pt × 812pt @3x)
  • 橫屏尺寸:2436px × 1125px(812pt × 375pt @3x)

與其它iOS設(shè)備的差異
以下是與iPhone 6、7岖免、8 (375×667pt) 相比岳颇。

  • Status Bar 高度由 20pt 增長為44pt。


  • 底部:預(yù)留 34pt 給 Home Indicator區(qū)域

寬度不變颅湘,高度多出 145pt话侧,但由于 Status Bar 以及 Home Indicator,實(shí)際上可有效利用的高度為
145 – 24 (Status Bar) – 34 (Home Indicator) = 87pt

差異對比

  • 鍵盤高度由 216pt 增長為 291pt

這里主要基于Firefly客戶端框架現(xiàn)有的UI結(jié)構(gòu)闯参,總結(jié)下適配的經(jīng)驗(yàn)瞻鹏。
Firefly現(xiàn)有UI結(jié)構(gòu):

  • (1)demo UI使用絕對坐標(biāo),沒有使用自動布局鹿寨;
  • (2)UI基本由代碼實(shí)現(xiàn)新博,基本沒有使用XIB;
  • (3)導(dǎo)航欄自定義脚草,沒有使用系統(tǒng)導(dǎo)航欄赫悄;
  • (4)底部欄使用系統(tǒng)組件UIToolbar實(shí)現(xiàn);
  • (5)默認(rèn)的自適配設(shè)置如下:
  • (6)App啟動圖使用LaunchImage配置玩讳;
- (void)setDefaultLayout
{
    if (IOS6_OR_EARLIER)
    {
        self.view.frame = CGRectMake(0, 0,
                                     self.view.bounds.size.width,
                                     self.view.bounds.size.height);
    }
    
    if ([self respondsToSelector:@selector(setEdgesForExtendedLayout:)])
    {
        self.automaticallyAdjustsScrollViewInsets = NO;
        self.edgesForExtendedLayout = UIRectEdgeNone;
    }
}
1涩蜘、啟動圖適配:

解決iPhoneX上的app上下為黑色區(qū)域,不是全屏
適配方案
添加新的LaunchImage熏纯,編輯LaunchImage的Contents.json文件同诫,在前面添加如下代碼

    {
      "extent" : "full-screen",
      "idiom" : "iphone",
      "subtype" : "2436h",
      "filename" : "LaunchImage-Portrait~iphoneX@3x.png",
      "minimum-system-version" : "11.0",
      "orientation" : "portrait",
      "scale" : "3x"
    },

啟動圖分辨率為:1125x2436

2、基礎(chǔ)適配代碼改造

底層框架需要增加的一些適配公共代碼:

//iPhoneX機(jī)型判斷
#define IS_iPhoneX ([UIScreen mainScreen].bounds.size.width == 375 && [UIScreen mainScreen].bounds.size.height == 812)
//狀態(tài)欄高度配置
#define STATUS_GAP (IS_iPhoneX? 44 : 20)
//設(shè)備底部安全距離配置
#define iPhoneXSafeBottomMargin (IS_iPhoneX ? 34.f : 0.f)
3樟澜、iPhoneX導(dǎo)航欄適配:

基于Firefly UI現(xiàn)有的導(dǎo)航欄實(shí)現(xiàn)方案误窖,iPhoneX設(shè)備上Navigation Bar 的適配只需要將高度增加 44pt即可叮盘。
相關(guān)的代碼實(shí)現(xiàn)如下:

#define STATUS_GAP (IS_iPhoneX? 44 : 20)
...
#define NAV_BAR_HEIGHT 44
#define NAV_BAR_FRAME (IOS7_OR_LATER? CGRectMake(0, 0, ScreenWidth, NAV_BAR_HEIGHT + STATUS_GAP):CGRectMake(0, 0, ScreenWidth, NAV_BAR_HEIGHT))

適配效果:

4、iPhoneX底部欄適配:

基于Firefly UI現(xiàn)有的導(dǎo)航欄實(shí)現(xiàn)方案霹俺,iPhoneX設(shè)備上底部欄的適配需要作以下改動:
(1)toolbar高度適配
相關(guān)的代碼實(shí)現(xiàn)如下:

#define iPhoneXSafeBottomMargin (IS_iPhoneX ? 34.f : 0.f)
...
#define TOOLBAR_HEIGHT (48 + iPhoneXSafeBottomMargin)

(2)toolbar改用自定義FireflyToolbar實(shí)現(xiàn)
實(shí)現(xiàn)的代碼如下:

@interface TestToolbar : FireflyToolbar
@implementation FireflyToolbar

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.backgroundColor = UIColorFromRGBAValue(0x0e, 0x17, 0x31, 0.85);
    }
    return self;
}


- (void)setItems:(NSArray *)aItems
{
    [aItems count];
    NSArray *tmpItems = [[NSArray alloc] initWithArray:aItems];
    [tmpItems enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        
        UIView *tmpItem = (UIView *)obj;
        CGRect itemFrame = [self getItemFrame:idx
                                        count:[aItems count]
                                        frame:tmpItem.frame];
        tmpItem.frame = itemFrame;
        [self addSubview:tmpItem];
    }];
}

- (CGRect)getItemFrame:(NSUInteger)aIndex count:(NSUInteger)aCount frame:(CGRect)aFrame
{
    CGRect itemFrame = CGRectZero;
    CGFloat itemWidth =  (ScreenWidth - (aCount + 1) * ToolbarItemGap) / aCount;
    itemFrame.size.height = aFrame.size.height;
    itemFrame.origin.y = (TOOLBAR_BASICHEIGHT - aFrame.size.height) / 2.0;
    if (aFrame.size.width < itemWidth)
    {
        itemFrame.size.width = aFrame.size.width;
        itemFrame.origin.x = aIndex * aFrame.size.width + (aIndex + 1) * (ScreenWidth - aCount * aFrame.size.width) / (aCount + 1);
    }
    else
    {
        itemFrame.size.width = itemWidth;
        itemFrame.origin.x = aIndex * itemWidth + (aIndex + 1) * ToolbarItemGap;
    }
    return itemFrame;
}

適配效果:

三柔吼、XCode9適配相關(guān)
1、函數(shù)定義跳轉(zhuǎn)修改:

XCode使用“commad+函數(shù)”默認(rèn)不再直接跳向函數(shù)定義丙唧,而是彈出一個工具面板愈魏。如下所示:

恢復(fù)之前的設(shè)置,可以進(jìn)行如下修改:

2想际、打包命令修改:

控制臺打包命令

xcodebuild -exportArchive  -exportOptionsPlist "$exportPlistPath"  -archivePath "$xcarchivePath" -exportPath  "$exportPath"

參數(shù)-exportOptionsPlist 配置文件需要進(jìn)行修改培漏,增加provisioningProfiles字段,新的配置文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>method</key>
    <string>development</string>
    <key>provisioningProfiles</key>
    <dict>
        <key>com.cmbc.firefly.testlib</key>
        <string>firefly161109</string>
    </dict>
</dict>
</plist>

參考:
iPhoneX人機(jī)交互指南
http://www.reibang.com/p/670318acae90
https://developer.apple.com/ios/update-apps-for-iphone-x/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末胡本,一起剝皮案震驚了整個濱河市牌柄,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌侧甫,老刑警劉巖珊佣,帶你破解...
    沈念sama閱讀 222,000評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異披粟,居然都是意外死亡咒锻,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評論 3 399
  • 文/潘曉璐 我一進(jìn)店門守屉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來虫碉,“玉大人,你說我怎么就攤上這事胸梆。” “怎么了须板?”我有些...
    開封第一講書人閱讀 168,561評論 0 360
  • 文/不壞的土叔 我叫張陵碰镜,是天一觀的道長。 經(jīng)常有香客問我习瑰,道長绪颖,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,782評論 1 298
  • 正文 為了忘掉前任甜奄,我火速辦了婚禮柠横,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘课兄。我一直安慰自己牍氛,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,798評論 6 397
  • 文/花漫 我一把揭開白布烟阐。 她就那樣靜靜地躺著搬俊,像睡著了一般紊扬。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上唉擂,一...
    開封第一講書人閱讀 52,394評論 1 310
  • 那天餐屎,我揣著相機(jī)與錄音,去河邊找鬼玩祟。 笑死腹缩,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的空扎。 我是一名探鬼主播藏鹊,決...
    沈念sama閱讀 40,952評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼勺卢!你這毒婦竟也來了伙判?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,852評論 0 276
  • 序言:老撾萬榮一對情侶失蹤黑忱,失蹤者是張志新(化名)和其女友劉穎宴抚,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體甫煞,經(jīng)...
    沈念sama閱讀 46,409評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡菇曲,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,483評論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了抚吠。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片常潮。...
    茶點(diǎn)故事閱讀 40,615評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖楷力,靈堂內(nèi)的尸體忽然破棺而出喊式,到底是詐尸還是另有隱情,我是刑警寧澤萧朝,帶...
    沈念sama閱讀 36,303評論 5 350
  • 正文 年R本政府宣布桩砰,位于F島的核電站江锨,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜匆光,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,979評論 3 334
  • 文/蒙蒙 一谅摄、第九天 我趴在偏房一處隱蔽的房頂上張望民宿。 院中可真熱鬧往枣,春花似錦、人聲如沸用爪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽偎血。三九已至班眯,卻和暖如春希停,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背署隘。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評論 1 272
  • 我被黑心中介騙來泰國打工宠能, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人磁餐。 一個月前我還...
    沈念sama閱讀 49,041評論 3 377
  • 正文 我出身青樓违崇,卻偏偏與公主長得像,于是被迫代替她去往敵國和親诊霹。 傳聞我的和親對象是個殘疾皇子羞延,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,630評論 2 359

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