技術(shù)參考:
View Controller Presentation Changes in iOS 13
1. Apple Login (2020年4月份)
2. Dark Mode
2.1 暗黑模式 狀態(tài)判斷 && 切換監(jiān)聽(tīng)
- 判斷模式狀態(tài)
if (UITraitCollection.currentTraitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) {
// 暗黑模式
}
else {
// 正常模式
}
- 監(jiān)聽(tīng)模式切換
// 注意:參數(shù)為變化前的traitCollection
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection;
// 判斷兩個(gè)UITraitCollection對(duì)象是否不同
- (BOOL)hasDifferentColorAppearanceComparedToTraitCollection:(UITraitCollection *)traitCollection;
2.2 禁用暗黑模式
-
info.plist 內(nèi)APP級(jí)別禁用暗黑模式
Key:
User Interface Style
value:Light -
widow級(jí)別的禁用暗黑模式
if (@available(iOS 13.0, *)) { [UIApplication sharedApplication].keyWindow.overrideUserInterfaceStyle = UIUserInterfaceStyleLight; } -
ViewController級(jí)別禁用暗黑模式
想全局禁用需要在 baseVC內(nèi)全局禁用
#if defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0 - (UIUserInterfaceStyle)overrideUserInterfaceStyle{ return UIUserInterfaceStyleLight; } #endif -
view級(jí)別禁用暗黑模式
view.overrideUserInterfaceStyle = UIUserInterfaceStyleLight;
2.3 適配暗黑模式顏色
參考這里 :iOS開(kāi)發(fā)如何適配暗黑模式(Dark Mode)
+ (UIColor *)colorWithDynamicProvider:(UIColor * (^)(UITraitCollection *))dynamicProvider API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchos);
- (UIColor *)initWithDynamicProvider:(UIColor * (^)(UITraitCollection *))dynamicProvider API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchos);
[UIColor colorWithDynamicProvider:^UIColor * _Nonnull(UITraitCollection * _Nonnull trait) {
if (trait.userInterfaceStyle == UIUserInterfaceStyleDark) {
return UIColorRGB(0x000000);
} else {
return UIColorRGB(0xFFFFFF);
}
}];
3. present 半屏問(wèn)題
modalPresentationStyle屬性默認(rèn)不是UIModalPresentationFullScreen了,需要根據(jù)需求手動(dòng)設(shè)置。
LXNavigationViewController *nav = [[LXNavigationViewController alloc] initWithRootViewController:loginViewController];
nav.modalPresentationStyle = UIModalPresentationFullScreen;
[self presentViewController:nav animated:YES completion:nil];
-
全局hook
presentViewController方法+ (void)hoookPresentFuc{ [UIViewController aspect_hookSelector:@selector(presentViewController:animated:completion:) withOptions:AspectPositionBefore usingBlock:^(id<AspectInfo> aspectInfo){ UIViewController *presentingVC = (UIViewController *)aspectInfo.arguments.firstObject; presentingVC.modalPresentationStyle = UIModalPresentationFullScreen; } error:NULL]; }
4. UITextField
- 支付輸入密碼有問(wèn)題
UITextField 的私有屬性 _placeholderLabel 被禁止訪問(wèn)了
-
_placeholderLabel.textColor私有屬性被禁止訪問(wèn)
[self.textField setValue:self.placeholderColor forKeyPath:@"_placeholderLabel.textColor"];
崩潰信息:
'Access to UITextField's _placeholderLabel ivar is prohibited.
This is an application bug'
- 解決方案
UITextField有個(gè)attributedPlaceholder的屬性,我們可以自定義這個(gè)富文本來(lái)達(dá)到我們需要的結(jié)果。
NSMutableAttributedString *placeholderString = [[NSMutableAttributedString alloc] initWithString:placeholder attributes:@{NSForegroundColorAttributeName : self.placeholderColor}];
_textField.attributedPlaceholder = placeholderString;
- 項(xiàng)目適配代碼
if (@available(iOS 13.0, *)) {
if (textField.attributedText.length > 0) {
color = textField.attributedText.color;
}
}else{
color = [textField valueForKeyPath:@"_placeholderLabel.textColor"];
}
iOS 13 通過(guò) KVC 方式修改私有屬性,有 Crash 風(fēng)險(xiǎn),謹(jǐn)慎使用!并不是所有KVC都會(huì)Crash,要嘗試!
5. UITextView 同上
6. navigationBar 使用UINavigation+SXFixSpace
if ([NSStringFromClass(subview.class) containsString:@"ContentView"]) {
// 結(jié)構(gòu)調(diào)整后 在這里return掉
if (@available(iOS 13.0, *)) {
if ([NSStringFromClass(subview.class) containsString:@"_UINavigationBarContentView"]) {
return;
}
}
//可修正iOS11之后的偏移
subview.layoutMargins = UIEdgeInsetsMake(0, space, 0, space);break;
}
同時(shí),下面的屬性也已經(jīng)被禁止訪問(wèn)了:
[barBgView valueForKey:@"_shadowView"];[barBgView valueForKey:@"_backgroundEffectView"];
7. statusBar
-
UIStatusBarStyleDefault枚舉值代表含義有變化typedef NS_ENUM(NSInteger, UIStatusBarStyle) { UIStatusBarStyleDefault = 0, // 根據(jù)用戶交互樣式自動(dòng)選擇狀態(tài)條樣式 UIStatusBarStyleLightContent API_AVAILABLE(ios(7.0)) = 1, // Light content, for use on dark backgrounds UIStatusBarStyleDarkContent API_AVAILABLE(ios(13.0)) = 3, // Dark content, for use on light backgrounds UIStatusBarStyleBlackTranslucent NS_ENUM_DEPRECATED_IOS(2_0, 7_0, "Use UIStatusBarStyleLightContent") = 1, UIStatusBarStyleBlackOpaque NS_ENUM_DEPRECATED_IOS(2_0, 7_0, "Use UIStatusBarStyleLightContent") = 2, } API_UNAVAILABLE(tvos); 定制狀態(tài)條的樣式 使用apple 推薦的這個(gè)系統(tǒng)方法
// ios 13.0 之后,這個(gè)方法已經(jīng)失效了
// [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];
- (UIStatusBarStyle)preferredStatusBarStyle {
if (@available(iOS 13.0, *)){
return UIStatusBarStyleDarkContent;
}
return UIStatusBarStyleDefault;
}
或者 ------>>:
UIStatusBarStyleDefault 替換為
(@available(iOS 13.0, *) ? UIStatusBarStyleDarkContent : UIStatusBarStyleDefault)
如果你還是使用的Xcode 10 為了走過(guò)編譯器這一步,可以使用預(yù)編譯命令,這么寫(xiě):
#if defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0
if (@available(iOS 13.0, *)) {
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDarkContent];
}else{
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];
}
#else
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];
#endif
8. UITabbar
- 橫線
UITabbar 層次發(fā)生改變,無(wú)法通過(guò)設(shè)置 shadowImage去掉上面的線; - 紅點(diǎn)
如果之前有通過(guò)TabBar上圖片位置來(lái)設(shè)置紅點(diǎn)位置,在iOS13上會(huì)發(fā)現(xiàn)顯示位置都在最左邊去了。遍歷UITabBarButton的subViews發(fā)現(xiàn)只有在TabBar選中狀態(tài)下才能取到UITabBarSwappableImageView,解決辦法是修改為通過(guò)UITabBarButton的位置來(lái)設(shè)置紅點(diǎn)的frame
9. UISearchBar
- UISearchBar的私有屬性
UISearchBarBackground,禁止訪問(wèn)和remove
if ([subview isKindOfClass:NSClassFromString(@"UISearchBarBackground")]) {
if (@available(iOS 13.0, *)) {
subview.backgroundColor = [UIColor lightGrayColor];
// subview.layer.contents = nil;
}else{
[subview removeFromSuperview];
}
}
10. 增加一直使用藍(lán)牙的權(quán)限申請(qǐng)
info.plist文件下
Key: NSBluetoothAlwaysUsageDescription
Value: 我們要一直使用您的藍(lán)牙,具體做什么別問(wèn)我
11. 推送 獲取deviceToken
#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);
}
12. CNCopyCurrentNetworkInfo
An app that fails to meet any of the above requirements receives the following return value:
- An app linked against iOS 12 or earlier receives a dictionary with pseudo-values. In this case, the SSID is Wi-Fi (or WLAN in the China region), and the BSSID is 00:00:00:00:00:00.
- An app linked against iOS 13 or later receives NULL.
-
iOS13 以后只有開(kāi)啟了 Access WiFi Information capability,才能獲取到 SSID 和 BSSID
13. APP 啟動(dòng)速度優(yōu)化 導(dǎo)致frame獲取失敗
App啟動(dòng)過(guò)程中,部分View可能無(wú)法實(shí)時(shí)獲取到frame。
14. WKWebView 中測(cè)量頁(yè)面內(nèi)容高度的方式變更
iOS 13以前 document.body.scrollHeight iOS 13中 document.documentElement.scrollHeight 兩者相差55 應(yīng)該是瀏覽器定義高度變了
15. fishhook 導(dǎo)致的Crash
16. MPMoviePlayerController 已經(jīng)被棄用
'MPMoviePlayerController is no longer available. Use AVPlayerViewController in AVKit.'
17. LaunchImage 即將消失
從 iOS 8 的時(shí)候,蘋(píng)果就引入了 LaunchScreen,我們可以設(shè)置 LaunchScreen來(lái)作為啟動(dòng)頁(yè)。當(dāng)然,現(xiàn)在你還可以使用LaunchImage來(lái)設(shè)置啟動(dòng)圖。不過(guò)使用LaunchImage的話,要求我們必須提供各種屏幕尺寸的啟動(dòng)圖,來(lái)適配各種設(shè)備,隨著蘋(píng)果設(shè)備尺寸越來(lái)越多,這種方式顯然不夠 Flexible。而使用 LaunchScreen的話,情況會(huì)變的很簡(jiǎn)單, LaunchScreen是支持AutoLayout+SizeClass的,所以適配各種屏幕都不在話下。
注意啦??,從2020年4月開(kāi)始,所有使? iOS13 SDK 的 App 將必須提供 LaunchScreen,LaunchImage即將退出歷史舞臺(tái)。
18. window層級(jí)變化
遍歷視圖獲取 keywindow 的方式會(huì)失效。
新增了 screenWindow 自定義視圖和 keywindow之間新增iOS 13系統(tǒng)的特有圖層。
轉(zhuǎn)自鏈接
關(guān)于iOS13更新的一些記錄
更新日期說(shuō)明
從2020年4月開(kāi)始,提交給App Store的所有iPhone和iPad應(yīng)用程序都必須使用iOS 13 SDK或更高版本構(gòu)建。他們還必須支持iPhone X S Max或12.9英寸iPad Pro(第三代)或更高版本的全屏設(shè)計(jì)。
從2020年4月開(kāi)始,所有使? iOS13 SDK 的 App 將必須提供 LaunchScreen,LaunchImage即將退出歷史舞臺(tái)。
iOS 13 相關(guān)更新
借助iOS 13 SDK,您的應(yīng)用程序可以利用黑暗模式,通過(guò)Apple登錄,與CloudKit同步的Core Data,PencilKit等優(yōu)勢(shì)。您可以使用SwiftUI更快地構(gòu)建動(dòng)態(tài)用戶界面,使用Combine編寫(xiě)現(xiàn)代事件處理代碼,并使用UIKit創(chuàng)建iPad應(yīng)用程序的Mac版本。
暗黑模式
使用iOS 13,用戶可以切換到“暗模式”以將iOS轉(zhuǎn)換為深色配色方案,將重點(diǎn)放在工作上,而控件則退到后臺(tái)。有關(guān)將“暗模式”并入您的應(yīng)用程序的信息。
適配具體詳情請(qǐng)參考官方說(shuō)明:外觀定制
SwiftUI
SwiftUI是一種現(xiàn)代方法,可為iOS,macOS,watchOS和tvOS構(gòu)建用戶界面。使用基于組合的聲明式編程,您可以比以往更快地構(gòu)建動(dòng)態(tài)接口。該框架提供了用于聲明應(yīng)用程序用戶界面的視圖,控件和布局結(jié)構(gòu)。它還提供事件處理程序,用于向您的應(yīng)用程序傳遞敲擊,手勢(shì)和其他類(lèi)型的輸入,并提供工具來(lái)管理從應(yīng)用程序模型到用戶將看到并與之交互的視圖和控件的數(shù)據(jù)流。
具體可參看官方 SwiftUI 教程
Combine框架
Combine是一個(gè)新框架,提供了聲明性的Swift API,用于隨時(shí)間推移處理值。這些值可以表示用戶界面事件,網(wǎng)絡(luò)響應(yīng),計(jì)劃的事件以及許多其他類(lèi)型的異步數(shù)據(jù)。使用合并,可以聲明發(fā)布者公開(kāi)可以更改的值,以及訂閱者從發(fā)布者那里接收這些值。組合通過(guò)集中事件處理代碼并消除麻煩的技術(shù)(例如嵌套閉包和基于約定的回調(diào)),使您的代碼更易于閱讀和維護(hù)。
詳情參看:Combine技術(shù)文檔
使用Apple登錄
使用Apple登錄可以為人們提供一種快速,安全且隱私友好的方式,供人們?cè)O(shè)置帳戶并開(kāi)始使用您的應(yīng)用程序和網(wǎng)站中的服務(wù)。
相關(guān)技術(shù)說(shuō)明,可前往官方說(shuō)明
關(guān)于使用Apple登錄場(chǎng)景官方說(shuō)明如下:
僅使用第三方或社交登錄服務(wù)(例如Facebook登錄,Google登錄,Twitter登錄,LinkedIn登錄,Amazon登錄或微信登錄)的應(yīng)用來(lái)設(shè)置或驗(yàn)證用戶的主帳戶該應(yīng)用程序還必須提供“與Apple登錄”作為等效選項(xiàng)。用戶的主要帳戶是他們與您的應(yīng)用建立的帳戶,用于識(shí)別自己,登錄并訪問(wèn)您的功能和相關(guān)服務(wù)。
如果滿足以下條件,則無(wú)需使用Apple登錄:
- 您的應(yīng)用程序?qū)iT(mén)使用公司自己的帳戶設(shè)置和登錄系統(tǒng)。
- 您的應(yīng)用是教育,企業(yè)或商業(yè)應(yīng)用,要求用戶使用現(xiàn)有的教育或企業(yè)帳戶登錄。
- 您的應(yīng)用程序使用政府或行業(yè)支持的公民身份識(shí)別系統(tǒng)或電子ID來(lái)對(duì)用戶進(jìn)行身份驗(yàn)證。
- 您的應(yīng)用是特定第三方服務(wù)的客戶端,要求用戶直接登錄其郵件,社交媒體或其他第三方帳戶才能訪問(wèn)其內(nèi)容。
更多iOS13更新說(shuō)明可參考官方What’s New in the iOS SDK
關(guān)于iOS13和13.1 API變動(dòng)的一些說(shuō)明
iOS 13 不再支持 UIApplicationExitsOnSuspend。 需要更新應(yīng)用以處理現(xiàn)代多任務(wù)處理。
不建議使用OpenAL框架,為了兼容起見(jiàn),它仍然存在。轉(zhuǎn)換為空間音頻功能:AVAudioEngine
AUGraph在AVAudioEngine已經(jīng)被棄用。
從iOS 8開(kāi)始,將 UISearchController 與 UINavigationController 一起使用需要將頂視圖控制器的 definesPresentationContext 屬性設(shè)置為 true。如果不這樣做會(huì)導(dǎo)致難以檢測(cè)和調(diào)試的細(xì)微錯(cuò)誤。從 iOS & iPadOS 13 beta 開(kāi)始,如果視圖控制器的 navigationItem 具有 non-nil 搜索控件,當(dāng)視圖控制器顯示在導(dǎo)航控制器中時(shí),UINavigationController 會(huì)自動(dòng)將該視圖控制器的 definesPresentationContext 屬性設(shè)置為 true
swiftUI :現(xiàn)在通過(guò)UIColor或建一個(gè)NSColor來(lái)創(chuàng)建color。
BindableObject被替換為Combine框架中的協(xié)議ObservableObject。
更新API比較多,這里不做過(guò)多說(shuō)明了。
更多可API更新說(shuō)明可參考官方:
iOS13 注意事項(xiàng)特別說(shuō)明:
- 使用textField一些私有KVC在xcode11上運(yùn)行會(huì)崩潰。
比如:
[_textField setValue:[UIColor redColor] forKeyPath:@"_placeholderLabel.textColor"];//崩潰
[_textField setValue:[UIFont systemFontOfSize:14] forKeyPath:@"_placeholderLabel.font"];//崩潰
在iOS13中modalPresentationStyle的默認(rèn)改為UIModalPresentationAutomatic,而在之前默認(rèn)是UIModalPresentationFullScreen。這可能會(huì)導(dǎo)致presentViewController的問(wèn)題。
獲取deviceToken適配
。iOS13的一個(gè)重要變化是"[deviceToken
description]" 會(huì)受不同運(yùn)行環(huán)境及系統(tǒng)的影響而發(fā)生變化。
這里我們可以參考友盟的deviceToken適配
- (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);
}
- 陸續(xù)有人在打包上傳到 App Store 時(shí)收到蘋(píng)果審核的反饋郵件,提到他們將會(huì)停止接收還在使用 UIWebView API 的應(yīng)用,希望開(kāi)發(fā)者在下次提交的時(shí)候處理好這個(gè)問(wèn)題.當(dāng)然目前只是個(gè)警告。
更多適配可參考:iOS13適配
Xcode 11更新簡(jiǎn)單說(shuō)明
Xcode 11包括Swift 5.1和適用于iOS 13,tvOS 13,watchOS 6和macOS Catalina 10.15的SDK。
Xcode 11支持SwiftUI開(kāi)發(fā)
Xcode 11增加了對(duì)Mac Catalyst的支持,以將iPad應(yīng)用程序引入Mac
Xcode現(xiàn)在支持創(chuàng)建和使用Swift軟件包,以及添加,刪除和管理軟件包依賴(lài)項(xiàng)。Xcode中的軟件包管理支持建立在開(kāi)源Swift Package Manager項(xiàng)目的基礎(chǔ)上。
Xcode默認(rèn)使用響應(yīng)文件將輸入文件傳遞給Swift編譯器。要關(guān)閉此行為,請(qǐng)?jiān)O(shè)置為 USE_SWIFT_RESPONSE_FILE為NO。
更多Xcode11更新可看:
Xcode 11 使用體驗(yàn)可參考: