iOS 新機(jī)適配原理及更新三方應(yīng)用——讓 TIM 適配 Xs Max

背景

自從買了 iPhone Xs Max仔掸,就一直處于等待應(yīng)用適配新設(shè)備的狀態(tài)脆贵。不過本次增加的新屏幕(Xs Max)與 iPhone X 的屏幕比例相似,所以即使應(yīng)用沒有第一時間適配 Xs Max 機(jī)型起暮,iOS 也會把應(yīng)用的窗口以 iPhone X 為基礎(chǔ)拉伸到滿屏丹禀,以便最大限度的展示應(yīng)用界面。相比之前推出 X 和 Plus 系列時鞋怀,用戶的過度成本降低了許多双泪。

但是在苦苦等待過程中,騰訊的 TIM 一直沒有得到更新密似。即便是等待蘋果開售 iPhone Xr(Xr 在 Xs 開售后一個月才開售焙矛,所以開發(fā)者可能會等到 Xr 開售后才一起適配 Xs Max 和 Xr),還是等待蘋果修復(fù)新的 Assets 壓縮算法在 iOS 9 下閃退的 bug残腌,微信也在年底前完成了 Xs Max 的適配村斟,并且推出了微信 7.0。然而直到作者編寫此文(2019年01月26日)時抛猫,TIM 依舊沒有更新蟆盹,粗糙的 UI 元素讓人覺得不是一個 1 萬塊錢手機(jī)該有的界面。處于強(qiáng)迫癥考慮闺金,能否在沒有三方應(yīng)用源碼的情況下讓三方應(yīng)用適配新的機(jī)型呢逾滥?

本文將通過以下幾點的研究,來學(xué)習(xí)蘋果的應(yīng)用適配之道败匹。

  • 在發(fā)布新設(shè)備之后寨昙,蘋果如何讓沒有適配新設(shè)備的應(yīng)用正常運(yùn)行在新的設(shè)備上
  • 在發(fā)布新設(shè)備之后讥巡,開發(fā)者如何讓自己的應(yīng)用適配新的設(shè)備
  • 在發(fā)布新設(shè)備之后,如何讓三方應(yīng)用適配新的設(shè)備(以 TIM 為例)

另外簡單介紹一下 TIM:

TIM 是騰訊推出的一款精簡版的 QQ舔哪。騰訊已推出多個版本的QQ欢顷,如:QQ、國際版捉蚤、HD 版抬驴、TIM。TIM 是一個面向工作缆巧、白領(lǐng)的一款產(chǎn)品布持。擁有強(qiáng)大的文件管理,以及精簡的 UI 界面盅蝗。由于他使用簡單鳖链,辦公高效姆蘸,得到極多喜歡簡約風(fēng)格的用戶(包括作者)一致好評墩莫。

PS:本文只探討 iPhone,不探討 iPad逞敷。

iPad 原理如同 iPhone狂秦。

iOS 如何兼容沒有適配新屏幕的應(yīng)用

即使蘋果在開發(fā)者協(xié)議中注明:任何時候,開發(fā)者上傳到 App Store 的應(yīng)用必須適配最新的設(shè)備推捐,否則被拒(你爸爸還是你爸爸)裂问。蘋果也無法保證在開售新設(shè)備的時候,已經(jīng)在 App Store 上的應(yīng)用全部都已被更新過牛柒。所以每當(dāng)新設(shè)備(新屏幕)發(fā)布時堪簿,蘋果都要在新的 iOS 系統(tǒng)中讓新的設(shè)備兼容舊的應(yīng)用。

先回憶一下蘋果發(fā)布的幾款機(jī)型(主要探討屏幕)皮壁,以及用戶過渡期的處理方式(兼容已經(jīng)在 App Store 上還未適配新設(shè)備的應(yīng)用)椭更。

從 2007 年第一代 iPhone 發(fā)布一直到 2018 年的 iPhone Xs Max,蘋果一共發(fā)布了 8 款 iPhone 屏幕蛾魄,它們分別如下(以搭載該屏幕的第一款設(shè)備命名虑瀑,以發(fā)布時間及市場定位排序):

