以下所有示例均使用
var str = "Hello, playground"
斯威夫特4
在Swift 4中,字符串得到了很大的改进。当您现在从字符串中获得了一些子字符串时,您将得到一个Substring
返回的类型,而不是String
。为什么是这样?字符串是Swift中的值类型。这意味着,如果您使用一个String来创建一个新的String,则必须将其复制过来。这有利于稳定(在您不知情的情况下,没有其他人会改变它),但不利于效率。
另一方面,子字符串是对原始字符串的引用。这是文档中的图像说明了这一点。
无需复制,因此使用效率更高。但是,假设您从一百万个字符的字符串中得到了十个字符的子字符串。因为子字符串引用了字符串,所以只要子字符串存在,系统就必须保留整个字符串。因此,无论何时完成操作子字符串,都将其转换为字符串。
let myString = String(mySubstring)
这将只复制子字符串,并且可以回收保存旧String的内存。子字符串(作为一种类型)意味着寿命很短。
Swift 4的另一个重大改进是(再次),Strings是Collections。这意味着无论您对集合执行什么操作,都可以对字符串进行操作(使用下标,遍历字符,过滤器等)。
以下示例说明如何在Swift中获取子字符串。
获取子字符串
您可以使用标或一些其他的方法(例如,获得一个字符串的子串prefix
,suffix
,split
)。不过,您仍然需要使用String.Index
而不是Int
范围的索引。(如果需要帮助,请参阅我的其他答案。)
字符串的开头
您可以使用下标(请注意Swift 4的单面范围):
let index = str.index(str.startIndex, offsetBy: 5)
let mySubstring = str[..<index] // Hello
或prefix
:
let index = str.index(str.startIndex, offsetBy: 5)
let mySubstring = str.prefix(upTo: index) // Hello
甚至更简单:
let mySubstring = str.prefix(5) // Hello
字符串结尾
使用下标:
let index = str.index(str.endIndex, offsetBy: -10)
let mySubstring = str[index...] // playground
或suffix
:
let index = str.index(str.endIndex, offsetBy: -10)
let mySubstring = str.suffix(from: index) // playground
甚至更简单:
let mySubstring = str.suffix(10) // playground
请注意,在使用时,suffix(from: index)
我必须使用从头算起-10
。仅使用时suffix(x)
,这是不必要的,它只接受x
String 的最后一个字符。
字符串范围
同样,我们在这里仅使用下标。
let start = str.index(str.startIndex, offsetBy: 7)
let end = str.index(str.endIndex, offsetBy: -6)
let range = start..<end
let mySubstring = str[range] // play
转换Substring
为String
别忘了,当您准备保存子字符串时,应该将其转换为a,String
以便可以清理旧字符串的内存。
let myString = String(mySubstring)
使用Int
索引扩展名?
Int
在阅读了Airspeed Velocity和Ole Begemann 的文章Swift 3中的字符串后,我犹豫使用基于索引的扩展名。尽管在Swift 4中,字符串是集合,但是Swift团队故意没有使用Int
索引。它仍然是String.Index
。这与由不同数量的Unicode代码点组成的Swift字符有关。必须为每个字符串唯一地计算实际索引。
我必须说,我希望Swift小组String.Index
将来能找到一种抽象的方法。但是直到他们我选择使用他们的API。它可以帮助我记住String操作不只是简单的Int
索引查找。