iOS 13適配

9月20號iOS 13 已正式發布,第一時間更新了最新系統,網上對其用戶體驗上的新特性的描述也很多,而對于開發者來說,更需要關注的是新系統在 API 層面做了哪些改動,對我們現有的代碼產生什么影響,需要做什么樣的適配。
本文主要列舉了一些需要開發者注意的地方,不一定項目中都有涉及到相關發生變化的東西,但仍需注意。

一、 iOS 13 支持的機型

?iPhone X、iPhone XR、iPhone XS、iPhone XS Max
?iPhone 8、iPhone 8 Plus
?iPhone 7、iPhone 7 Plus
?iPhone 6s、iPhone 6s Plus
?iPhone SE
?iPod touch (第七代)

二、 適配要求

Starting April, 2020, all iOS apps submitted to the App Store will need to be built with the iOS 13 SDK or later. They must also support the all-screen design of iPhone XS Max or the 12.9-inch iPad Pro (3rd generation), or later.

根據官網的說法,2020年4月之后所有提交到 App Store 的應用必須使用 iOS 13 以上的 SDK 進行編譯,并要求屏幕尺寸支持 iPhone Xs Max 和 12.9 寸 iPad Pro。

三、具體適配清單

1、 Dark Mode

Dark Mode(暗黑模式)是蘋果在iOS13推出的新特性。使用iOS13及更高版本的系統的iOS 設備,可以使用暗黑模式。在暗黑模式下,系統會采用較暗的視圖控件。開發者在開發過程中需要對視圖控件進行相應暗模式的適配。

適配原理:
1.將同一個資源,創建出兩種模式的樣式。系統根據當前選擇的樣式,自動獲取該樣式的資源
2.每次系統更新樣式時,應用會調用當前所有存在的元素調用對應的一些重新方法,進行重繪視圖,可以在對應的方法做相應的改動

如果不打算適配 Dark Mode,可以強行關閉暗黑模式

if(@available(iOS 13.0, *)){
    [self setOverrideUserInterfaceStyle:UIUserInterfaceStyleLight];
}

不過即使設置了顏色方案,系統自帶的申請各個權限的彈窗還是會依據系統的顏色進行顯示,自己創建的提示彈窗 UIAlertController則不會。

對于暗黑模式,如果項目中重新對各個控件設置過背景色,那么即使開啟暗黑模式,也不會對控件的背景色有影響;如果未重新設置過背景色,那么APP里的控件就會根據系統的顯示模式而顯示相應的顏色,此時需要適配暗黑模式,否則有些控件顯示就會異常。

2、Sign In with Apple

在 iOS 13 中蘋果推出一種在 App 和網站上快速、便捷登錄的方式: Sign In With Apple。這是 iOS 13 新增的功能,因此需要使用 Xcode 11 進行開發。關于應用是否要求接入此登錄方式,蘋果在 App Store 應用審核指南 中提到:

Apps that exclusively use a third-party or social login service (such as Facebook Login, Google Sign-In, Sign in with Twitter, Sign In with LinkedIn, Login with Amazon, or WeChat Login) to set up or authenticate the user’s primary account with the app must also offer Sign in with Apple as an equivalent option.

如果應用使用了第三方或社交賬號登錄服務(如Facebook、Google、Twitter、LinkedIn、Amazon、微信等)來設置或驗證用戶的主賬號,就必須把 Sign In With Apple 作為同等的選項添加到應用上。

如果是下面這些類型的應用則不需要添加:
?僅僅使用公司內部賬號來注冊和登錄的應用;
?要求用戶使用現有的教育或企業賬號進行登錄的教育、企業或商務類型的應用;
?使用政府或業界支持的公民身份識別系統或電子標識對用戶進行身份驗證的應用;
?特定第三方服務的應用,用戶需要直接登錄其郵箱、社交媒體或其他第三方帳戶才能訪問其內容。

另外需要注意,關于何時要求接入 Sign In With Apple,蘋果在 News and Updates 中提到:

Starting today, new apps submitted to the App Store must follow these guidelines. Existing apps and app updates must follow them by April 2020.

現有應用和應用更新須在 2020 年 4 月前完成接入。

這部分目前還未看到有APP做這一條的適配,對于我們自己自身的APP我覺得暫時也不急于做,可以先看看其他APP具體如何做,然后參考參考,再制定具體的方案。

3、模態彈出視圖的顯示問題

一般打開新頁面會采用push的方式,某些臨時頁面會采用模態視圖present的方式,iOS13后模態出新頁面的時候會出現頁面從導航欄下開始顯示的情況,主要是因為之前對UIViewController里面的一個屬性,即modalPresentationStyle(該屬性是控制器在模態視圖時將要使用的樣式)沒有設置需要的類型。

