1、簡化的if let/guard let語法
SE-0345 引入了新的速記語法,可以將可選型展開為同名的變量。以后我們可以像下面這樣解包了:
let name: String? = "zhangsan"
print(name) // Optional("zhangsan")
// Swift5.7之前
// if let
if let name = name {
print(name) // zhangsan
}
// Swift5.7之后
// if let
if let name {
print(name) // zhangsan
}
func method(name: String?, age: Int?) {
// Swift5.7之前
// guard let
guard let name = name else { return }
// Swift5.7之后
// guard let
guard let age else { return }
print("姓名\(name),年齡\(age)")
}
2 、增強(qiáng)的閉包類型推斷
SE-0326 極大地提高了 Swift 對閉包使用參數(shù)和類型推斷的能力,這意味著我們現(xiàn)在可以刪除許多必須明確指定輸入和輸出類型的寫法。
let array: [String] = ["11", "2", "3", "40", "5"]
// Swift5.7之前
let newArray1 = array.map { str -> Int in
if str.count > 1 {
return Int(str) ?? 0
} else {
return Int(10)
}
}
print(newArray1) // [11, 10, 10, 40, 10]
// Swift5.7之后
let newArray2 = array.map { str in
if str.count > 1 {
return Int(str) ?? 0
} else {
return Int(10)
}
}
print(newArray2) // [11, 10, 10, 40, 10]
3、基于默認(rèn)表達(dá)式的類型推斷
SE-0347 擴(kuò)展了 Swift 使用泛型參數(shù)類型的默認(rèn)值的能力。如果你有一個(gè)泛型類型或函數(shù),現(xiàn)在可以為默認(rèn)表達(dá)式提供一個(gè)具體類型。
例如,我們可能有一個(gè)函數(shù),它從任意類型的序列中返回 count 個(gè)隨機(jī)項(xiàng):
func drawLotto1<T: Sequence>(from options: T, count: Int = 7) -> [T.Element] {
Array(options.shuffled().prefix(count))
}
這允許我們使用任何類型的序列來運(yùn)行函數(shù),例如字符串?dāng)?shù)組或者整數(shù)范圍:
print(drawLotto1(from: 1...49))
print(drawLotto1(from: ["Jenny", "Trixie", "Cynthia"], count: 2))
SE-0347 允許我們?yōu)楹瘮?shù)中的 T
參數(shù)提供一個(gè)具體類型作為默認(rèn)值,同時(shí)允許我們保持使用字符串?dāng)?shù)組或任何其他序列類型的靈活性:
func drawLotto2<T: Sequence>(from options: T = 1...49, count: Int = 7) -> [T.Element] {
Array(options.shuffled().prefix(count))
}
這樣一來我們既可以使用自定義序列調(diào)用函數(shù),也可以讓默認(rèn)值接管:
print(drawLotto2(from: ["Jenny", "Trixie", "Cynthia"], count: 2))
print(drawLotto2())
4、 函數(shù)參數(shù)與返回類型支持不透明結(jié)果類型
SE-0341 解鎖了在使用更簡單泛型的地方對參數(shù)聲明使用 some 的能力。
some --- 用在當(dāng)返回值為不確定類型的情況。
some類型只對已聲明的屬性和下標(biāo)類型以及函數(shù)的返回類型實(shí)現(xiàn)
舉個(gè)例子,如果我們想編寫一個(gè)檢查數(shù)組是否排序的函數(shù),Swift 5.7 及更高版本允許我們這樣寫:
func isSorted(array: [some Comparable]) -> Bool {
array == array.sorted()
}
[some Comparable] 參數(shù)類型意味著此函數(shù)適用于包含某種類型的元素的數(shù)組,該類型遵循 Comparable
協(xié)議,這是等效通用代碼的語法糖:
func isSortedOld<T: Comparable>(array: [T]) -> Bool {
array == array.sorted()
}
當(dāng)然,我們也可以寫更長的約束擴(kuò)展:
extension Array where Element: Comparable {
func isSorted() -> Bool {
self == self.sorted()
}
}
這種簡化的泛型語法確實(shí)意味著我們不再有能力為我們的類型添加更復(fù)雜的約束,因?yàn)楹铣傻姆盒蛥?shù)沒有特定的名稱。
5、結(jié)構(gòu)化的不透明結(jié)果類型
SE-0328 拓寬了不透明結(jié)果類型可以使用的范圍。
例如,我們現(xiàn)在可以一次返回多個(gè)不透明類型:
func showUserDetails() -> (some Equatable, some Equatable) {
("Username", "@twostraws")
}
返回不透明類型數(shù)組:
func createUser() -> [some Equatable] {
["Username", "Username"]
}
6、 不可異步屬性
SE-0340 通過允許我們將類型和函數(shù)標(biāo)記為在異步上下文中不可用,部分屏蔽了 Swift 并發(fā)模型中的潛在風(fēng)險(xiǎn)情況。
要將某些內(nèi)容標(biāo)記為在異步上下文中不可用,需要使用 @available,然后在末尾添加 noasync,例如:
@available(*, noasync)
func doRiskyWork() {
}
在常規(guī)的同步函數(shù)中,我們可以正常調(diào)用它:
func synchronousCaller() {
doRiskyWork()
}
假如我們試圖在異步函數(shù)中也這么做,Swift 會(huì)指出錯(cuò)誤:
func asynchronousCaller() async {
doRiskyWork()
}
這個(gè)保護(hù)機(jī)制是一種改進(jìn),但我們不應(yīng)過度依賴它。因?yàn)樗鼰o法防范我們把調(diào)用嵌套到同步函數(shù)內(nèi)部的情況,例如:
func sneakyCaller() async {
synchronousCaller()
}
上面的代碼在異步上下文中運(yùn)行,但調(diào)用同步函數(shù),該函數(shù)又可以調(diào)用 noasync 函數(shù) doRiskyWork()。
7、正則表達(dá)式
-
SE-0350 引入了新的
Regex類型 -
SE-0351 引入了一個(gè)用于創(chuàng)建正則表達(dá)式的
result builder驅(qū)動(dòng)的 DSL。 -
SE-0354 引入了使用
/.../而不單是Regex來共同創(chuàng)建正則表達(dá)式的方式。 - SE-0357 添加了許多新的基于正則表達(dá)式的字符串處理算法。
現(xiàn)在,讓我們從簡單的例子開始:
let message = "the cat sat on the mat"
print(message.ranges(of: "at"))
print(message.replacing("cat", with: "dog"))
print(message.trimmingPrefix("the "))
//尋找“The”,但將正則表達(dá)式修改為不區(qū)分大小寫,以便匹配“the”、“THE”等。
print(message.trimmingPrefix(/The/.ignoresCase()))
Swift 還提供了專門的 Regex 類型:
do {
let atSearch = try Regex("[a-z]at")
print(message.ranges(of: atSearch))
} catch {
print("Failed to create regex")
}
這里兩種方式有一個(gè)關(guān)鍵區(qū)別:當(dāng)我們使用 Regex 從字符串創(chuàng)建正則表達(dá)式時(shí),Swift 必須在運(yùn)行時(shí)解析字符串以找出它應(yīng)該使用的實(shí)際表達(dá)式。相比之下,使用正則表達(dá)式字面量允許 Swift 在編譯時(shí) 檢查你的正則表達(dá)式:它可以驗(yàn)證正則表達(dá)式不包含錯(cuò)誤,并且還可以準(zhǔn)確了解它將包含什么匹配項(xiàng)。
func regularFunc() {
let message = "This is a regex test case 123456789 一二三"
do {
// 字符串中搜索regex
let regex = try Regex("[a-z] regex")
let index = message.ranges(of: regex)
// 范圍
print("范圍--\(index)")
// 替換
print(message.replacing(regex, with: "正則表達(dá)式"))
} catch {
print("Failed to create Regex")
}
// /.../創(chuàng)建正則表達(dá)式,查找數(shù)字并替換
// \d+:一個(gè)或多個(gè)數(shù)字。
print(message.replacing(/(\d+)/, with: "我是數(shù)字"))
}
相關(guān)文章
1、Xcode14新特性(基于Xcode 14 Beta1)
2、史上最全正則表達(dá)式語法,文末附常用表達(dá)式!
3、Swift5.7下