iOS13的API的變更和適配問題,在一段時間內可能會有不一樣的問題和方式出現,因此本文會持續更新iOS13所存在的問題
修改的API
被禁止的KVC方式
關於暗黑模式和切換
在iOS13以前,UIColor指標是一種顏色。
在iOS13,UIColor擁有了動態屬性。它能夠在 LightMode 和 DarkMode 擁有不一樣的顏色。如下是iOS13最新系統提供的顏色的方法
ios
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
}
複製代碼
系統顏色的動態切換是怎麼作的,你是否很好奇,實際上是作了不一樣的狀態下設置顏色,在切換的時候就取了相應的顏色。下面來看看:web
@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
}
}
複製代碼
新增的一些顏色,那你能夠直接點進去看看。這裏舉例部分:windows
/* 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 }
...
複製代碼
在iOS13以前有兩種狀態,default
和lightContent
在iOS13 有三種狀態,default
, darkContent
和 lightContent
api
darkContent
對應以前的 default
,如今的 default 會根據狀況自動選擇 darkContent 和 lightContent
iOS13以前有三種樣式:UIActivityIndicatorViewStyleGray 灰色
UIActivityIndicatorViewStyleWhite 白色
UIActivityIndicatorViewStyleWhiteLarge 白色(大型)
xcode
iOS13廢棄了以上三種樣式,而用如下兩種樣式代替:UIActivityIndicatorViewStyleLarge (大型)
UIActivityIndicatorViewStyleMedium (中型)
bash
iOS13經過color屬性設置其顏色
微信
@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
複製代碼
如今可使用app
let window = UIApplication.shared.windows[0]
複製代碼
在 iOS 9 以前播放視頻可使用 MediaPlayer.framework 中的MPMoviePlayerController類來完成,它支持本地視頻和網絡視頻播放。可是在 iOS 9 開始被棄用,若是在 iOS 13 中繼續使用的話會直接拋出異常:ide
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'MPMoviePlayerController is no longer available. Use AVPlayerViewController in AVKit.'
複製代碼
解決辦法: Use AVPlayerViewController in AVKit
,即便用 AVPlayer 做爲視頻播放控件
在 iOS 8 以前,咱們在 UITableView
上添加搜索框須要使用 UISearchBar + UISearchDisplayController
的組合方式,
在 iOS 8 以後,蘋果就已經推出了 UISearchController
來代替這個組合方式。在 iOS 13 中,若是還繼續使用 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.'
複製代碼
Please migrate your application to UISearchController.', 也就是用UISearchController代替
在 iOS 13,使用 presentViewController 方式打開視圖,會跟導航欄有部分視覺差,這裏就不上圖了,能夠自行試一下。
緣由是:蘋果將 UIViewController
的 modalPresentationStyle
屬性的默認值改爲了新加的一個枚舉值 UIModalPresentationAutomatic,對於多數 UIViewController
,此值會映射成 UIModalPresentationPageSheet
。
解決辦法: 能夠在vcpresent以前設置modalPresentationStyle 爲 UIModalPresentationFullScreen
另外,present的vc用戶下拉能夠dissmiss
控制器,若是不想要這效果,能夠這樣設置
/*當該屬性爲 false 時,用戶下拉能夠 dismiss 控制器,爲 true 時,下拉不能夠 dismiss控制器*/
xxVC.isModalInPresentation = true
複製代碼
UIModalPresentationFullScreen
樣式彈出頁面,那麼這個頁面彈出 ViewController
會依次調viewWillDisappear
和 viewDidDisappear
。而後在這個頁面被 dismiss 的時候,將他彈出的那個 ViewController
的 viewWillAppear
和 viewDidAppear
會被依次調用。然而使用默認的視差效果彈出頁面,將他彈出的那個 ViewController
並不會調用這些方法,原先寫在這四個函數中的代碼之後都有可能會存在問題。在 iOS 13 中,蘋果將原來藍牙申請權限用的 NSBluetoothPeripheralUsageDescription 字段,替換爲 NSBluetoothAlwaysUsageDescription 字段。
For apps with a deployment target of iOS 13 and later, use NSBluetoothAlwaysUsageDescription instead.
複製代碼
@available(iOS, introduced: 2.0, deprecated: 12.0, message: "No longer supported; please adopt WKWebView.")
複製代碼
iOS13 開始蘋果將 UIWebview 列爲過時API(支持iOS2.0-iOS12)。 目前提交蘋果應用市場(App Store)會發送郵件提示你在下一次提交時將應用中UIWebView
的 api 移除。郵件內容:
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,之後更高的版本中防止出現問題,儘早移除是上上之策。
目前我所用到的最新版本微信支付sdk(1.8.6版)
,已將UIWebView
替換成了WKWebView.
這個來自別人的文章,能夠查看哪些sdk使用了UIWebView
(我沒有試過):
find . -type f | grep -e ".a" -e ".framework" | xargs grep -s UIWebView
複製代碼
在 iOS 13 中蘋果推出一種在 App 和網站上便捷登陸的方式: Sign In With Apple
,這是 iOS 13 新增的功能,所以須要使用 Xcode 11 進行開發。請在 App Store 應用審覈指南 中查看具體要求
目前個人項目中也是使用 LaunchImage
來設置啓動圖。可是在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
複製代碼
LaunchScreen.storyboard
,不然將沒法提交到 App Store 進行審批。修改辦法
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")
}
複製代碼
在iOS13以前,咱們經過"_searchField"來獲取UISearchTextField來修改一些屬性。
let searchTextField = searchBar.value(forKey: "_searchField")
複製代碼
在iOS13中,繼續這樣會崩潰,以下圖。
系統提供能夠直接獲取到的方法
//系統提供的方法
extension UISearchBar {
open var searchTextField: UISearchTextField { get }
}
複製代碼
在使用的過程當中須要判斷處理
if #available(iOS 13.0, *) {
let searchTextField = searchBar.searchTextField
} else {
let searchTextField = searchBar.value(forKey: "_searchField")
}
複製代碼
iOS13以前爲了處理搜索框的黑線問題,一般會遍歷 searchBar 的 subViews
,找到並刪除 UISearchBarBackground
,
在 iOS13 中這麼作會致使 UI 渲染失敗,而後直接崩潰,崩潰信息以下:
Terminating app due to uncaught exception'NSInternalInconsistencyException', reason: 'Missing or detached view for search bar layout'
複製代碼
for (UIView *view in _searchBar.subviews.lastObject.subviews) {
if ([view isKindOfClass:NSClassFromString(@"UISearchBarBackground")]) {
view.layer.contents = nil;
break;
}
}
複製代碼
UIView *statusBar = [[[UIApplication sharedApplication] valueForKey:@"statusBarWindow"] valueForKey:@"statusBar"];
複製代碼
UIViewController
或 UIView
的模式。只要設置了控制器爲暗黑模式,那麼它子view也會對應的修改
。可是當咱們在 window 上設置 overrideUserInterfaceStyle 的時候,就會影響 window 下全部的 controller, view,包括後續推出的 controller。
self.overrideUserInterfaceStyle = .dark // .light
複製代碼
if self.traitCollection.userInterfaceStyle == .dark {
// Dark
print("是dark模式、。。。")
} else if self.traitCollection.userInterfaceStyle == .light {
// Light
print("是light模式、。。。")
} else {
//unspecified
print("是unspecified模式、。。。")
}
複製代碼
///監聽模式的變化
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
if traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection) {
//模式發生變化會回調這裏
}
}
複製代碼
須要在xcode11上處理,以下圖
Dark
模式下圖片的地方
這樣仍是比較快捷的,例外若是切圖是有背景色的估計會有點麻煩,可能會須要從新切,具體看適配狀況。