前言:
iOS13的API的變動和適配問題,在一段時間內(nèi)可能會有不同的問題和方式出現(xiàn),會持續(xù)更新,如果您有好的建議和方法,歡迎加QQ群:457236811,我們一起來探討,完善。。。
一、目錄
修改的API被禁止的KVC方式關(guān)于暗黑模式和切換
二、修改的API
1. UIColor動態(tài)屬性
在iOS13之前,UIColor指標(biāo)是一種顏色。
在iOS13,UIColor擁有了動態(tài)屬性。它可以在 LightMode 和 DarkMode 擁有不同的顏色。
以下是iOS13最新系統(tǒng)提供的顏色的方法
extension UIColor {
@available(iOS 13.0, *)
public init(dynamicProvider: @escaping (UITraitCollection) -> UIColor)
/* Resolve any color to its most fundamental form (a non-dynamic color) for a specific trait collection.
*/
@available(iOS 13.0, *)
open func resolvedColor(with traitCollection: UITraitCollection) -> UIColor
}
系統(tǒng)顏色的動態(tài)切換是怎么做的,你是否很好奇,其實是做了不同的狀態(tài)下設(shè)置顏色,在切換的時候就取了相應(yīng)的顏色。下面來看看:
@available(iOS 12.0, *)
public enum UIUserInterfaceStyle : Int {
case unspecified
case light
case dark
}
//利用上面iOS13的 init方法
let color = UIColor{ (traitCollection) -> UIColor in
if traitCollection.userInterfaceStyle == .light {
return .orange
} else if traitCollection.userInterfaceStyle == .dark {
return .white
} else { //traitCollection.userInterfaceStyle == .unspecified
return .green
}
}
新增的一些顏色,那你可以直接點進去看看。這里舉例部分:
/* Foreground colors for static text and related elements.
*/
@available(iOS 13.0, *)
open class var label: UIColor { get }
@available(iOS 13.0, *)
open class var secondaryLabel: UIColor { get }
@available(iOS 13.0, *)
open class var tertiaryLabel: UIColor { get }
@available(iOS 13.0, *)
open class var quaternaryLabel: UIColor { get }
/* Foreground color for standard system links.
*/
@available(iOS 13.0, *)
open class var link: UIColor { get }
/* Foreground color for placeholder text in controls or text fields or text views.
*/
@available(iOS 13.0, *)
open class var placeholderText: UIColor { get }
@available(iOS 13.0, *)
open class var separator: UIColor { get }
@available(iOS 13.0, *)
open class var opaqueSeparator: UIColor { get }
...
2. Status Bar更新
在iOS13之前有兩種狀態(tài),default 和lightContent
在iOS13 有三種狀態(tài),default, darkContent 和 lightContent
- 現(xiàn)在的
darkContent對應(yīng)之前的default, 現(xiàn)在的 default 會根據(jù)情況自動選擇 darkContent 和 lightContent
3. UIActivityIndicatorView加載視圖菊花
iOS13之前有三種樣式:
UIActivityIndicatorViewStyleGray 灰色
UIActivityIndicatorViewStyleWhite 白色
UIActivityIndicatorViewStyleWhiteLarge 白色(大型)iOS13廢棄了以上三種樣式,而用以下兩種樣式代替:
UIActivityIndicatorViewStyleLarge (大型)
UIActivityIndicatorViewStyleMedium (中型)iOS13通過color屬性設(shè)置其顏色
4. 獲取Window用keyWindow
@available(iOS, introduced: 2.0, deprecated: 13.0, message: "Should not be used for applications that support multiple scenes as it returns a key window across all connected scenes")
open var keyWindow: UIWindow? { get }
open var windows: [UIWindow] { get }
iOS13之前
let window = UIApplication.shared.keyWindow
現(xiàn)在可以使用
let window = UIApplication.shared.windows[0]
5. MPMoviePlayerController 被棄用
在 iOS 9 之前播放視頻可以使用 MediaPlayer.framework 中的MPMoviePlayerController類來完成,它支持本地視頻和網(wǎng)絡(luò)視頻播放。但是在 iOS 9 開始被棄用,如果在 iOS 13 中繼續(xù)使用的話會直接拋出異常:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'MPMoviePlayerController is no longer available. Use AVPlayerViewController in AVKit.'
解決辦法: Use AVPlayerViewController in AVKit,即使用 AVPlayer 作為視頻播放控件
6.使用 UISearchDisplayController 導(dǎo)致崩潰
在 iOS 8 之前,我們在 UITableView 上添加搜索框需要使用 UISearchBar + UISearchDisplayController 的組合方式,
在 iOS 8 之后,蘋果就已經(jīng)推出了 UISearchController 來代替這個組合方式。在 iOS 13 中,如果還繼續(xù)使用 UISearchDisplayController會直接導(dǎo)致崩潰,崩潰信息如下:
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.'
- 解決辦法:
Please migrate your application to UISearchController.', 也就是用UISearchController代替
7. 模態(tài)彈出默認(rèn)樣式改變
在 iOS 13,使用 presentViewController 方式打開視圖,會跟導(dǎo)航欄有部分視覺差,這里就不上圖了,可以自行試一下。
原因是:蘋果將 UIViewController 的 modalPresentationStyle 屬性的默認(rèn)值改成了新加的一個枚舉值 UIModalPresentationAutomatic,對于多數(shù) UIViewController,此值會映射成 UIModalPresentationPageSheet。
解決辦法: 可以在vcpresent之前設(shè)置
modalPresentationStyle 為 UIModalPresentationFullScreen另外,present的vc用戶下拉可以
dissmiss控制器,如果不想要這效果,可以這樣設(shè)置
/*當(dāng)該屬性為 false 時,用戶下拉可以 dismiss 控制器,為 true 時,下拉不可以 dismiss控制器*/
swift代碼:
xxVC.isModalInPresentation = true
OC代碼
xxVC..modalInPresentation = YES;
- 還有一點需要注意,原來以
UIModalPresentationFullScreen樣式彈出頁面,那么這個頁面彈出ViewController會依次調(diào)viewWillDisappear和viewDidDisappear。然后在這個頁面被 dismiss 的時候,將他彈出的那個ViewController的viewWillAppear和viewDidAppear會被依次調(diào)用。然而使用默認(rèn)的視差效果彈出頁面,將他彈出的那個ViewController并不會調(diào)用這些方法,原先寫在這四個函數(shù)中的代碼以后都有可能會存在問題。
8. 藍牙權(quán)限更新
在 iOS 13 中,蘋果將原來藍牙申請權(quán)限用的 NSBluetoothPeripheralUsageDescription 字段,替換為 NSBluetoothAlwaysUsageDescription 字段。
For apps with a deployment target of iOS 13 and later, use NSBluetoothAlwaysUsageDescription instead.
9.廢棄UIWebview 改用 WKWebView
@available(iOS, introduced: 2.0, deprecated: 12.0, message: "No longer supported; please adopt WKWebView.")
iOS13 開始蘋果將 UIWebview 列為過期API(支持iOS2.0-iOS12)。 目前提交蘋果應(yīng)用市場(App Store)會發(fā)送郵件提示你在下一次提交時將應(yīng)用中UIWebView 的 api 移除。郵件內(nèi)容:
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…]([https://developer.apple.com/documentation/uikit/uiwebview](https://developer.apple.com/documentation/uikit/uiwebview)
) 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,但是在iOS13開始UIWebView已是廢棄的API,以后更高的版本中防止出現(xiàn)問題,盡早移除是上上之策。目前我所用到的最新版本
微信支付sdk(1.8.6版),已將UIWebView替換成了WKWebView.這個來自別人的文章,可以查看哪些sdk使用了
UIWebView(我沒有試過):
find . -type f | grep -e ".a" -e ".framework" | xargs grep -s UIWebView
10.UISegmentedControl 默認(rèn)樣式改變,默認(rèn)樣式變?yōu)?白底黑字,如果設(shè)置修改過顏色的話,頁面需要修改
11.Sign In with Apple
在 iOS 13 中蘋果推出一種在 App 和網(wǎng)站上便捷登錄的方式: Sign In With Apple,這是 iOS 13 新增的功能,因此需要使用 Xcode 11 進行開發(fā)。請在 App Store 應(yīng)用審核指南 中查看具體要求
12.LaunchImage (iOS 7.0–13.0)
目前我的項目中也是使用 LaunchImage來設(shè)置啟動圖。但是在iOS13開始蘋果建議使用 Launch Screen.
UILaunchImages has been deprecated; use Xcode launch storyboards instead. For more information on how to construct and format your launch storyboard, seeLaunch Screen
- 從2020年4月開始,所有支持 iOS 13 的 App 必須提供
LaunchScreen.storyboard,否則將無法提交到 App Store 進行審批。
13. Xcode 11下獲取App名稱CFBundleDisplayName返回nil
解決辦法: 在info.plist里面添加 Bundle display name