在iOS13中modalPresentationStyle的默認改為UIModalPresentationAutomatic,而在之前默認是UIModalPresentationFullScreen。所以如果想顯示樣式和以前的保持一致,需要手動設置modalPresentationStyle為UIModalPresentationFullScreen

這個屬性不受Xcode版本的影響,只要是iOS13系統,采用present的方式打開頁面卻沒有設置modalPresentationStyle為UIModalPresentationFullScreen的話,就會有這個顯示問題

4、不允許使用KVC進行對私有屬性進行獲取或者修改

iOS13中通過KVC方式來獲取私有屬性,有Carsh風險,盡量避免使用.比如我們常用的UITextFiled和UISearchController等。盡量不要使用valueForKey、setValue: forKeyPath: 等方法獲取或設置私有屬性,雖然編譯可以通過,但是在運行時會直接崩潰。比如訪問 UISearchBar 的 _searchField:

UITextField *textField = [searchBar valueForKey:@"_searchField"];//崩潰
[textField setValue:[UIColor redColor] forKeyPath:@"_placeholderLabel.textColor"];//崩潰

5、推送的 deviceToken 獲取到的格式發生變化

系統返回deviceToken的方法是- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
由此可見,返回的是NSData類型的deviceToken。如果需要把NSData類型的deviceToken轉換成字符串類型,原本只需要用系統方法轉換,然后替換掉多余的符號即可:

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
NSString *token = [deviceToken description];
for (NSString *symbol in @[@" ", @"<", @">", @"-"]) {
    token = [token stringByReplacingOccurrencesOfString:symbol withString:@""];
}
NSLog(@"deviceToken:%@", token);
}

但在 iOS 13 中,這種方法已經失效,NSData類型的 deviceToken 轉換成的字符串變成了:

