如何不再害怕弃用并爱上 Swift 中的 slicing
如果你曾经用 Swift 写过代码,并试图截取字符串的一部分,你很可能遇到过这个令人恐慌的消息:'substring(to:)' is deprecated: Please use String slicing subscript with a 'partial range from' operator。听起来像是一纸判决?实际上,这是邀请你进入一个更安全、更强大的字符串处理新世界。让我们来弄清楚发生了什么,为什么 Apple 决定改变我们熟悉的 API,以及现在如何在 Swift 4 及更高版本中正确地“切割”字符串。
为什么 substring 成为了过去式?
过去好用的 substring(to:) 虽然能工作,但……并不太聪明。它返回一个新的 Substring 对象,本质上只是原始字符串的一个“窗口”。这导致了混淆:你以为自己在操作一个独立的字符串,但实际上你持有的是对旧内存的引用。在 Swift 4 中,他们决定整顿秩序:现在所有子字符串操作都返回 Substring 类型,要获得完整的字符串,需要显式转换结果。听起来更复杂了?实际上,这更清晰、更安全。
认识一下:String slicing subscript
新方法使用下标(subscripts)和范围(ranges)。不再使用 substring(to:)、substring(from:) 和 substring(with:) 方法,你现在编写的代码看起来就像操作数组一样。以下是一个基本类比:
let fullString = "Привет, мир!"// 旧方法(已弃用)// let oldResult = fullString.substring(to: fullString.index(fullString.startIndex, offsetBy: 6))
// 新方法let newResult = fullString[..<fullString.index(fullString.startIndex, offsetBy: 6)]print(newResult) // "Привет"看到 ..< 运算符了吗?这就是所谓的partial range from operator——一个从开头到指定索引(不包含该索引)的部分范围。很强大,对吧?
新方法的三大支柱:from, to, through
让我们分解一下以前由 substring 方法覆盖的三个主要场景。
1. substring(to:) → prefix(upTo:) 或部分范围
想获取到某个索引之前的所有内容?使用 ..<(半开范围)或 prefix(upTo:) 方法:
let str = "Hello, Swift"let index = str.firstIndex(of: ",") ?? str.endIndex
// 通过下标的方式let result1 = str[..<index]print(result1) // "Hello"
// 通过方法的方式let result2 = str.prefix(upTo: index)print(result2) // "Hello"2. substring(from:) → suffix(from:) 或部分范围
需要获取从某个索引到结尾的所有内容?使用省略了起始位置的 ...(闭区间范围):
let startIndex = str.index(str.startIndex, offsetBy: 7)let result3 = str[startIndex...]print(result3) // "Swift"
// 或者通过方法let result4 = str.suffix(from: startIndex)print(result4) // "Swift"3. substring(with:) → 普通范围
想截取特定的一段?直接指定一个范围:
let range = str.index(str.startIndex, offsetBy: 7)..<str.endIndexlet result5 = str[range]print(result5) // "Swift"
// 或者通过闭区间范围let closedRange = str.index(str.startIndex, offsetBy: 7)...str.index(before: str.endIndex)let result6 = str[closedRange]print(result6) // "Swift"请注意:所有这些操作都返回 Substring,而不是 String。如果你需要一个完整的字符串,只需将结果包装在 String() 中:
let newString = String(result1)print(type(of: newString)) // String那 prefix 和 suffix 呢?它们没有被弃用!
是的,prefix(_:)、suffix