Name Pixel Size PPI Scale 過渡期的自適配方式
iPhone 320 x 480 320 x 480 326 1 iPhone 祖宗,無需適配
iPhone 4 640 x 960 320 x 480 326 2 寬度拉伸滴须,高度拉伸舌狗,無黑邊
iPhone 5 640 x 1136 320 x 568 326 2 寬度不變,垂直居中扔水,上下黑邊
iPhone 6 750 x 1334 375 x 667 326 2 寬度拉伸痛侍,垂直居中,上下黑邊
iPhone 6 Plus 1242 x 2208 414 x 736 401 3 寬度拉伸魔市,垂直居中恋日,上下黑邊
iPhone X 1125 x 2436 375 x 812 458 3 寬度拉伸膀篮,垂直居中,上下黑邊
iPhone Xr 1242 x 2688 414 x 896 326 2 寬度拉伸岂膳,高度拉伸誓竿,無黑邊
iPhone Xs Max 828 x 1792 414 x 896 458 3 寬度拉伸,高度拉伸谈截,無黑邊

如果新的設(shè)備的長寬比和舊的設(shè)備相同(Size 相同筷屡,或者 Size.width / Size.height 近似相同),如:iPhone 到 iPhone 4簸喂,iPhone X 到 iPhone Xs Max毙死,就單純的按照舊的設(shè)備來渲染(UIScreen.mainScreen.bounds 還是舊的設(shè)備的值),并且等比例拉伸到全屏喻鳄,所以會變得有的線條有點粗獷 = =扼倘。

如果新的設(shè)備的長款比和舊的設(shè)備不同,如:iPhone 4 到 iPhone 5(臉被拉長了)除呵,iPhone 5 到 iPhone 6 和 Plus(不僅臉長了再菊,還胖了)。就以寬度為基準(zhǔn)盡可能的等比例放大颜曾,長度不夠的黑邊湊纠拔,同時整體垂直居中(這樣就導(dǎo)致上下留有黑邊)。

以上兩種處理雖然最終都不能完美解決問題泛豪,但是至少保證舊的應(yīng)用在渲染 UI 的時候不會因屏幕分辨率而導(dǎo)致布局錯亂稠诲。

為什么有 Autolayout 還不能完美自適應(yīng)呢?

因為你 Autolayout 再怎么牛逼诡曙,也躲不過無劉海到有劉海的變化臀叙。。价卤。

應(yīng)用開發(fā)者如何適配新的屏幕

對于使用 UIKit.framework 提供的幾個常用接口來開發(fā) UI 的應(yīng)用劝萤,在適配新屏幕時就非常的簡便,一般只有以下三步驟:

  1. 下載新的 Xcode
  2. 加入新屏幕對應(yīng)大小的啟動圖
  3. 重新構(gòu)建應(yīng)用

對于大量自定義 UI 框架的應(yīng)用(如自己重寫了 UINavigationController)荠雕,需要在代碼中加入新設(shè)備的判斷(此文不考慮這種情況)稳其。

在這里必須吐槽一下,每當(dāng)有新屏幕出現(xiàn)炸卑,網(wǎng)絡(luò)上就有大量的博客:《教你如何適配新的 iPhone》既鞠,《適配新的 iPhone 看我就夠了》,《你真的適配新的 iPhone 了嗎》盖文。嘱蛋。。
甚至有的公司為了適配新的 iPhone 花了至少一個工作日的時間。

如果應(yīng)用使用蘋果標(biāo)準(zhǔn) API 構(gòu)建界面洒敏,真的只需要添加一個啟動圖然后重新打包即可解決問題龄恋。

我們對每一個步驟進(jìn)行一次分析:

1. 使用最新的 Xcode

使用最新的 Xcode 無疑是正確的。最新的 Xcode 可以給我們帶來兩個功能:

  • 新的 iOS SDK
  • 新屏幕的啟動圖坑位

這兩個功能在適配新的設(shè)備時給了很大的幫助凶伙。新的 SDK 能夠讓應(yīng)用在新的 iOS 系統(tǒng)上完美運(yùn)行郭毕。新的啟動圖能夠讓應(yīng)用獲取到正確的屏幕大小。

