原文:Exploring the new String API in Swift 4 — Swift by Sundelljavascript
WWDC 已經結束了(我以爲是自 2014 年來最好的一場 WWDC),同時 Xcode 9 beta 版也發佈了,不少開發者已經開始把玩 Swift 4 ,今年的新版本真心不錯,這是一個改進版本而不是重構版本(像 Swift 2 和 3),所以大多數代碼升級起來會更容易。java
其中一個改進是 String 的 API,在 Swift 4 中更易用,也更強大。在過去的 Swift 版本中,String API 常常被提出爲一個例子用來講明正確性,以繁瑣的方式處理字符和子串。git
本週,咱們來看看在 Swift 4 中如何使用 String,以及如何在各類狀況下利用新的改進的 API。程序員
有時咱們的應用或腳本中有很長的靜態字符串會跨越多行。在 Swift 4以前,咱們只能在字符串之間插入 \n
來換行,appendOnNewLine()
經過給 String 添加一個 extension
方法,屢次 print()
來添加換行符用來大段文本輸出。github
譯者注:這裏的腳本指的是命令行程序swift
好比,下面是 TestDrive
的 printHelp()
方法(用於打印腳本的使用說明)在 Swift 3 看起來以下:api
func printHelp() {
print("🚘 Test Drive")
print("--------------")
print("Quickly try out any Swift pod or framework in a playground.")
print("\nUsage:")
print("- Simply pass a list of pod names or URLs that you want to test drive.")
print("- You can also specify a platform (iOS, macOS or tvOS) using the '-p' option")
print("- To use a specific version or branch, use the '-v' argument (or '-m' for master)")
print("\nExamples:")
print("- testdrive Unbox Wrap Files")
print("- testdrive https://github.com/johnsundell/unbox.git Wrap Files")
print("- testdrive Unbox -p tvOS")
print("- testdrive Unbox -v 2.3.0")
print("- testdrive Unbox -v swift3")
}複製代碼
Swift 4 中處理多行文本字符串:app
func printHelp() {
print(
"""
🚘 Test Drive
--------------
Quickly try out any Swift pod or framework in a playground.
Usage:
- Simply pass a list of pod names or URLs that you want to test drive.
- You can also specify a platform (iOS, macOS or tvOS) using the '-p' option
- To use a specific version or branch, use the '-v' argument (or '-m' for master)
Examples:
- testdrive Unbox Wrap Files
- testdrive https://github.com/johnsundell/unbox.git Wrap Files
- testdrive Unbox -p tvOS
- testdrive Unbox -v 2.3.0
- testdrive Unbox -v swift3
"""
)
}複製代碼
如上所示,當使用多行文本字符串時,代碼會表示得更加清楚和整潔,咱們不須要再添加不少 \n
換行符,而是簡單地在字符串中添加真正的換行符,使得在運行腳本以前,能夠很容易地看到輸出後的樣子。框架
在縮進方面,多行文本字符串使用底部的 """
來肯定字符串的基礎縮進,因此跟這些引號對齊的全部內容都不會在字符串中進行額外的真實縮進。工具
在 Swift 1 中,String 遵循了 CollectionType
(Swift 3+ 中的 Collection
)協議,這意味着您能夠對它們執行各類收集操做(好比 forEach()
,filter()
等)。 您仍然能夠在 Swift 2 & 3 中進行此操做,經過訪問 characters
屬性,但這很快會致使閱讀代碼更難。
Swift 4 中字符串再次成爲了集合對象,這意味着你能夠簡單地將它們視爲「字符集合」。這可能會頗有用,好比從字符串中過濾出某些字符(讓咱們以歎號爲例):
let filtered = string.filter { $0 != "!" }複製代碼
Swift 4 引入了一種處理子字符串的新方法,使用了一個徹底不一樣的類型 Substring 。如今大多數方法都會返回 Substring(如 split()
),而且還引入了一個新的 subscripting API,讓你能夠快速訪問一個子字符串:
// 從一個置頂的
let substring = string[index...]複製代碼
咱們來看一個例子,咱們截斷用戶輸入的文本返回一個子字符串,將其限制在必定長度。在 Swift 3 中,你會寫成這樣:
extension String {
func truncated() -> String {
return String(characters.prefix(truncationLimit))
}
}複製代碼
(編輯註釋:我以前用的是一個更復雜的例子,感謝 Ole Begemann 指出這個更好的解決方案)
好消息是,因爲 Swift 4 代碼大多數兼容 Swift 3,因此上述代碼一樣能夠在 Swift 4 下運行。但更好的消息是,因爲 String 在 Swift 4 中是集合類型,咱們能夠直接簡化上述代碼爲:
extension String {
func truncated() -> Substring {
return prefix(truncationLimit)
}
}複製代碼
上面用 prefix()
方法返回最多爲 n 個元素的子序列,同時包括邊界檢查(若是咱們的集合(這裏是字符串)包含少於 n 個元素的時候,以防咱們不會遇到錯誤)。
你能夠看到上面的 truncated()
方法的返回類型如今是新的 Substring 類型。雖然起初看起來很累贅由於字符串現是一個不一樣的類型,但它在內存可預測性方面給了咱們很大的優點。
爲了不建立許多冗餘拷貝,Swift 字符串使用 「copy on write」 方式只須要在須要時進行拷貝。這意味着子字符串一般與內存中的父字符串共享相同的底層緩衝區。可是在 truncated()
這個例子中,咱們不想在內存中保留整個未截斷的字符串,只是爲了可以使用截斷的子字符串。
經過給咱們一個 Substring 類型,而不是一個完整的 String,Swift 如今 「強制」 咱們在須要時顯式拷貝副本,讓父字符串的內存能夠被釋放。咱們能夠簡單地從截取的子字符串建立一個新的 String ,以下所示:
label.text = String(userInput.truncated())複製代碼
因爲幾乎全部的 Swift 應用和腳本都會處理字符串,因此很高興能看到這些 API 的改進。我認爲新的 API 是在正確性和易用性之間的一個很好的權衡,同時也要求程序員在 copy 時慎重選擇,像 Substring 同樣。
我沒有在這篇文章中介紹的字符串 API 也有更多的進步,好比 Unicode 9 支持更簡單的字符管理,而且可以輕鬆訪問構成字符的底層 Unicode 代碼。
咱們將在即將發佈的後續文章包括 WWDC 中發佈的其餘新的 Swift 4 API 、框架、工具中深刻研究字符串處理和編碼。敬請關注!😉
如何在 Swift 4 中找到新的 String API?String 如今是集合類型真的會讓你的字符串處理更簡單嗎?若是你有相似問題或其餘問題請讓我知道,意見或反饋能夠在這裏評論或 Twitter @johnsundell。
感謝閱讀!🚀