Swift 的 Standard Library 提供豐富的功能,而你可以透過匯入外部函式庫和框架,使用更多額外的功能。 這些模組可能直接來自 Swift 專案(例如 Swift Argument Parser)、來自 Apple 平台框架(例如 Foundation 和 Network Framework),或來自第三方開源函式庫(例如 SwiftyBeaver)。
像 Foundation 這類核心模組,也就是 Swift 中最廣泛使用的函式庫之一,會隨 Swift 工具鏈一起提供。 第三方函式庫必須先加入專案設定(例如使用 Swift Package Manager),才能匯入。
匯入模組的方式是寫下import關鍵字,後面接著模組名稱。
所以只要在程式裡加入以下內容,就能匯入 Foundation。
import Foundation
匯入模組後,你的程式碼就能使用它的型別、方法和函式。
例如,匯入 Foundation 會為String增加像components(separatedBy:)這樣實用的工具方法。
按照慣例,import敘述會放在 Swift 檔案的開頭,讓任何閱讀程式碼的人都能馬上看到相依項目。
String中的個別字元可以像陣列一樣,使用下標取值的方式來存取。
不過,字串使用的索引並_不是_整數,無法直接操作。
而是必須根據其他已知的索引計算出來,例如startIndex,它指向非空字串中第一個字元的位置,而且要用 String 和 NSString 函式庫提供的方法(匯入Foundation模組後,Swift 的字串就能使用所有 NSString 的屬性和方法)。
例如,假設有下列字串:
let csv = "apple,pear,peach,orange,cherry,lime,goosberry"
你無法寫csv[21]來取得「orange」裡的「g」,必須改為計算一個String.Index型別的值,並以該索引取代。
注意,這些索引本身並不是設計給人直接閱讀的。
它們就是所謂的_不透明索引_,因為人類不需要知道裡面是什麼。
let index = csv.index(csv.startIndex, offsetBy: 21)
csv[index]
// "g"
print(index)
// prints Index(_rawBits: 1376513)
不過要注意,如果偏移量不是有效的索引,也就是說,如果算出來的索引在startIndex之前或endIndex之後,這個操作就會引發錯誤,導致程式崩潰。
為了避免這個問題,你可以指定一個限制索引。
這會回傳一個可選的索引,對於原本無效的索引則會回傳 nil。
let tooFar = csv.index(csv.startIndex, offsetBy: 200)
// error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0).
let tooFarButSafe = csv.index(csv.startIndex, offsetBy: 200, limitedBy: csv.endIndex)
// nil
此外,索引不能在不同字串之間共用。
例如,用上面算出的「orange」中「g」的index去索引字串fam = "This is my family: 👨👩👦👦, this is our dog: 🐶, this is our cat: 🐱!",也就是fam[index],會讓程式崩潰。
這一切背後有很多原因,但基本上都歸結為一句話:「Unicode 很棘手」。
一般來說,如果你需要隨機存取個別字元,你大概應該改用其他資料結構,例如Array<Character>。
Swift 有first和last兩個方法,可以取得字串的第一個和最後一個字元。
這些方法會回傳可選的字元,所以如果字串是空的,就會回傳 nil。
let str = "Hello, world!"
print(str.first) // Prints Optional("H")
print(str.last) // Prints Optional("!")
你也可以用prefix和suffix方法取得字串的子字串。
這些方法接受一個整數作為引數,並回傳包含字串前 n 個或後 n 個字元的子字串。
let str = "Hello, world!"
print(str.prefix(5)) // Prints "Hello"
print(str.suffix(6)) // Prints "world!"
處理文字是程式設計中常見的工作。 Swift 與 Foundation 框架提供了許多方便的方法和屬性,用來檢視、轉換和操作字串。
components(separatedBy:)分割字串要根據分隔符號把字串分割成子字串陣列,請使用components(separatedBy:)(需要匯入 Foundation):
import Foundation
let sentence = "Hello, world!"
let words = sentence.components(separatedBy: " ")
print(words) // Prints ["Hello,", "world!"]
hasPrefix(_:)和hasSuffix(_:)檢查前綴和後綴要檢查字串是否以特定的字元序列開頭或結尾,請使用hasPrefix(_:)和hasSuffix(_:):
let greeting = "Hello, world!"
print(greeting.hasPrefix("Hello")) // Prints true
print(greeting.hasSuffix("world!")) // Prints true
你可以用這些標準方法和屬性來轉換字串的大小寫:
lowercased():回傳字串的小寫副本。uppercased():回傳字串的大寫副本。capitalized:回傳每個單字首字母大寫的副本(來自 Foundation)。let greeting = "hello, world!"
print(greeting.lowercased()) // Prints "hello, world!"
print(greeting.uppercased()) // Prints "HELLO, WORLD!"
print(greeting.capitalized) // Prints "Hello, World!"
replacingOccurrences(of:with:)取代子字串要用另一個字串取代目標子字串的所有出現處,請使用replacingOccurrences(of:with:)(來自 Foundation):
let greeting = "Hello, world!"
let updated = greeting.replacingOccurrences(of: "world", with: "Swift")
print(updated) // Prints "Hello, Swift!"
joined(separator:)連接字串joined(separator:)方法屬於字串的集合,例如[String]。
它會用分隔符號把元素連接成單一字串:
let words = ["Hello", "world"]
let sentence = words.joined(separator: ", ")
print(sentence) // Prints "Hello, world"
鎮上新開了一間詩社,你正考慮參加。 因為過去發生過一些狀況,這間詩社有著一套非常特別的入場規定,你得在嘗試進門之前先摸清楚。
詩社有兩扇門,兩扇都有人把守。 為了進場,你得先推理出當天的密碼:
你首先要做的,是把這首詩拆成個別的行。 警衛會朗誦一首詩,而你得把它拆成一行一行。
實作splitOnNewlines函式,它接受一個字串,並以換行字元為分隔符號,將它拆成字串陣列。
這個函式應該回傳一個字串陣列,其中每個字串都是這首詩的其中一行。
splitOnNewlines("Hello.\nHow are you?\n\nI'm doing fine.")
// returns ["Hello." ,"How are you?", "", "I'm doing fine"].
_代替。舉例來說,他們最喜歡的作家之一是 Michael Lockwood,他寫了下面這首_藏頭詩_,意思是每個句子的第一個字母會組成一個單字:
Stands so high
Huge hooves too
Impatiently waits for
Reins and harness
Eager to leave
當警衛朗誦這首詩時,你會把它拆成個別的行,並以每一行的第一個字母作答,也就是["S", "H", "I", "R", "E"]。
接著,警衛會把你回覆的字母陣列所組成的單字交給你,要你把它變成首字母大寫的形式。
最後你回傳的密碼是"SHIRE",就能進去了。
實作frontDoorPassword函式,它接受一個代表這首詩的字串。
這個函式應該回傳你會告訴警衛的密碼。
frontDoorPassword("Stands so high\nHuge hooves too\nImpatiently waits for\nReins and harness\nEager to leave")
// returns "SHIRE"
在詩社的後方,你會遇到最有名的詩人,那裡就像是貴賓區。 因為這不是人人都能進的,後門的流程稍微複雜一點。
", please"。舉例來說,前面提到的那首詩同時也是_藏尾詩_,意思是每個句子的最後一個字母會組成一個單字:
Stands so high
Huge hooves too
Impatiently waits for
Reins and harness
Eager to leave
當警衛朗誦這首詩時,你會把它拆成個別的行、去掉行尾的空白,並以每一行的第一個字母作答,也就是["h", "o", "r", "s", "e"]。
接著,警衛會把你回覆的字母陣列所組成的單字交給你,要你把它變成首字母大寫的形式,並在後面加上", please"。
最後你回傳的密碼是"horse, please",就能進去了。
實作backDoorPassword函式,它接受一個代表這首詩的字串。
這個函式應該回傳你會告訴警衛的密碼。
backDoorPassword("Stands so high\nHuge hooves too\nImpatiently waits for\nReins and harness\nEager to leave")
// returns "horse, please"
詩社的後室裡還有另一扇門,通往只有最頂尖的詩人才能進入的密室。
"!"。舉例來說,前面提到的那首詩經過修改後,就符合這個模式:
Stands so high
Huge hooves too
Impatiently waits for
Rider with harness
Eager to leave
當警衛朗誦這首詩時,你會把它拆成個別的行、去掉行尾的空白,並以每一行的第 ith 個字母作答,也就是 ["S", "u", "p", "e", "r"]。
接著,警衛會把你回覆的字母陣列所組成的單字交給你,要你把它變成全大寫的形式,並在後面加上"!"。
最後你回傳的密碼是SUPER!,就能進去了。
實作secretRoomPassword函式,它接受一個代表這首詩的字串。
這個函式應該回傳你會告訴警衛的密碼。
secretRoomPassword("Stands so high\nHuge hooves too\nImpatiently waits for\nRider with harness\nEager to leave")
// returns "SUPER!"