2. 加入屏幕對應(yīng)大小的啟動圖

如果某個應(yīng)用使用純代碼開發(fā)(沒有使用 Storyboardxib)函荣,那么這個應(yīng)用的啟動代碼應(yīng)該如下:

- (BOOL)application:(UIApplication *)application didFinishLaunchedWithOptions:(NSDictionary *)launchOptions {
    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    self.window.rootViewController = [[ViewController alloc] init];
    [self.window makeKeyAndVisible];
}

適配新的屏幕显押,本質(zhì)就是這個 self.window 對象的大小等于新的屏幕,然后子元素根據(jù)新的窗口大小來創(chuàng)建布局約束傻挂。

代碼中動態(tài)使用 [UIScreen mainScreen].bounds 的大小來創(chuàng)建 window 對象乘碑,似乎是完美適配了任何大小的屏幕。但實際上金拒,如果沒有添加新的設(shè)備的啟動圖兽肤,UIScreen 獲取到的屏幕大小并非真實設(shè)備的屏幕大小,而是 iOS 兼容模式所用的舊設(shè)備的屏幕大小绪抛。這是 iOS 兼容模式的一種優(yōu)化资铡,防止新的屏幕分辨率的出現(xiàn)導(dǎo)致應(yīng)用 UI 控件布局錯亂(寧愿等比例拉伸)。

3. 重新構(gòu)建應(yīng)用

不用多說了睦疫。

猜測——判斷應(yīng)用是否需要在兼容模式

首先有一個客觀事實:

當(dāng)新的設(shè)備發(fā)布后害驹,如果使用舊的 Xcode 打包的 ipa 一樣無法適配新機(jī)
如果使用新的 Xcode 并且沒有加入新的啟動圖的 ipa 一樣無法適配新機(jī)鞭呕。

因此是否適配取決于 Xcode 版本號以及是否包含啟動圖蛤育,與打包的時間無關(guān)。

之前說明葫松,開發(fā)者適配新設(shè)備的方法是:使用最新的 Xcode瓦糕,加入新的設(shè)備的啟動圖后重新打包應(yīng)用。所以 iOS 只需判斷這個應(yīng)用是否經(jīng)過這樣方式處理腋么,就可以知道這個應(yīng)用是否需要兼容模式下運(yùn)行咕娄。

1. 判斷是否包含啟動圖

判斷是否是啟動圖是一件很簡單的事情,只需要判斷當(dāng)前屏幕分辨率對應(yīng)的圖片是否存在在 .app 文件夾中即可珊擂,這個判斷會經(jīng)歷從 Info.plist 讀取啟動圖配置圣勒、查找啟動圖的幾個階段,此文不在闡述摧扇。

總之肯定會多一個 LaunchImage-xxx-xxx@nx.png 圖片文件圣贸,并且分辨率和別的啟動圖不同。

2. 判斷是否是新的 Xcode 打包

如何判斷這個 ipa 是用什么版本的 Xcode 打的包呢扛稽?

在一個 ipa 包中有幾個特殊文件:

  • Binary
  • Info.plist
  • _CodeSignature

clang 中不包含有 Xcode 版本信息吁峻,同時在編譯的腳本中也沒有將 Xcode 的版本信息作為參數(shù)傳遞給 clang,所以二進(jìn)制(Binary)文件中不含有有關(guān) Xcode 信息的數(shù)據(jù)。

_CodeSignature 是簽名產(chǎn)物用含,簽名時也沒有 Xcode 信息矮慕,所以也不可能有 Xcode 信息的數(shù)據(jù)。

Info.plist 是 App 的 Manifest 文件啄骇,包含 App 的各種信息痴鳄。這是我們著重考慮的方向。

分析 Info.plist 文件

打開一個自己做的 app 的 Info.plist 文件缸夹,可以查看到一下內(nèi)容:

Info.plist