14 網(wǎng)友補充:
2020年4月26@S型身材的豬
1、添加在keywindow上的視圖,會被present出來的頁面遮蓋,之前不會遮蓋
2、發(fā)送郵件的時候,發(fā)送成功之前會有“咻”地一聲,iOS13之后去除了這個聲音
2020.12.26 17:29@阿茲爾
'scanHexInt32' was deprecated in iOS 13.0
三、 被禁止的kvc
1.UITextFiled 修改根據(jù)kvc提示文字的大小和顏色,在iOS13會直接崩潰,報錯信息如下

修改辦法
if #available(iOS 13.0, *) {
let arrStr = NSMutableAttributedString(string: field.placeholder!, attributes: [NSAttributedString.Key.foregroundColor: UIColor.systemGray3, NSAttributedString.Key.font: UIFont.systemFont(ofSize: 15)])
field.attributedPlaceholder = arrStr
} else {
field.setValue(UIColor.systemGray3, forKeyPath: "_placeholderLabel.textColor")
field.setValue(UIFont.systemFont(ofSize: 15), forKeyPath:"_placeholderLabel.font")
}
2. 獲取UISearchBar的textField
在iOS13之前,我們通過"_searchField"來獲取UISearchTextField來修改一些屬性。
let searchTextField = searchBar.value(forKey: "_searchField")
在iOS13中,繼續(xù)這樣會崩潰,如下圖。