{length = 32, bytes = 0xd7f9fe34 69be14d1 fa51be22 329ac80d … 5ad13017 b8ad0736 } `

解決方案:

需要進行一次數據格式處理,獲取方式如下:

#include <arpa/inet.h>
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
if (![deviceToken isKindOfClass:[NSData class]]) return;
const unsigned *tokenBytes = [deviceToken bytes];
NSString *hexToken = [NSString stringWithFormat:@"%08x%08x%08x%08x%08x%08x%08x%08x",
                      ntohl(tokenBytes[0]), ntohl(tokenBytes[1]), ntohl(tokenBytes[2]),
                      ntohl(tokenBytes[3]), ntohl(tokenBytes[4]), ntohl(tokenBytes[5]),
                      ntohl(tokenBytes[6]), ntohl(tokenBytes[7])];
NSLog(@"deviceToken:%@", hexToken);
}

項目中用到deviceToken的場景是注冊極光推送,而極光推送注冊的API使用的是NSData類型的deviceToken,所以并不需要客戶端做類型轉換處理,目前相關的推送SDK也未有iOS13兼容的更新提示,后續是否需要升級推送SDK,還需繼續關注。

6、 iOS13以后將不再繼續支持UIWebView

UIKIT_EXTERN API_DEPRECATED("No longer supported; please adopt WKWebView.", ios(2.0, 12.0)) API_UNAVAILABLE(tvos, macos) @interface UIWebView : UIView <NSCoding, UIScrollViewDelegate>
1
在 iOS 13 后,官方將UIWebView的支持的系統范圍定格在了iOS 2.0 ~ iOS 12.0,建議開發者用WKWebView對UIWebView進行適配。目前,網上有人提到,如果開發者將包含 UIWebView api 的應用更新上傳到 App Store 審核后,其將會收到包含 ITMS-90809 信息的回復郵件,提示你在下一次提交時將應用中 UIWebView 的 api 移除。但是并不會影響當次的審核,下次再提交如果還是有UIWebView還是會繼續發郵件提醒你更換成WKWebView。

Dear Developer,
We identified one or more issues with a recent delivery for your app, "xxx". Your delivery              was successful, but you may wish to correct the following issues in your next delivery:
ITMS-90809: Deprecated API Usage - Apple will stop accepting submissions of apps that    use UIWebView APIs . See developer.apple.com/documentati… for more information.
After you’ve corrected the issues, you can use Xcode or Application Loader to upload a new binary to App Store Connect.
Best regards,
 The App Store Team

解決方案
用 WKWebView替代UIWebView,確保所有 UIWebView 的 api 都要移除,如果需要適配 iOS 7 的可以通過 openURL 的方式在 Safari 打開。

7、UISearchDisplayController被廢棄

在iOS 8 之前,在 UITableView 上添加搜索框可以采用 UISearchBar + UISearchDisplayController的組合方式,而在 iOS 8 之后,蘋果就已經推出了 UISearchController 來代替這個組合方式。在 iOS 13 中已經不支持UISearchDisplayController,如果還繼續使用 UISearchDisplayController 會直接導致崩潰,崩潰信息如下:

*** Terminating app due to uncaught exception 'NSGenericException', reason: 'UISearchDisplayController is no longer supported when linking against this version of iOS. Please migrate your application to UISearchController.'
1
解決方案

使用UISearchController替換 UISearchBar + UISearchDisplayController 的組合方案。

8、 MPMoviePlayerController 被棄用

在 iOS 9 之前播放視頻可以使用MediaPlayer.framework中的MPMoviePlayerController類來完成,它支持本地視頻和網絡視頻播放。但是在 iOS 9 開始被棄用,如果在 iOS 13 中繼續使用的話會直接拋出異常:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'MPMoviePlayerController is no longer available. Use AVPlayerViewController in AVKit.'
1
解決方案

使用AVFoundation 里的AVPlayer 作為視頻播放控件。

9、藍牙權限字段更新導致審核失敗

For apps with a deployment target of iOS 13 and later, use NSBluetoothAlwaysUsageDescription instead.
1
在 iOS 13 中,蘋果將原來藍牙申請權限用的 NSBluetoothPeripheralUsageDescription字段,替換為 NSBluetoothAlwaysUsageDescription 字段。

如果還是以舊的字段提交審核,將會收到包含 ITMS-90683 的郵件

解決方案
官方文檔提到:

For deployment targets earlier than iOS 13, add both NSBluetoothAlwaysUsageDescription and NSBluetoothPeripheralUsageDescription to your app’s Information Property List file.
1
所以只要在Info.plist 中把兩個字段都加上即可。

10、 LaunchImage 被棄用

iOS 有兩種設置啟動圖的方式,一種是LaunchImage,一種是LaunchScreen。采用LaunchImage設置啟動圖的話需要根據不同的機型設計相應尺寸的啟動圖,隨著蘋果設備屏幕尺寸越多,所需要的啟動圖就越多,這種啟動圖的設置方式就會顯得不夠智能;LaunchScreen只要一張圖片,系統會自動適配,其采用的是AutoLayout+SizeClass的方式,可以自動適配各種屏幕。

蘋果在 Modernizing Your UI for iOS 13 section 中提到 ,從2020年4月開始,所有支持 iOS 13 的 App 必須提供LaunchScreen.storyboard,否則將無法提交到 App Store 進行審核。

11、 UISegmentedControl 默認樣式改變

默認樣式變為白底黑字,如果設置修改過顏色的話,頁面需要修改。

原本設置選中顏色的tintColor 已經失效,新增了selectedSegmentTintColor 屬性用以修改選中的顏色。

12、 Xcode 11 創建的工程在低版本設備上運行黑屏

使用 Xcode 11 創建的工程,運行設備選擇 iOS 13.0 以下的設備,運行應用時會出現黑屏。這是因為 Xcode 11 默認是會創建通過UIScene管理多個 UIWindow 的應用,工程中除了AppDelegate外會多一個SceneDelegate,
SceneDelegate是為了 iPadOS 的多進程準備的,但是舊版本根本沒有UIScene。

解決方案

在 AppDelegate 的頭文件加上:
@property (strong, nonatomic) UIWindow *window;

13、 StatusBar 與之前版本不同

目前狀態欄也增加了一種模式,由之前的兩種,變成了三種, 其中default由之前的黑色內容,變成了會根據系統模式,自動選擇當前展示lightContent還是darkContent

14、 TabBar 選中文字顏色變成系統默認藍色

在iOS13系統中,跳轉到二級頁面再返回一級頁面時,TabBar的選中項的文字顏色會變成系統默認的藍色。主要是由于tincolor影響了 ,通過重新設置默認顏色即可

if (@available(iOS 13.0, *)) {
       self.tabBar.unselectedItemTintColor = THEMEBLUECOLOR;
   } else {
   // Fallback on earlier versions
   }

以上是綜合各個資料及項目中遇到的整理的iOS13適配點,從20號發布iOS13.0正式版到現在,截止目前已經推出了iOS13.1.3版本,關于iOS13的適配仍需持續關注。
————————————————
版權聲明:本文為CSDN博主「WScarlett」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/fhsahfihf/article/details/102592861

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容