其中紅色標(biāo)記的就是作者查找出來帶有編譯環(huán)境的信息:

  • DTSDKName 開發(fā)所用的 SDK 名稱
  • DTXcode 開發(fā)所用的 Xcode 版本號(Xcode 10.1.0)
  • DTSDKBuild 開發(fā)所用的 SDK Build 號(SDK 內(nèi)部版本號)
  • BuildMachineOSBuild 開發(fā)所用的機(jī)器 Build 號(Mac 的內(nèi)部版本號)
  • DTPlatformVersion 開發(fā)所用的平臺版本號
  • DTXcodeBuild 開發(fā)所用的 Xcode Build 號(Xcode 內(nèi)部版本號)
  • DTPlatformBuild 開發(fā)所用的平臺 Build 號(平臺的內(nèi)部版本號)

已經(jīng)很完美了夏跷,Xcode、MacOS明未、SDK 版本號全都在槽华。

同時我們也可以看見,如果應(yīng)用使用的是啟動圖趟妥,而不是 Storyboard猫态,在 Info.plist 文件中會包含一項 UILaunchImages:

使用啟動圖的 Info.plist

由此我們可以猜測蘋果的兼容方案。

蘋果的兼容方案

當(dāng) iOS 要啟動一個 App 時披摄,會先讀取 Info.plist 對應(yīng)編譯環(huán)境版本號亲雪,判斷是否是新版 Xcode 打的包。如果是新版本的 Xcode疚膊,再判斷是否包含啟動圖义辕。如果包含啟動圖,則說明該 ipa 適配了新機(jī)寓盗,無需兼容灌砖。反之,使用兼容模式運(yùn)行此 app傀蚌。

iOS 兼容模式

驗證——將三方應(yīng)用適配新機(jī)(以 TIM 為例)

鑒于以上的分析基显,只需要將 Info.plist 中的對應(yīng)版本號提高,并且加入新的啟動圖即可實現(xiàn)三方應(yīng)用適配新機(jī)善炫。

1. 砸殼

由于所有在 App Store 上的應(yīng)用均被蘋果加殼撩幽,并且我們將來需要修改 Info.plist 文件,所以必須要重簽名箩艺。因此我們所修改的 TIM 需要砸殼處理窜醉。

砸殼方式有很多種,此文不闡述艺谆。

參考:Clutch榨惰、frida-ios-dump 等等。

2. 修改 Info.plist 中的版本號

由于 Info.plist 中版本號有點復(fù)雜擂涛,有部分為內(nèi)部版本號(需要查詢)读串,所以我將已經(jīng)適配好 Xs Max 的應(yīng)用拿來做參考聊记,進(jìn)行數(shù)據(jù)覆蓋。

此處使用的是 WeChat 7.0.0 的 Info.plist 作為參考依據(jù)恢暖。將上述提到的 7 個字段的值排监,從微信的 Info.plist 文件里提取出來,覆蓋到 TIM 的 Info.plist 文件中杰捂。分別是:DTSDKName舆床、DTXcodeDTSDKBuild嫁佳、BuildMachineOSBuild挨队、DTPlatformVersionDTXcodeBuild蒿往、DTPlatformBuild盛垦。

除版本號外,Info.plist 也包含支持設(shè)備的硬件號瓤漏,字段為 UISupportedDevices

通過助手類軟件可以讀出 Xs Max 設(shè)備號為 iPhone11,6腾夯,將其加入到 UISupportedDevices 字段中,防止安裝時報錯(不支持此設(shè)備)

3. 添加啟動圖

經(jīng)過與微信的比較蔬充,發(fā)現(xiàn) Xs Max 和 Xr 的啟動圖分別是:

名稱 大小 機(jī)型
LaunchImage-1200-Portrait-1792h@2x.png 828 x 1792 Xr
LaunchImage-1200-Portrait-2688h@3x.png 1242 x 2688 Xs Max

終于祭出了自己的美工技術(shù)了蝶俱。提取 X 的啟動圖,修改為上述兩個文件饥漫,并添加到包中榨呆。

打開 Info.plist 文件,比較后在 UILaunchImages 的數(shù)組里添加兩項啟動圖配置:

<dict>
    <key>UILaunchImageOrientation</key>
    <string>Portrait</string>
    <key>UILaunchImageName</key>
    <string>LaunchImage-1200-Portrait-2688h</string>
    <key>UILaunchImageSize</key>
    <string>{414, 896}</string>
    <key>UILaunchImageMinimumOSVersion</key>
    <string>12.0</string>
