当你从一个字符串中获取了一个子字符串,比如使用下标或者prefix(_:)方法,那么结果是一个Substring的实例,而不是另外一个字符串。Swift中的Substring拥有差不多和String一样的方法,所以你可以像操作字符串一样操作Substring。和字符串不一样,只有局限在操作字符串的短暂时间里面会使用子字符串。当你准备把结果保存下来后续使用,需要把子字符串的实例转换成字符串的实例。例如:
let greeting = "Hello, world!"
let index = greeting.index(of: ",") ?? greeting.endIndex
let beginning = greeting[..<index]
// beginning is "Hello"
// Convert the result to a String for long-term storage.
let newString = String(beginning)
和字符串一样,每一个字符串都拥有一段内存,用来保存组成子字符串的字符。字符串和子字符串不同的地方在于对性能的优化,子字符串可以重用原字符串的内存空间,或者部分的空间去存储其他的子字符串。字符串也有相似的优化,如果2个字符串共享内存空间,那么它们是相等的。这个优化意味着你不需要为拷贝内存付出性能的代价,除非你改变了字符串或者子字符串。如上所述,子字符串不合适长时间的保存,因为它们会重用原字符串的内存,那么只要有子字符串正在被使用,整个原字符串就必须要常驻在内存中。
上面的例子中,greeting是一个字符串,所以他有自己的内存空间来保存其中的字符。beginning是greeting的子字符串,他重用了greeting的内存。相反,newString是一个通过子字符串创建而成字符串,他拥有自己的存储空间。下图表示出了它们之间的关系:
NOTE:String和Substring都实现了协议StringProtocol,也就是说通过接受一个实现了StringProtocol的协议的值来操作字符串或者子字符串会很方便。字符串和子字符串都可以调用这些方法。