1景描、前言
針對(duì) iOS 13堰乔,蘋果做了非常大的調(diào)整万哪,其中 Dark 模式是最新的 UI 層面可見的改變侠驯,而針對(duì)iPad推出了 iPadOS
,導(dǎo)致了與 iOS 的分化奕巍,同時(shí)為了 iPad 而不得不對(duì) iOS 同樣做出的改變吟策,比如一個(gè)應(yīng)用支持多 window 顯示。所以的止,每年 WWDC 后檩坚,因?yàn)槊總€(gè)應(yīng)用的情況不一樣,使用的API各不相同诅福,導(dǎo)致適配的工作無法一致匾委,大家遇到的坑不相同,所以氓润,把大家遇到的問題都匯總起來赂乐,那就是一定有作用,這就是本文的初心咖气。
2挨措、iOS 13 適配問題
1. 如何關(guān)閉程序中的暗黑模式?
iOS13最大的特點(diǎn)是帶來了暗黑模式崩溪,但是如果不適配的話浅役,可能會(huì)出現(xiàn)該是黑色的地方用了白色了,該是白色的地方是黑色了伶唯,看不到了觉既,怎么關(guān)掉呢?
- 1.1 代碼方式:
可以每一個(gè)頁面設(shè)置乳幸,當(dāng)然也可以整體設(shè)置奋救,一般我們的APP都是在一個(gè)window下的,那就整體設(shè)置APP里的window:
#if defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0
if(@available(iOS 13.0,*)){
self.window.overrideUserInterfaceStyle = UIUserInterfaceStyleLight;
}
#endif
- 1.2 配置文件方式:
在Info.plist
添加key:UIUserInterfaceStyle
設(shè)置為強(qiáng)制用暗黑模式(Dark
)或白天模式(Light
)
[...(image-a5b691-1579270138616)]
<key>UIUserInterfaceStyle</key>
<string>UIUserInterfaceStyleLight</string>
目前蘋果還沒有公布什么時(shí)候強(qiáng)制適配黑夜模式反惕。按之前的官方的文章其實(shí)是沒有強(qiáng)制要求所有App都適配尝艘,因?yàn)橛行〢pp確實(shí)可能很難適配。
如果您需要更多時(shí)間調(diào)節(jié) app 在深色模式中的外觀姿染,或您的 app 不適用于深色模式背亥,您可進(jìn)一步了解如何停用深色模式秒际。
2. UIWebView 已棄用
ITMS-90809: Deprecated API Usage - Apple will stop accepting submissions of apps that use UIWebView APIs . See https://developer.apple.com/documentation/uikit/uiwebview for more information.
UIWebView
iOS 2.0–12.0 Deprecated
Mac Catalyst 13.0–13.0 Deprecated
2019-12月更新
The App Store will no longer accept new apps using UIWebView as of April 2020 and app updates using UIWebView as of December 2020.
蘋果已經(jīng)強(qiáng)制要求2020年4月新應(yīng)用不能再使用 UIWebView,2020年12月所有應(yīng)用更新不能在使用 UIWebView狡汉。
3. PresentViewController 模式變動(dòng)
iOS13后娄徊,Prensent方式彈出頁面時(shí),默認(rèn)的模式變?yōu)榱薝IModalPresentationAutomatic盾戴,這樣的方式也挺好的寄锐,動(dòng)畫也好看,自帶關(guān)閉尖啡,只要下拉就關(guān)閉頁面了橄仆,這樣的動(dòng)畫方式下,之前會(huì)出現(xiàn)的《UITabBar在iPhoneX等Push時(shí)顯示錯(cuò)亂問題》 的問題也不存在了衅斩。
但有的時(shí)候盆顾,我們不希望使用這個(gè)樣式,比如需要用戶不能關(guān)閉的:
[圖片上傳失敗...(image-bc3086-1579270138616)]
只要指定彈出頁的 modalPresentationStyle
屬性畏梆,注意是要Present的頁面:
UIViewController *vc = [[UIViewController alloc] init];
vc.modalPresentationStyle = UIModalPresentationFullScreen;
[self.navigationController presentViewController:vc animated:YES completion:nil];
4. 增加"一直使用藍(lán)牙"的權(quán)限申請(qǐng)
iOS 13起您宪,app的 info.plist里增加
<key>NSBluetoothAlwaysUsageDescription</key>
<string>我們要一直使用您的藍(lán)牙,具體做什么別問我</string>
5. WKWebView 中測量頁面內(nèi)容高度的方式變更
iOS 13以前
document.body.scrollHeight
iOS 13中
document.documentElement.scrollHeight
兩者相差55 應(yīng)該是瀏覽器定義高度變了
6. UIActivityIndicatorView
之前的 UIActivityIndicatorView 有三種 style 分別為 whiteLarge
, white
和 gray
奠涌,現(xiàn)在全部廢棄宪巨。
增加兩種 style 分別為 medium
和 large
,指示器顏色用 color
屬性修改溜畅。
[圖片上傳失敗...(image-674006-1579270138616)]
7. Status Bar
去掉原來 .default
.lightContent
揖铜,改為 :
[圖片上傳失敗...(image-c71bd1-1579270138616)]
8. Sign In with Apple
Sign In with Apple will be available for beta testing this summer. It will be required as an option for users in apps that support third-party sign-in when it is commercially available later this year.
Apple登錄將于今年夏天進(jìn)行beta測試。對(duì)于支持第三方用戶登錄的應(yīng)用中达皿,apple 登錄將在今年晚些時(shí)候上市銷售時(shí)作為選項(xiàng)。
通過API來獲取到諸如用戶姓名這樣的信息贿肩,但是最為關(guān)鍵的userIdentifier
則是毫無規(guī)律可言的(至少在我們開發(fā)者看來)峦椰,而這個(gè)userIdentifier
則為同一個(gè)開發(fā)者賬號(hào)下的所有app中保持有且僅有一個(gè)。
另外汰规,apple 登錄是支持跨平臺(tái)汤功,安卓和 windows 的 web 頁面中使用 apple id 登錄授權(quán)。
注意:
Sign In with Apple 需要用戶開啟了兩步認(rèn)證溜哮,如果沒有開啟則會(huì)在第一次使用時(shí)提示開啟滔金,不開啟將無法使用。
另外茂嗓,蘋果登錄按鈕有所要求, 詳細(xì)見 Sign In with Apple - Sign In with Apple - Human Interface Guidelines - Apple Developer
2019年9月更新
4.8 通過 Apple 登錄
如果 app 專門使用第三方或社交登錄服務(wù) (例如餐茵,F(xiàn)acebook 登錄、Google 登錄述吸、通過 Twitter 登錄忿族、通過 LinkedIn 登錄、通過 Amazon 登錄或微信登錄) 來對(duì)其進(jìn)行設(shè)置或驗(yàn)證這個(gè) app 的用戶主帳戶,則該 app 必須同時(shí)提供“通過 Apple 登錄”作為等效選項(xiàng)道批。用戶的主帳戶是指在 app 中建立的错英、用于標(biāo)識(shí)身份、登錄和訪問功能和相關(guān)服務(wù)的帳戶隆豹。
在以下情況下椭岩,不要求提供“通過 Apple 登錄”選項(xiàng):
- 您的 app 僅使用公司自有的帳戶設(shè)置和登錄系統(tǒng)。
- 您的 app 是一款教育璃赡、企業(yè)或商務(wù) app判哥,要求用戶使用現(xiàn)有的教育或企業(yè)帳戶登錄。
- 您的 app 使用政府或行業(yè)支持的公民身份系統(tǒng)或電子身份證來鑒定用戶身份鉴吹。
- 您的 app 是特定第三方服務(wù)的客戶端姨伟,用戶需要使用他們的郵件、社交媒體或其他第三方帳戶直接登錄才能訪問內(nèi)容豆励。
9. KVC 限制
iOS 13 通過 KVC 方式修改私有屬性夺荒,有 Crush 風(fēng)險(xiǎn),謹(jǐn)慎使用良蒸!
iOS13 以后已經(jīng)不能肆無忌憚的通過 KVC 來修改一些沒有暴露出來的屬性了技扼。會(huì)崩潰:
'Access to UITextField's _placeholderLabel ivar is prohibited. This is an application bug'
已知:
// UITextField的placeholder的顏色
[textField setValue:[UIColor xxx] forKeyPath:@"_placeholderLabel.textColor"];
// UISearchBar 的 _searchField
[searchBar valueForKey:@"_searchField"];
修改如下:
NSMutableAttributedString *placeholderString = [[NSMutableAttributedString alloc] initWithString:placeholder attributes:@{NSForegroundColorAttributeName : self.placeholderColor}];
_textField.attributedPlaceholder = placeholderString;
10. UISegmentedControl 默認(rèn)樣式改變
默認(rèn)樣式變?yōu)榘椎缀谧郑绻O(shè)置修改過顏色的話嫩痰,頁面需要修改剿吻。另外UI樣式發(fā)生了變化。
11. App啟動(dòng)過程中串纺,部分View可能無法實(shí)時(shí)獲取到frame
可能是為了優(yōu)化啟動(dòng)速度(或者留海屏原因)丽旅,App 啟動(dòng)過程中,部分View可能無法實(shí)時(shí)獲取到正確的frame
// 只有等執(zhí)行完 UIViewController 的 viewDidAppear 方法以后纺棺,才能獲取到正確的值榄笙,在viewDidLoad等地方 frame Size 為 0,例如:
[[UIApplication sharedApplication] statusBarFrame];
12. MPMoviePlayerController 在iOS 13 棄用
在使用到MPMoviePlayerController的地方祷蝌,直接拋了異常:
'MPMoviePlayerController is no longer available. Use AVPlayerViewController in AVKit.'
替代方案就是AVKit里面的那套播放器
13. iOS 13 DeviceToken有變化
這個(gè)很重要C┳病!巨朦!
可能大多數(shù)使用第三方推送的童鞋都不會(huì)注意到這個(gè)問題米丘,一般現(xiàn)在的第三方推送都是將DeviceToken原始數(shù)據(jù)丟進(jìn)去,具體的解析都是第三方內(nèi)部處理糊啡,所以拄查,這些第三方解析DeviceToken的方式正確的話,那就毫無問題棚蓄。如果你們是通過這種方式來獲取DeviceToken靶累,那你需要注意了腺毫。(這個(gè)坑也是多年前埋下的,很多文章介紹的也是下面這個(gè)方法挣柬,不規(guī)范的做法遲早要還的)潮酒,如下:
NSString *dt = [deviceToken description];
dt = [dt stringByReplacingOccurrencesOfString: @"<" withString: @""];
dt = [dt stringByReplacingOccurrencesOfString: @">" withString: @""];
dt = [dt stringByReplacingOccurrencesOfString: @" " withString: @""];
這段代碼運(yùn)行在 iOS 13 上已經(jīng)無法獲取到準(zhǔn)確的DeviceToken字符串了,iOS 13 通過[deviceToken description]獲取到的內(nèi)容已經(jīng)變了邪蛔。
{length = 32, bytes = 0x778a7995 29f32fb6 74ba8167 b6bddb4e ... b4d6b95f 65ac4587 }
解決方法急黎,fb sdk 中:
+ (NSString *)hexadecimalStringFromData:(NSData *)data
{
NSUInteger dataLength = data.length;
if (dataLength == 0) {
return nil;
}
const unsigned char *dataBuffer = data.bytes;
NSMutableString *hexString = [NSMutableString stringWithCapacity:(dataLength * 2)];
for (int i = 0; i < dataLength; ++i) {
[hexString appendFormat:@"%02x", dataBuffer[i]];
}
return [hexString copy];
}
友盟推送的解決方法
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
if (![deviceToken isKindOfClass:[NSData class]]) return;
const unsigned *tokenBytes = (const unsigned *)[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);
}
}
這2個(gè)方法那個(gè)好?
根據(jù)蘋果文檔 application:didRegisterForRemoteNotificationsWithDeviceToken::
友盟的兼容方案并不嚴(yán)謹(jǐn)侧到,蘋果說tokens長度可變勃教,建議不要硬編碼!匠抗!
更多參考:
iOS13 PKPushCredentials broken |Apple Developer Forums
facebook-objc-sdk/FBSDKInternalUtility.m
【公告】iOS 13正式發(fā)布后對(duì)U-Push的影響
NotificationCenter · Issue #23 · ChenYilong/iOS13AdaptationTips
14. 即將廢棄的 LaunchImage
從 iOS 8 的時(shí)候故源,蘋果就引入了 LaunchScreen,我們可以設(shè)置 LaunchScreen來作為啟動(dòng)頁汞贸。當(dāng)然绳军,現(xiàn)在你還可以使用LaunchImage來設(shè)置啟動(dòng)圖。不過使用LaunchImage的話矢腻,要求我們必須提供各種屏幕尺寸的啟動(dòng)圖门驾,來適配各種設(shè)備,隨著蘋果設(shè)備尺寸越來越多多柑,這種方式顯然不夠 Flexible奶是。而使用 LaunchScreen的話,情況會(huì)變的很簡單竣灌, LaunchScreen是支持AutoLayout+SizeClass的聂沙,所以適配各種屏幕都不在話下。
注意: 從2020年4月開始初嘹,所有使? iOS13 SDK 的 App 將必須提供 LaunchScreen及汉,LaunchImage即將退出歷史舞臺(tái)。
再補(bǔ)充一點(diǎn)削樊,在使用 LaunchScreen的時(shí)候,里面用到的圖片資源兔毒,最好別放在 xcassets 里面漫贞,不然在你修改圖片后,你會(huì)發(fā)現(xiàn)真機(jī)上并不會(huì)生效育叁。
15. App Delegate
iOS 支持多界面同時(shí)運(yùn)行多個(gè)用戶界面迅脐。 root view controller 的 view superview 也不直接是 UIWindow 了:
[圖片上傳失敗...(image-50d6ff-1579270138616)]
iOS 13 可以多windows窗口,把ui相關(guān)的生命周期單獨(dú)到 SceneDelegate:
[圖片上傳失敗...(image-979c17-1579270138616)]
如果實(shí)現(xiàn) SceneDelegate 那么iOS 13會(huì)調(diào)整 SceneDalegate豪嗽, 如果不實(shí)現(xiàn)谴蔑,就會(huì)使用 AppDelegate豌骏。iOS 12 以下還是調(diào)用 AppDelegate:
[圖片上傳失敗...(image-579a22-1579270138616)]
@property(nullable, nonatomic,readonly) UIWindow *keyWindow API_DEPRECATED("Should not be used for applications that support multiple scenes as it returns a key window across all connected scenes", ios(2.0, 13.0));
獲取keyWindow 使用 [UIApplicatoin sharedApplication].keyWindow 情況就有多種:
- 1、此接口已經(jīng)棄用
- 2隐锭、針對(duì) iPad, 一個(gè)應(yīng)用可以打開多窗口(比如 office 可以打開多個(gè) word 文檔窃躲。),此時(shí)钦睡,keyWindow 就有多個(gè) scenes蒂窒,并不唯一。
- 3荞怒、針對(duì) iPhone洒琢,目前還不能同時(shí)打開多窗口。所以 keyWindow 還是唯一的褐桌,暫時(shí)不影響獲取衰抑。
沒有了 keyWindow,那以后怎么獲得當(dāng)前激活中的 window 呢荧嵌?可以看看這里:How to resolve: 'keyWindow' was deprecated in iOS 13.0
具體調(diào)整可參見官方WWDC: Architecting Your App for Multiple Windows - WWDC 2019 - Videos - Apple Developer
16. - (BOOL)application: openURL: options: 中 SourceApplication 為 nil
在 Xcode 11之前的文檔:
// value is an NSString containing the bundle ID of the originating application
在 Xcode 11后變?yōu)椋?/p>
// value is an NSString containing the bundle ID of the originating application; non-nil if the originating application and this application share the same team identifier
官方在線文檔:
UIApplicationOpenURLOptionsSourceApplicationKey
A key that contains the bundle ID of the app that sent the open-URL request to your app.The value of this key is an NSString object containing the bundle ID of the app that made the request. If the request originated from another app belonging to your team, UIKit sets the value of this key to the ID of that app. If the team identifier of the originating app is different than the team identifier of the current app, the value of the key is nil.
在 iOS 13 中呛踊,非同一開發(fā)者賬號(hào)(team identifier)的App完丽,在 iOS 13 通過 URL Scheme
打開App里恋技,在代理方法 - (BOOL)application: openURL: options:
中將UIApplicationOpenURLOptionsSourceApplicationKey
返回為nil
逻族,也就是說薄辅,再也拿不到原App的 bundle ID,關(guān)于這個(gè)大家都說是蘋果為了解決隱私問題抠璃?
對(duì)于開發(fā)者來說站楚,如果有使用到 SourceApplication 字段,只能在 iOS 13以上調(diào)整自己的業(yè)務(wù)邏輯搏嗡。
- iOS 13 beta 2, openURL, with SourceApplication ... |Apple Developer Forums
- iOS13 UIApplicationOpenURLOptionsSourceApplicat... |Apple Developer Forums
- UIApplicationOpenURLOptionsSourceApplicationKey - UIKit | Apple Developer Documentation
總結(jié)
這些都只是常見和匯總網(wǎng)上大家遇到的情況窿春,還有很多細(xì)節(jié)上,針對(duì) iOS13 需要大家細(xì)調(diào)采盒,這些年下來旧乞,iOS各系統(tǒng)版本之前的突變很多,當(dāng)然這樣也有好處磅氨,比如 WKWebview 支持 iOS 8.0 + , SFSafariViewController 支持 iOS 9.0+尺栖,慢慢地,很多更好的 API 大家都可以使用烦租,拋棄舊的接口延赌,兼容新的接口除盏,這樣的工作,可預(yù)見未來一直會(huì)這樣挫以,誰叫我們是 API 使用者者蠕!努力成為提供 API man 吧!
參考
- iOS13 開發(fā)適配 - 簡書
- WWDC2019 ---webview iOS13適配
- iOS13 Sign In With Apple適配 – 小瑞的Blog
- 適配 iOS13 | Feng's Notes
- iOS 13 適配 - 簡書
- ChenYilong/iOS13AdaptationTips: iOS13 AdaptationTips
- Architecting Your App for Multiple Windows - WWDC 2019 - Videos - Apple Developer
- Implementing Dark Mode on iOS - WWDC 2019 - Videos - Apple Developer
- How to resolve: 'keyWindow' was deprecated in iOS 13.0
- Usage Guidelines for Website and Other Platforms - Sign in with Apple - Apple Developer
- App Store 審核指南 - Apple Developer
- 有關(guān)“通過 Apple 登錄”的指南更新 - 新聞 - Apple Developer
- Updating Apps that Use Web Views - News - Apple Developer
- 為深色模式做好準(zhǔn)備 - 新聞 - Apple Developer
- iOS 13 beta 2, openURL, with SourceApplication ... |Apple Developer Forums
- iOS13 UIApplicationOpenURLOptionsSourceApplicat... |Apple Developer Forums
- UIApplicationOpenURLOptionsSourceApplicationKey - UIKit | Apple Developer Documentation
- 如有不正確的地方屡贺,歡迎指導(dǎo)蠢棱!
- 如有疑問,歡迎在評(píng)論區(qū)一起討論甩栈!
注:本文首發(fā)于 iHTCboy's blog泻仙,如若轉(zhuǎn)載,請(qǐng)注來源