系統(tǒng)提供可以直接獲取到的方法
//系統(tǒng)提供的方法
extension UISearchBar {
open var searchTextField: UISearchTextField { get }
}
在使用的過程中需要判斷處理
if #available(iOS 13.0, *) {
let searchTextField = searchBar.searchTextField
} else {
let searchTextField = searchBar.value(forKey: "_searchField")
}
3.UISearchBar 黑線處理導(dǎo)致崩潰
iOS13之前為了處理搜索框的黑線問題,通常會遍歷 searchBar 的 subViews,找到并刪除 UISearchBarBackground,
在 iOS13 中這么做會導(dǎo)致 UI 渲染失敗,然后直接崩潰,崩潰信息如下:
Terminating app due to uncaught exception'NSInternalInconsistencyException', reason: 'Missing or detached view for search bar layout'
- 解決辦法 設(shè)置 UISearchBarBackground 的 layer.contents 為 nil:
for (UIView *view in _searchBar.subviews.lastObject.subviews) {
if ([view isKindOfClass:NSClassFromString(@"UISearchBarBackground")]) {
view.layer.contents = nil;
break;
}
}
4. 設(shè)置UISearchBar 的searchTextField.attributedPlaceholder無效問題
在 iOS13中需要把設(shè)置的代碼寫在viewDidAppear,親測可以
var lglSearchBar: UISearchBar!
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let attributeDict = [NSAttributedString.Key.foregroundColor: UIColor.green, NSAttributedString.Key.font: UIFont.systemFont(ofSize: 20)]
lglSearchBar.searchTextField.attributedPlaceholder = NSMutableAttributedString(string: "阿開始節(jié)點那里開始去上課技能點", attributes: attributeDict)
}
5獲取狀態(tài)欄視圖
UIView *statusBar = [[[UIApplication sharedApplication] valueForKey:@"statusBarWindow"] valueForKey:@"statusBar"];
四、關(guān)于暗黑模式和切換
1. 暗黑模式是iOS13的一大亮點,下面來看看模式切換的設(shè)置。
- 切換 修改當(dāng)前
UIViewController或UIView的模式。只要設(shè)置了控制器為暗黑模式,那么它子view也會對應(yīng)的修改。
即:只會影響當(dāng)前的視圖,不會影響前面的 controller 和后續(xù) present 的 controller。
但是當(dāng)我們在 window 上設(shè)置 overrideUserInterfaceStyle 的時候,就會影響 window 下所有的 controller, view,包括后續(xù)推出的 controller。
self.overrideUserInterfaceStyle = .dark // .light
- 獲取當(dāng)前的模式
if self.traitCollection.userInterfaceStyle == .dark {
// Dark
print("是dark模式、。。。")
} else if self.traitCollection.userInterfaceStyle == .light {
// Light
print("是light模式、。。。")
} else {
//unspecified
print("是unspecified模式、。。。")
}
- 監(jiān)聽模式的變化
///監(jiān)聽模式的變化
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
if traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection) {
//模式發(fā)生變化會回調(diào)這里
}
}
2. 圖片簡單適配
需要在xcode11上處理,如下圖

選擇后出現(xiàn)下圖所示的,可以防止
Dark模式下圖片的地方
這樣還是比較快捷的,例外如果切圖是有背景色的估計會有點麻煩,可能會需要重新切,具體看適配情況。