适配 iOS 13
前言
目前 iOS 可下载的最新正式版是 13.3,早在今年 6 月份向公众推出 iOS 13 的开发者预览版,在 9 月份发布 iOS 13.0 版本后,苹果又接连推出了 13.1 / 13.1.1 / 13.1.2 ,iOS 13.2 还因为频繁杀后台被用户吐槽新版本 Bug 太多。目前市场上主流的 iPhone 机型(包括iPhone 6s、6s Plus、7、7Plus、8、8Plus、SE、X 、XS 、XS Max、XR、iPod touch 7代等)都兼容升级 iOS13 版本,但值得注意的是已不再支持 A7 或 A8 处理器的机型,仅限于 A9 处理器。
Apple 在 10 月份推送了 iOS13 公开版后,iOS 用户更新应用版本如果应用没有做适配会导致 Crash 、兼容适配等问题,这里记录一下当时适配过程遇到的一些问题以及移动开发的一些收获,由于对 iOS 开发、Swift 等并不是很熟悉,如内容有误,请及时斧正。
功能更新
在适配前应该先了解一下具体都做了哪些更新,先来看下这次的 iOS 13 带来了的功能上的更新,有一些功能我也是比较期待的,这里归纳总结一下:
视觉上的提升 - Dark mode
- 毫无疑问 iOS 13最受关注的功能点就是这个“能让你更方便熬夜”的暗黑模式,用户可以在设置-显示与亮度中更改深色模式设置,也可以在“选项”中根据日出与日落时间切换模式,或者自定义深色模式的时间段,这个版本系统还提供有针对黑夜模式的新壁纸。
控制中心优化及增强可操作性
- 允许从控制中心直接操作 WiFi 蓝牙,长按 WiFi 、蓝牙等选项会弹出当前可用的网络、蓝牙设备列表;
- 蜂窝煤提供低数据连接模式;
- 更新音量调节 UI,禁音操作后,会在顶部弹出一个静音模式的通知;操作侧边栏音量键后,会在按键侧出现显示音量大小的条形图,还可以用手指触摸条以通过滑动来调整声音;
增强 Safari
- 在 Safari 中截屏的的时候多了一个屏幕选项,可以实现长截图了,甚至可以调整、编辑图片;
- 允许直接将网页保存为PDF;
性能上的提升
- 据 PPT 介绍 Face ID 解锁速度提升 30%,App Store 的应用程序提供新的压缩模式,使得 App 下载的体积减少 50% 左右,这意味着更快的应用更新速度,App 开启速度提升2倍。(具体数据这里没有实际测试);
照片和相机改进
- 相机功能优化,包括照片根据 AI 自动归类,照片标签会自动按照天、月以及年的时间进行分类;
Sign In With Apple
- 目前国内很多 app 都有做第三方登陆,例如微信、微博、github 登陆等,苹果也来抢饭碗,推出了自己的第三方登陆功能:Sign In With Apple,可以通过已有的 Apple ID 来快速登录其它 app 和网站,App 和网站只能索取你的姓名和电邮地址,在 WWDC大会 演示中看到苹果甚至还可以隐藏真实的邮箱地址,让第三方产品难以追踪该账号的数据。
这里没有全面列举这次功能上的更新,具体可以网上查看 iOS 的更新列表。
API 层变动
KVC
私有 KVC 在 iOS 开发中可以说是一个黑魔法,因为 KVC 可以访问和修改私有变量,经常会用于动态取值和设值。在 iOS 13 中苹果已不再允许这样使用。原项目代码中存在比较多这样使用的代码,例如 UISearchBar 通过 forKey 获取 searchField 然后修改 backgroundColor ,在新版本系统中会直接导致应用崩溃,或者 valueForKey、setValue:forKey 等方法获取修改属性均会报错。
例如:
[_textField setValue:[UIColor redColor] forKeyPath:@"_placeholderLabel.textColor"];
[_textField setValue:[UIFont systemFontOfSize:14] forKeyPath:@"_placeholderLabel.font"];
兼容:
- (UITextField *)set_searchTextField{
if ([UIDevice currentDevice].systemVersion.floatValue >= 13.0) {
//判断xcode版本
return self.searchTextField;
#else
return [self valueForKey:@"searchTextField"];
#endif
}
return [self valueForKey:@"searchField"];
}
Modal Presentation Style
在 iOS13 中, Apple 将视图控制器的默认显示样式从 iOS12 的全屏显示改为 Modal 模式显示,这种类似于弹窗模块的卡片需要你手动往下滑将其取消,这个改动可能会影响应用的一些交互。
Defaults to UIModalPresentationAutomatic on iOS starting in iOS 13.0, and UIModalPresentationFullScreen on previous versions.By default UIViewController resolves UIModalPresentationAutomatic to UIModalPresentationPageSheet, but other system-provided view controllers may resolve UIModalPresentationAutomatic to other concrete presentation styles.
针对 navigationController 增加兼容全屏的代码, Swift、OC 代码中分别设置 modalPresentationStyle 为fullScreen, 示例:
/// swift
@objc private func dismiss() {
let navigationController = UINavigationController(rootViewController: XTNoLoginTagGuideViewController())
navigationController.modalPresentationStyle = .fullScreen
XTGlobalTools.getCurrentVC()?.present(navigationController, animated: true, completion: {
self.removeFromSuperview() })
}
// oc
UINavigationController *navi = [[UINavigationController alloc] initWithRootViewController:readXiaoceVC];
[navi setModalPresentationStyle: UIModalPresentationFullScreen];
[currentVC presentViewController:navi animated:YES completion:nil];
Dark mode
暗黑模式的适配稍微复杂一些,这里把兼容分为基本、中等、最高三个级别:
- 最基本
不适配 dark mode,即用户切换 darkmode 的时和 lightmode 的时候 app 的样式一致,这样能保证用户正常使用。最基本层级的兼容比较容易,尝试直接在项目的 info.split 中更改 User Interface Style 为 Light, 可直接 Xcode 界面设置或更新 info.split 代码
<key>UIUserInterfaceStyle</key>
<string>Light</string>
但这样强制使用 Light 模式带来的影响就是用户切换成 Dark mode ,如果 Status Bar 的显示未兼容会影响用户查看设备状态栏信息。
- 中等
中等适配主要是颜色相关,例如针对 dark mode 修改背景颜色和字体颜色, 需要UI配合针对目前正常的颜色值给出 dark mode 的颜色值,然后整体来修改替换。
- 最高
最高级别的适配除了颜色外,App 中所有涉及到需要兼容的 icon 或图片、webView 样式都需要进行适配,例如 icon 、图片需要准备两套。同样这部分也需要产品、UI 来配合。
子线程修改界面导致崩溃
GCD(Grand Central Dispatch) 是苹果公司为多核的并行运算提出的解决方案, 允许程序将任务切分为多个单一任务然后提交至工作队列来并发地或者串行地执行,主要分为 Main queue 、Global queue 和 Custom queue三种,分别对应串行的主线程、并行的全局队列,自定义队列,Custom Queues 默认是串行,当然也可以设置 attributes 为 concurrent,这样它变成了并行 queue。Main queue 运行在系统主线程的一个串行队列,我们所有的UI刷新都发生在 Main queue.如果我们在主线程外的地方做UI操作则会报错,需要将 UI 刷新操作放置 mainQueue 里,如下例子所示:
DispatchQueue.main.async {
// view 更新操作
self.view.reload()
}
UIWebView
当你需要在应用里展示一些 HTML 页面的时候,就需要用到 webview, iOS中有 UIWebview 和 WKWebview 两种 Webview ,在 WWDC 2018 的演讲介绍中,官方已经宣布正式弃用 UIWebView,并建议之后采用 WKWebview API 构建。
WKWebView has been around since 2014, so it’s not technically new. However, it’s worth mentioning again because we are now officially deprecating UIWebView. So, if you’re starting a new app, or a new project, and would like to display web content that’s not easily put into a native view, use the WKWebView.
区别:
- UIWebView 使用 UIKit 框架,而 WKWebView 使用 WebKit.
- WKWebView 运行在应用单独的一个线程上,并且它可以利用 Safari JavaScript 引擎进行优化,这意味着 WKWebView 加载页面更快更加高效,减少内存开销
- WKWebView 加载本地文件在 iOS 9 中得到修复
- WKWebView 中无法像在 UIWebView 中那样对页面进行缩放适应
WKWebView 增强了对 indexedDB 的支持
// UIWebView
import UIKit
class UIWebViewController: UIViewController{
@IBOutlet weak var webView: UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
let url = URL (string: "https://www.example.com")
let requestObj = URLRequest(url: url!)
webView.backgroundColor = UIColor.blue
webView.loadRequest(requestObj)
}
}
// WKWebView
import UIKit
import WebKit
class WKWebViewController: UIViewController, WKNavigationDelegate {
var webView : WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
let myUrl = "https://www.example.com"
let url = NSURL(string: myUrl)
let request = NSURLRequest(url: url! as URL)
webView = WKWebView(frame: self.view.frame)
webView.navigationDelegate = self
webView.load(request as URLRequest)
self.view.addSubview(webView)
self.view.sendSubview(toBack: webView)
}
}
Sign In With Apple
使用苹果登陆是苹果推出的新功能,方便用户使用他们的苹果ID登录到你的应用程序或网站。无需填写登陆注册表单、验证电子邮件地址、选择新的密码等,可以使用“Sign In With Apple”建立一个帐户并快速开始使用该应用。苹果的在 WWDC2019 介绍PPT中提到:
- 精简的账户注册(Name + Email addresses)
- 使用已验证邮箱地址(依赖 AppleID 做双重验证)
- 反作弊
- 安全地(APP只能访问名称和邮件,苹果不记录信息、可以隐藏邮箱地址)
- 跨平台(iOS macOS watchOS tvOS JavaScript)
Apple 介绍的一些使用场景:
- 用户在你的应用帐户系统功能有限的情况下创建一个帐户进行体验
- 用户在体验产品应用的功能后创建一个账户,例如保存进度、设置个人资料信息等
用户以访客身份完成购买后创建用户
移动端:
接入分为以下四步,提供 “Sign In With Apple” 按钮 => 授权 => 认证 => 处理回调:
在应用的登陆页面添加 “Sign In With Apple” 登陆按钮:
// Add “Sign In with Apple” button to your login view
func setupProviderLoginView() {
let authorizationButton = ASAuthorizationAppleIDButton()
authorizationButton.addTarget(self, action: #selector(handleAuthorizationAppleIDButtonPress), for: .touchUpInside)
self.loginProviderStackView.addArrangedSubview(authorizationButton)
}
绑定按钮点击事件,给苹果发送授权请求:
// Configure request, setup delegates and perform authorization request
func handleAuthorizationAppleIDButtonPress() {
let appleIDProvider = ASAuthorizationAppleIDProvider()
let request = appleIDProvider.createRequest()
request.requestedScopes = [.fullName, .email]let authorizationController = ASAuthorizationController(authorizationRequests: [request]) authorizationController.delegate = self authorizationController.presentationContextProvider = self authorizationController.performRequests() }
针对苹果授权请求响应进行处理,成功即可在系统创建对应账号、保存账号到 keychain 等操作。
extension LoginViewController: ASAuthorizationControllerDelegate {
// 授权成功处理,拿到授权反馈后可以直接创建账号了
func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
if let appleIDCredential = authorization.credential as? ASAuthorizationAppleIDCredential {let userIdentifier = appleIDCredential.user let fullName = appleIDCredential.fullName let email = appleIDCredential.email // Create an account in your system. } } // 授权失败处理 func authorizationController(_: ASAuthorizationController, didCompleteWithError error: Error) { // Handle error }
}
网页端 :
苹果针对网页版应用提供了对应的JS SDK, 也能接入 “Sign In With Apple”,配置过程类似,示例如下:
HTML 头部页面接入 Apple 的 JS:
可以使用 meta 标签或在 JavaScript 代码中配置授权 API 字段,并提供 Apple 登录按钮,如下例子所示:
- 处理认证信息回调,Apple 处理授权请求后会将一个包含授权结果的HTTP POST请求发送到redirectURI 中提供的 URL 中。具体配置可以查看官方文档,参考使用官方提供的 demo。
LaunchImage 弃用
启动页的图片设置方式有两种:
- 通过 LaunchScreen.storyboard 设置
- 通过 Assets.xcassets 增加 iOS Launch Image 设置启动页图片,苹果设备的尺寸增多,意味着我们需要在对应的 assets 里放入对应尺寸的启动图。
‘UILaunchImages’ has been deprecated, use launch storyboards instead.
当 Xcode 升级到11后,如果继续使用则会提示上面提示,建议在 storyboards 设置。
总结
这次适配过程中的一些个人体会:
苹果已经更新了 iOS13 的适配时间节点,从 2020 年 4 月份起,所有提交到 App Store 的应用都需要使用 iOS 13 SDK 或更高的版本来构建,并且还需要兼容 iPhone XS Max 、iPad Pro 等设备,如果提供了第三方登陆功能的应用还得兼容使用 “Sign In With Apple” 登陆,兼容暗黑模式,提供一个暗黑模式下的应用截图,所以建议尽早完成应用 iOS13 的适配。
由于目前并没有完成所有的适配工作,截止到目前开发过程遇到的一些报错基本都是 API 层改动造成的,阅读文档提示加上网上查找答案修改代码即可,只是稍微有一点点 swift 基础,但对 iOS 开发的认识其实远远不够,之后还需要多看多练习代码。
iOS 开发测试发版周期都较长,不像 web 端能快速更新部署上线,例如前期准准备 iOS 开发机器、熟悉Xcode 开发工具、iOS 测试设备、开发者账号、配置证书等需要做比较多的准备工作,后期的 App Store 发版还有可能被拒,所以对代码质量、发版前的测试质量要求都比较高。
附录
作者暂无likerid, 赞赏暂由本网站代持,当作者有likerid后会全部转账给作者(我们会尽力而为)。Tips: Until now, everytime you want to store your article, we will help you store it in Filecoin network. In the future, you can store it in Filecoin network using your own filecoin.
Support author:
Author's Filecoin address:
Or you can use Likecoin to support author: