Swift5.5git
WWDC2021 給咱們帶來了Swift 5.5,這是Swift 語言最新的版本,在這個版本中有許多重大的更新,下面會你們詳細介紹一下Swift 5.5的一些重要更新。
github
▐ Swift Concurrency
Swift 5.5 中最大的更新就是引入了全新的併發編程方式,包括async/await語法、結構化併發、Actor等,新的併發編程方式解決了咱們以往使用回調的種種缺陷 (嵌套地獄、回調錯誤處理麻煩、回調分支編寫困難等),爲開發者帶來了極大的便利。web
async/await
過去咱們編寫異步代碼都是經過回調的方式,以下:express
func processImageData2a(completionBlock: (_ result: Image?, _ error: Error?) -> Void) { loadWebResource("dataprofile.txt") { dataResource, error in guard let dataResource = dataResource else { completionBlock(nil, error) return } loadWebResource("imagedata.dat") { imageResource, error in guard let imageResource = imageResource else { completionBlock(nil, error) return } decodeImage(dataResource, imageResource) { imageTmp, error in guard let imageTmp = imageTmp else { completionBlock(nil, error) return } dewarpAndCleanupImage(imageTmp) { imageResult, error in guard let imageResult = imageResult else { completionBlock(nil, error) return } completionBlock(imageResult) } } } }}
processImageData2a { image, error in guard let image = image else { display("No image today", error) return } display(image)}
經過回調的方式編寫異步代碼有如下缺點:編程
閱讀不直觀canvas
嵌套邏輯複雜swift
錯誤處理麻煩xcode
分支邏輯難以處理安全
常常會忘了回調或者返回
在Swift 5.5中爲了解決上述回調方式的缺點,引入了async/await語法,能夠幫助咱們快速的編寫異步代碼,經過async/await上述代碼能夠變成以下同步代碼:
func loadWebResource(_ path: String) async throws -> Resourcefunc decodeImage(_ r1: Resource, _ r2: Resource) async throws -> Imagefunc dewarpAndCleanupImage(_ i : Image) async throws -> Image
func processImageData() async throws -> Image { let dataResource = try await loadWebResource("dataprofile.txt") let imageResource = try await loadWebResource("imagedata.dat") let imageTmp = try await decodeImage(dataResource, imageResource) let imageResult = try await dewarpAndCleanupImage(imageTmp) return imageResult}
正如上述代碼所展示的,全部的閉包和縮進都消失了,你能夠按順序依次書寫代碼——除了 await 關鍵字,它看起來就和同步代碼同樣。
關於async函數的工做方式,有一些規則須要注意:
同步函數不能簡單地直接調用異步函數, Swift 編譯器會拋出錯誤。
異步函數能夠調用其餘異步函數,但若是須要,它們也能夠調用常規的同步函數。
若是有能夠以相同方式調用的異步和同步函數,Swift 將優先選擇與當前上下文匹配的任何一個, 若是當前執行上下文是異步的,那麼 Swift 將調用異步函數,不然它將調用同步函數。
最後一點很重要,由於它容許庫的做者提供他們代碼的同步和異步版本,而無需專門命名異步函數。
Structured concurrency
在介紹結構化併發以前,咱們先來看一個案例:
func chopVegetables() async throws -> [Vegetable] { ... }func marinateMeat() async -> Meat { ... }func preheatOven(temperature: Double) async throws -> Oven { ... }
// ...
func makeDinner() async throws -> Meal { let veggies = try await chopVegetables() // 處理蔬菜 let meat = await marinateMeat() // 醃製肉 let oven = try await preheatOven(temperature: 350) //預熱烤箱
let dish = Dish(ingredients: [veggies, meat]) // 把蔬菜和肉裝盤 return try await oven.cook(dish, duration: .hours(3)) // 用烤箱作出晚餐}
上面處理蔬菜、醃製肉、預熱烤箱等都是異步執行的,可是上述三個步驟仍然是串行執行的,這使得作晚餐的時間變長了,爲了讓晚餐準備時間變短,咱們須要讓處理蔬菜、醃製肉、預熱烤箱幾個步驟併發執行
爲了解決上述問題,Swift 5.5中引入了Structured concurrency(結構化併發),下面是維基百科中的解釋:
結構化併發是一種編程範式,旨在經過使用結構化的併發編程方法來提升計算機程序的清晰度、質量和研發效能。
核心理念是經過具備明確入口和出口點並確保全部生成的子任務在退出前完成的控制流構造來封裝併發執行任務(這裏包括內核和用戶線程和進程)。這種封裝容許併發任務中的錯誤傳播到控制結構的父做用域,並由每種特定計算機語言的本機錯誤處理機制進行管理。儘管存在併發性,但它容許控制流經過源代碼的結構保持顯而易見。爲了有效,這個模型必須在程序的全部級別一致地應用——不然併發任務可能會泄漏、成爲孤立的或沒法正確傳播運行時錯誤。(來自維基百科)
使用結構化併發,上述製做晚餐的過程能夠經過下面的方式進行:
func makeDinner() async throws -> Meal { // Prepare some variables to receive results from our concurrent child tasks var veggies: [Vegetable]? var meat: Meat? var oven: Oven?
enum CookingStep { case veggies([Vegetable]) case meat(Meat) case oven(Oven) }
// Create a task group to scope the lifetime of our three child tasks try await withThrowingTaskGroup(of: CookingStep.self) { group in group.async { try await .veggies(chopVegetables()) } group.async { await .meat(marinateMeat()) } group.async { try await .oven(preheatOven(temperature: 350)) }
for try await finishedStep in group { switch finishedStep { case .veggies(let v): veggies = v case .meat(let m): meat = m case .oven(let o): oven = o } } }
// If execution resumes normally after `withTaskGroup`, then we can assume // that all child tasks added to the group completed successfully. That means // we can confidently force-unwrap the variables containing the child task // results here. let dish = Dish(ingredients: [veggies!, meat!]) return try await oven!.cook(dish, duration: .hours(3))}
Actors
class RiskyCollector { var deck: Set<String>
init(deck: Set<String>) { self.deck = deck }
func send(card selected: String, to person: RiskyCollector) -> Bool { guard deck.contains(selected) else { return false }
deck.remove(selected) person.transfer(card: selected) return true }
func transfer(card: String) { deck.insert(card) }}
actor SafeCollector { var deck: Set<String>
init(deck: Set<String>) { self.deck = deck }
func send(card selected: String, to person: SafeCollector) async -> Bool { guard deck.contains(selected) else { return false }
deck.remove(selected) await person.transfer(card: selected) return true }
func transfer(card: String) { deck.insert(card) }}
-
Actor 是使用新的 actor 關鍵字建立的 -
send() 方法被標記爲 async,由於它須要異步執行 -
儘管 transfer(card:) 方法沒有用 async 標記,但咱們仍然須要用 await 調用它,由於它會等到另外一個 SafeCollector actor 可以處理請求。
-
二者都是引用類型,所以它們可用於共享狀態。 -
它們能夠有方法、屬性、初始值設定項和下標。 -
它們能夠實現協議。任何靜態屬性和方法在這兩種類型中的行爲都相同,由於它們沒有 self 的概念,所以不會被隔離。
-
Actor 目前不支持繼承,這在將來可能會改變 -
全部 Actor 都隱式遵照一個新的 Actor Protocol
更新項 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
不限制 |
|
|
|
|
|
|
|
DocC
▐ DocC註釋編寫
/// Eat the provided specialty sloth food.////// Sloths love to eat while they move very slowly through their rainforest /// habitats. They're especially happy to consume leaves and twigs, which they /// digest over long periods of time, mostly while they sleep.////// When they eat food, a sloth's `energyLevel` increases by the food's `energy`.////// - Parameters:/// - food: The food for the sloth to eat./// - quantity: The quantity of the food for the sloth to eat.////// - Returns: The sloth's energy level after eating.////// - Throws: `SlothError.tooMuchFood` if the quantity is more than 100.mutating public func eat(_ food: Food, quantity: Int) throws -> Int {

▐ 從代碼註釋構建DocC文檔
要爲 Swift 工程構建文檔,請選擇Product > Build Documentation。DocC 編譯工程的文檔並能夠在 Xcode 的文檔查看器中打開它。
Notifications
在WWDC2021中,系統通知也發生了較大的變化,具體反映在以下幾個方面:
▐ 視覺升級
好比用戶收到以下通知:
在iOS15系統中開發者能夠自定義點擊效果,以下圖
爲了實現上述App icon、內容擴展、動做icon等視覺效果,咱們只須要按照下面的方式進行開發:
▐ Focus Mode
Apple 新增了Focus Mode,這個模式能夠更好地使通知體驗與用戶偏好保持一致。
新的專一模式很是適合減小對用戶的干擾。iPhone用戶能夠自定義他們但願收到通知的方式和時間。之前,用戶能夠經過啓用「請勿打擾」模式來選擇將全部來電和通知靜音。如今,用戶將可以經過設置工做、睡眠和我的通知模式來完善他們的通知偏好以適應不一樣的場景。
對於每一個配置文件,用戶能夠選擇要接收通知的應用和聯繫人、要阻止的應用和聯繫人,以及要暫停的特定應用功能。用戶還能夠建立一個主屏幕頁面以匹配他們當前的焦點模式並僅顯示相關的應用程序。例如,在工做模式下,用戶能夠選擇僅查看與工做相關的應用程序。
焦點配置文件將同步到全部其餘蘋果設備。 焦點設置也能夠由其餘設置肯定,例如一天中的時間、地理位置或日曆事件。
Apple 將使用 AI 自動預測要設置的配置文件。例如,當用戶到達工做地點時,iPhone 可使用地理位置數據來觸發工做模式,或者在用戶接近就寢時間時使用睡眠時間偏好來觸發睡眠模式。
還將有兩個與焦點模式相關的新 API。 Status API 告訴應用設備是否處於焦點模式。時間敏感 API 容許應用指定對時間敏感的通知以覆蓋設置。
// 返回焦點系統的狀態,包括有關當前焦點項目的信息。class func status() -> UIFocusDebuggerOutput
// 返回系統通知時間敏感的設置var timeSensitiveSetting: UNNotificationSetting { get }