Swift5.7(上)

apple / swift-evolution

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下

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容