</dict>
<dict>
    <key>UILaunchImageOrientation</key>
    <string>Portrait</string>
    <key>UILaunchImageName</key>
    <string>LaunchImage-1200-Portrait-1792h</string>
    <key>UILaunchImageSize</key>
    <string>{414, 896}</string>
    <key>UILaunchImageMinimumOSVersion</key>
    <string>12.0</string>
</dict>

保存庸队。

4. 重簽名

重簽名的方式有很多種积蜻,此文不再詳述。

至于重簽名后無法正常推送皿哨,不在此文的探討范圍浅侨,我就不詳細(xì)說明了纽谒。

對比圖

左側(cè)為適配前证膨,右側(cè)為適配后

聊天列表
文件管理
好友列表

適配后的 UI 變得非常的細(xì)膩。舒服~~

總結(jié)

Xcode 在打包的時候講打包環(huán)境信息(各種版本號)保存到 Info.plist 中鼓黔。iOS 運(yùn)行應(yīng)用時央勒,通過 Info.plist 中的版本號進(jìn)行比較,來判斷開發(fā)者是否適配了新設(shè)備澳化,從而判斷是否需要兼容模式運(yùn)行此應(yīng)用崔步。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市缎谷,隨后出現(xiàn)的幾起案子井濒,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,729評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瑞你,死亡現(xiàn)場離奇詭異酪惭,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)者甲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評論 3 399
  • 文/潘曉璐 我一進(jìn)店門春感,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人虏缸,你說我怎么就攤上這事鲫懒。” “怎么了刽辙?”我有些...
    開封第一講書人閱讀 169,461評論 0 362
  • 文/不壞的土叔 我叫張陵窥岩,是天一觀的道長。 經(jīng)常有香客問我宰缤,道長谦秧,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,135評論 1 300
  • 正文 為了忘掉前任撵溃,我火速辦了婚禮疚鲤,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘缘挑。我一直安慰自己集歇,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 69,130評論 6 398
  • 文/花漫 我一把揭開白布语淘。 她就那樣靜靜地躺著诲宇,像睡著了一般。 火紅的嫁衣襯著肌膚如雪惶翻。 梳的紋絲不亂的頭發(fā)上姑蓝,一...
    開封第一講書人閱讀 52,736評論 1 312
  • 那天,我揣著相機(jī)與錄音吕粗,去河邊找鬼纺荧。 笑死,一個胖子當(dāng)著我的面吹牛颅筋,可吹牛的內(nèi)容都是我干的宙暇。 我是一名探鬼主播,決...
    沈念sama閱讀 41,179評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼议泵,長吁一口氣:“原來是場噩夢啊……” “哼占贫!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起先口,我...
    開封第一講書人閱讀 40,124評論 0 277
  • 序言:老撾萬榮一對情侶失蹤型奥,失蹤者是張志新(化名)和其女友劉穎瞳收,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體厢汹,經(jīng)...
    沈念sama閱讀 46,657評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡缎讼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,723評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了坑匠。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片血崭。...
    茶點故事閱讀 40,872評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖厘灼,靈堂內(nèi)的尸體忽然破棺而出夹纫,到底是詐尸還是另有隱情,我是刑警寧澤设凹,帶...
    沈念sama閱讀 36,533評論 5 351
  • 正文 年R本政府宣布舰讹,位于F島的核電站,受9級特大地震影響闪朱,放射性物質(zhì)發(fā)生泄漏月匣。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,213評論 3 336
  • 文/蒙蒙 一奋姿、第九天 我趴在偏房一處隱蔽的房頂上張望锄开。 院中可真熱鬧,春花似錦称诗、人聲如沸萍悴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽癣诱。三九已至,卻和暖如春袜香,著一層夾襖步出監(jiān)牢的瞬間撕予,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評論 1 274
  • 我被黑心中介騙來泰國打工蜈首, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留实抡,地道東北人。 一個月前我還...
    沈念sama閱讀 49,304評論 3 379
  • 正文 我出身青樓疾就,卻偏偏與公主長得像澜术,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子猬腰,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,876評論 2 361

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