为了记念上周发布的iOS13,咱们来看一看你如今能够在你的应用程序中使用的一些模糊的(基本上是没有文档的)API。咱们已经清除了最好的部分IOS13发行说明API差别如今把它们呈现给你。 下面是咱们最喜欢的一些从iOS 13开始能够作的事情:html
新的IOS 13,连接呈现框架提供一种方便的内置方式来复制您在消息中看到的URL的丰富预览。若是您的应用程序有任何聊天或消息功能,您确定会想要检查这一点。ios
丰富的URL预览至少能够追溯到20世纪初,随着微格式由语义web先驱和早期先驱使用khtml2png若要生成网页的缩略图图像,请执行如下操做。快到2010年,随着社交媒体和用户生成的内容的兴起,facebook建立了OpenGraphProtocol容许网络出版商自定义其页面的外观时,张贴在新闻提要。git
现在,大多数网站都有开放图形标签在他们的网站上,为社会网络,搜索引擎,以及任何其余连接被贩运的地方提供他们的内容摘要。例如,若是您对这个网页进行了“查看源”,您将看到如下内容:web
<meta property="og:site_name" content="NSHipster" />
<meta property="og:image" content="https://nshipster.com/logo.png" />
<meta property="og:type" content="article" />
<meta property="og:title" content="iOS 13" />
<meta property="og:url" content="https://nshipster.com/ios-13/" />
<meta property="og:description" content="To mark last week's release of iOS 13, we're taking a look at some obscure (largely undocumented) APIs that you can now use in your apps." />
复制代码
若是您想在应用程序中使用这些信息,如今可使用LinkPresting框架的LPMetadataProvider类来获取元数据,并可选择地构造一个表示:api
import LinkPresentation
let metadataProvider = LPMetadataProvider()
let url = URL(string: "https://nshipster.com/ios-13/")!
let metadataProvider = LPMetadataProvider()
metadataProvider.startFetchingMetadata(for: url) { [weak self] metadata, error in
guard let metadata = metadata else { return }
let linkView = LPLinkView(metadata: metadata)
self?.view.addSubview(linkView)
}
复制代码
在设置适当的约束(或者调用sizeToFit()),您将获得如下内容,用户能够点击它预览连接的网页:bash
在startFetchingMetadata(for:)完成处理程序,您能够检查和变异从服务器检索的元数据。您可能会利用这个机会为没有这些内容的页面添加默认的图像/视频,将文本翻译成用户首选的语言之一,或者检查显式文本和媒体。服务器
或者,若是您已经在-app中拥有元数据,或者不能或不但愿远程获取元数据,则能够构造一个LPLinkMetadata直接:网络
let metadata = LPLinkMetadata()
metadata.url = url
metadata.title = "iOS 13"
metadata.iconProvider = ...
let linkView = LPLinkView(metadata: metadata)
复制代码
LPMetadataProvider
在IOS上作广告,但MacOS客户端必须具备com.apple.security.network.client权限,以便从远程URL获取元数据。session
SFSpeechRecognizer在iOS 13中得到一次重大升级-最显著的是它增长了对设备上语音识别的支持。app
之前,抄写须要一个互联网链接,而且被限制在最多1分钟的时间内,天天的请求都有限制。可是如今,你能够彻底在设备上和离线下进行语音识别,没有任何限制.惟一要注意的是,离线转录不如服务器链接的效果好,并且只适用于某些语言。
若要肯定脱机转录是否可用于用户的区域设置,请检查SFSpeechRecognizer财产supportsOnDeviceRecognition..在出版时,所支持的语文清单以下:
根据IOS 13发布说明:
“supportsOnDeviceRecognition属性老是返回false第一次被访问的时候。几秒钟后,再次访问它将返回正确的值。“
但这并非iOS 13中的所有语音识别!SFSpeechRecognizer如今提供信息,包括说话速率和平均停顿时间,以及语音分析功能,如抖动(音高的变化)和闪光器(振幅的变化)。
import Speech
guard SFSpeechRecognizer.authorizationStatus() == .authorized
let recognizer = SFSpeechRecognizer()
else {
fatalError()
}
let url: URL = ...
let request = SFSpeechURLRecognitionRequest(url: url)
recognizer.recognitionTask(with: request) { (result, error) in
guard let result = result else { return }
for segment in result.bestTranscription.segments {
guard let voiceAnalytics = segment.voiceAnalytics else { continue }
let pitch = voiceAnalytics.pitch.acousticFeatureValuePerFrame
let voicing = voiceAnalytics.voicing.acousticFeatureValuePerFrame
let jitter = voiceAnalytics.jitter.acousticFeatureValuePerFrame
let shimmer = voiceAnalytics.shimmer.acousticFeatureValuePerFrame
}
}
复制代码
您的应用程序可使用有关音调、语音和其余功能的信息(可能)。协同CoreML)区分说话人或从说话人的拐弯处肯定潜台词。
说到FoundationURL加载系统,咱们如今已经有了本机支持的东西,这些东西在咱们的愿望列表中占据了不少年的首位:Web套接字.
多亏了新的URLSessionWebSocketTask在IOS 13中,您如今能够像发送HTTP请求同样轻松可靠地在应用程序中集成实时通讯-全部这些都没有任何第三方库或框架:
let url = URL(string: "wss://...")!
let webSocketTask = URLSession.shared.webSocketTask(with: url)
webSocketTask.resume()
// Configure how messages are received
webSocketTask.receive { result in
guard let .success(message) = result else { return }
...
}
// Send a message
let message: URLSessionWebSocketTask.Message = .string("Hello, world!")
webSocketTask.send(message) { error in
...
}
// Eventually...
webSocketTask.cancel(with: .goingAway, reason: nil)
复制代码
对于web套接字的低级控制,包括客户端和服务器支持,请查看网络框架.
多年来,网络可能一直是整个苹果技术体系中移动最快的部分。每一个WWDC,都有太多要谈论的话题,以致于他们不得不在两个不一样的会议上打破他们的内容。2019年也不例外,咱们强烈建议你花点时间看看今年的“网络进步”会议(第一部分, 第二部分).
MapKit是Apple SDK的另外一个组成部分,它在WWDC上年复一年地表现强劲。在咱们平常生活中,影响最大的每每是那些小小的触碰。
例如,新的MKMapView.CameraBoundaryiOS 13中的API使得在不彻底锁定地图的状况下将地图的视口限制到特定区域变得容易得多。
let region = MKCoordinateRegion(center: mapView.center,
latitudinalMeters: 1000,
longitudinalMeters: 1000)
mapView.cameraBoundary = MKMapView.CameraBoundary(coordinateRegion: region)
复制代码
新的MKPointOfInterestFilterapi,您如今能够自定义地图视图的外观,只显示特定类型的兴趣点。(而之前是全无命题).
let filter = MKPointOfInterestFilter(including: [.cafe])
mapView.pointOfInterestFilter = filter // only show cafés
复制代码
最后,用MKGeoJSONDecoder,咱们如今有一个内置的方式来拉进来。GeoJSON来自Web服务和其余数据源的形状。
let decoder = MKGeoJSONDecoder()
if let url = URL(string: "..."),
let data = try? Data(contentsOfURL: url),
let geoJSONObjects = try? decoder.decode(data) {
for case let overlay as MKOverlay in geoJSONObjects {
mapView.addOverlay(overlay)
}
}
复制代码
若是你喜欢咱们的文章JavaScriptCore,你会很高兴知道JSValue对象如今本地支持承诺.
对于不熟悉的人:在JavaScript中,Promise表示异步操做的最终完成(或拒绝)及其结果值的对象。承诺是现代JS开发的支柱-也许最值得注意的是fetchAPI
iOS 13中JavaScriptCore的另外一个补充是对符号(不,不是那些符号)。有关init(newSymbolFromDescription:in:), 参考文档 猜猜怎么用。
在云雀上,咱们决定看看目标C今年是否有什么新发现,并惊讶地发现objc_setHook_setAssociatedObject..一样,除了声明以外,咱们没有什么可继续进行的,可是如今您彷佛能够配置一个块,以便在关联对象已经设定好了。对于任何仍深刻目标C运行时的人来讲,这听起来很方便。
关于失踪文件的问题:UIActivityItemsConfiguration彷佛就像在新的iOS13共享表中管理操做的一个颇有吸引力的选项,可是咱们不知道从哪里开始…
遗憾的是,咱们尚未足够的信息来利用这一点。
中讨论过的前一篇文章,IOS 13为基金会带来了两个新的格式:ListFormatter和RelativeDateTimeFormatter.
不是为了唠叨这件事,但他们都是仍然所以,若是您想了解更多信息,咱们建议您从7月份开始查看这篇文章。或者,若是您很着急,下面是一个演示如何将二者结合使用的快速示例:
import Foundation
let relativeDateTimeFormatter = RelativeDateTimeFormatter()
relativeDateTimeFormatter.dateTimeStyle = .named
let listFormatter = ListFormatter()
listFormatter.string(from: [
relativeDateTimeFormatter.localizedString(from: DateComponents(day: -1)),
relativeDateTimeFormatter.localizedString(from: DateComponents(day: 0)),
relativeDateTimeFormatter.localizedString(from: DateComponents(day: 1))
]) // "yesterday, today, and tomorrow"
复制代码
从iOS 13开始,OperationQueue如今有一个progress财产。
固然,(NS)Progress对象并非最简单、最方便的东西(咱们一直打算在某个时候写一篇关于它们的文章),可是它们有一个完整的、通过深思熟虑的API,甚至在应用程序框架中也有一些方便的插槽。
例如,检查链接一个UIProgressView若要以其方式显示操做队列的实时更新进度,请执行如下操做:observedProgress财产:
import UIKit
fileprivate class DownloadOperation: Operation { ... }
class ViewController: UIViewController {
private let operationQueue = {
let queue = OperationQueue()
queue.maxConcurrentOperationCount = 1
}()
@IBOutlet private var progressView: UIProgressView!
@IBAction private func startDownloading(_ sender: Any) {
operationQueue.cancelAllOperations()
progressView.observedProgress = operationQueue.progress
for url in [...] {
let operation = DownloadOperation(url: url)
operationQueue.addOperation(operation)
}
}
}
复制代码
还值得一提的是13岁时出现的其余一些API,如schedule(after:interval:tolerance:options::),哪条线索OperationQueue进入新的组合框架以一种很好的方式,并且addBarrierBlock(:),它的工做原理多是调度屏障(虽然没有文档,但这是任何人的猜想)。
定义应用程序与竞争对手的区别之一是,它们使用后台任务来确保应用程序在下一次进入前台时获得充分同步和更新。
iOS 7是第一个提供用于调度后台任务的官方API (尽管在此以前,开发人员使用了各类创造性的方法)..但在这段时间里,多个因素-从iOS应用程序能力和复杂性的提升,到对应用程序的性能、效率和隐私的日益重视-催生了对更全面解决方案的需求。
该解决方案是经过新的iOS 13实现的。背景测试框架.
现在年WWDC会议所述“应用程序后台执行的进展”该框架区分了两大类背景任务:
WWDC会话和附带的示例代码项目很好地解释了如何将这二者结合到您的应用程序中。可是,若是您想要它的快速要点,下面是一个应用程序从Web服务器按期刷新的一个小例子:
import UIKit
import BackgroundTasks
fileprivate let backgroundTaskIdentifier = "com.nshipster.example.task.refresh"
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
lazy var backgroundURLSession = {
let configuration = URLSessionConfiguration.background(withIdentifier: "com.nshipster.url-session.background")
configuration.discretionary = true
configuration.timeoutIntervalForRequest = 30
return URLSession(configuration: configuration, delegate: ..., delegateQueue: ...)
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
...
BGTaskScheduler.shared.register(forTaskWithIdentifier: backgroundTaskIdentifier, using: nil) { task in
self.handleAppRefresh(task: task as! BGAppRefreshTask)
}
return true
}
func applicationDidEnterBackground(_ application: UIApplication) {
scheduleAppRefresh()
}
func scheduleAppRefresh() {
let request = BGAppRefreshTaskRequest(identifier: backgroundTaskIdentifier)
request.earliestBeginDate = Date(timeIntervalSinceNow: 60 * 10)
do {
try BGTaskScheduler.shared.submit(request)
} catch {
print("Couldn't schedule app refresh: \(error)")
}
}
func handleAppRefresh(task: BGAppRefreshTask) {
scheduleAppRefresh()
let url: URL = ...
var dataTask = backgroundURLSession.dataTask(with: url) { (data, response, error) in
...
let success = (200..<300).contains(response?.statusCode)
task.setTaskCompleted(success: success)
}
task.expirationHandler = {
dataTask.cancel()
}
dataTask.resume()
}
...
}
复制代码
之前进行背景更新的方法-即,UIApplication.setMinimumBackgroundFetchInterval(:)和UIApplicationDelegate.application(:performFetchWithCompletionHandler:)-如今已在IOS 13中被否决。
注释文本内容类型以得到更好的可访问性。 你知道听到一些人读出网址是多么使人沮丧吗?“eɪʧtipiˈkoʊlənslʃˈdʌbəljuˈdʌbəljudɑt”…)这就是当画外音试图在不了解更多信息的状况下阅读一些东西什么在看书。
iOS 13承诺经过新的accessibilityTextualContext财产和UIAccessibilityTextAttributeContextNSAttributedString属性键只要有可能,必定要用最能描述所显示的文本类型的常量对视图和属性字符串进行注释:
SwiftUI可能已经预示了故事板的最终结束,但这并不意味着事情不是也不会继续好转,直到那一天到来。
对于斯威夫特纯粹主义者来讲,在使用故事板进行iOS项目时,最使人恼火的反模式之一就是视图控制器初始化。因为Interface Builder的“准备”方法与SWIFT的对象初始化规则之间的阻抗不匹配,咱们常常不得不在使全部属性成为非私有、变量和(隐式展开)选项之间进行选择,或者彻底选择前面的故事板。
Xcode 11和IOS 13容许这些范例经过新的方式来协调它们之间的差别。@IBSegueAction属性和一些新的UIStoryboard班级方法:
首先,@IBSegueAction属性能够应用视图控制器方法声明来指定本身为API,负责建立segue的目标视图控制器。(即destinationViewController的属性segue参数中的prepare(for:sender:)方法).
@IBSegueAction
func makeProfileViewController(coder: NSCoder, sender: Any?, segueIdentifier: String?) -> ProfileViewController? {
ProfileViewController(
coder: coder,
name: self.selectedName,
avatarImageURL: self.selectedAvatarImageURL
)
}
复制代码
第二,UIStoryboard类方法instantiateInitialViewController(creator:)和instantiateViewController(identifier:creator:)提供一个方便的基于块的定制点来实例化Storyboard的视图控制器.
import UIKit
struct Person { ... }
class ProfileViewController: UIViewController {
let name: String
let avatarImageURL: URL?
init?(coder: NSCoder, name: String, avatarImageURL: URL?) {
self.name = name
self.avatarImageURL = avatarImageURL
super.init(coder: coder)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
let storyboard = UIStoryboard(name: "ProfileViewController", bundle: nil)
storyboard.instantiateInitialViewController(creator: { decoder in
ProfileViewController(
coder: decoder,
name: "Johnny Appleseed",
avatarImageURL: nil
)
})
复制代码
和新的UIKit场景在咱们等待SwiftUI成熟和稳定的时候,iOS 13提供了大量的工做。
这是为了咱们的iOS 13功能的总结性,你可能已经错过了。可是请放心-咱们计划在将来的NSHipster文章中涵盖更多的新API。
若是遗漏了什么你想让咱们来掩护,请经过加咱们的交流群 点击此处进交流群 ,来一块儿交流或者发布您的问题,意见或反馈。