前言:
iOS13的API的变动和适配问题,在一段时间内可能会有不同的问题和方式出现,会持续更新,如果您有好的建议和方法,欢迎加QQ群:457236811
,我们一起来探讨,完善。。。
一、目录
修改的API
被禁止的KVC方式
关于暗黑模式和切换
二、修改的API
1. UIColor
动态属性
在iOS13之前,UIColor指标是一种颜色。
在iOS13,UIColor拥有了动态属性。它可以在 LightMode 和 DarkMode 拥有不同的颜色。
以下是iOS13最新系统提供的颜色的方法
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
}
系统颜色的动态切换是怎么做的,你是否很好奇,其实是做了不同的状态下设置颜色,在切换的时候就取了相应的颜色。下面来看看:
@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之前有两种状态,default
和lightContent
在iOS13 有三种状态,default
, darkContent
和 lightContent
- 现在的
darkContent
对应之前的default
, 现在的 default 会根据情况自动选择 darkContent 和 lightContent
3. UIActivityIndicatorView
加载视图菊花
iOS13之前有三种样式:
UIActivityIndicatorViewStyleGray 灰色
UIActivityIndicatorViewStyleWhite 白色
UIActivityIndicatorViewStyleWhiteLarge 白色(大型)
iOS13废弃了以上三种样式,而用以下两种样式代替:
UIActivityIndicatorViewStyleLarge (大型)
UIActivityIndicatorViewStyleMedium (中型)
iOS13通过color属性设置其颜色
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
现在可以使用
let window = UIApplication.shared.windows[0]
5. 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.'
解决办法: Use AVPlayerViewController in AVKit
,即使用 AVPlayer 作为视频播放控件
6.使用 UISearchDisplayController
导致崩溃
在 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代替
7. 模态弹出默认样式改变
在 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
并不会调用这些方法,原先写在这四个函数中的代码以后都有可能会存在问题。
8. 蓝牙权限更新
在 iOS 13 中,苹果将原来蓝牙申请权限用的 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)。 目前提交苹果应用市场(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
10.UISegmentedControl
默认样式改变,默认样式变为 白底黑字
,如果设置修改过颜色的话,页面需要修改
11.Sign In with Apple
在 iOS 13 中苹果推出一种在 App 和网站上便捷登录的方式: Sign In With Apple
,这是 iOS 13 新增的功能,因此需要使用 Xcode 11 进行开发。请在 App Store 应用审核指南 中查看具体要求
12.LaunchImage (iOS 7.0–13.0)
目前我的项目中也是使用 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
- 从2020年4月开始,所有支持 iOS 13 的 App 必须提供
LaunchScreen.storyboard
,否则将无法提交到 App Store 进行审批。
三、 被禁止的kvc
1.UITextFiled
修改根据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中,继续这样会崩溃,如下图。
系统提供可以直接获取到的方法
//系统提供的方法
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 黑线处理导致崩溃
iOS13之前为了处理搜索框的黑线问题,通常会遍历 searchBar 的 subViews
,找到并删除 UISearchBarBackground
,
在 iOS13 中这么做会导致 UI 渲染失败,然后直接崩溃,崩溃信息如下:
Terminating app due to uncaught exception'NSInternalInconsistencyException', reason: 'Missing or detached view for search bar layout'
- 解决办法 设置 UISearchBarBackground 的 layer.contents 为 nil:
for (UIView *view in _searchBar.subviews.lastObject.subviews) {
if ([view isKindOfClass:NSClassFromString(@"UISearchBarBackground")]) {
view.layer.contents = nil;
break;
}
}
4. 设置UISearchBar 的searchTextField.attributedPlaceholder
无效问题
在 iOS13中需要把设置的代码写在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: "阿开始节点那里开始去上课技能点", attributes: attributeDict)
}
5获取状态栏视图
UIView *statusBar = [[[UIApplication sharedApplication] valueForKey:@"statusBarWindow"] valueForKey:@"statusBar"];
四、关于暗黑模式和切换
1. 暗黑模式是iOS13的一大亮点,下面来看看模式切换的设置。
- 切换 修改当前
UIViewController
或UIView
的模式。只要设置了控制器为暗黑模式,那么它子view也会对应的修改
。
即:只会影响当前的视图,不会影响前面的 controller 和后续 present 的 controller。
但是当我们在 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) {
//模式发生变化会回调这里
}
}
2. 图片简单适配
需要在xcode11上处理,如下图
选择后出现下图所示的,可以防止
Dark
模式下图片的地方
这样还是比较快捷的,例外如果切图是有背景色的估计会有点麻烦,可能会需要重新切,具体看适配情况。