String 是我们最常用到的语言元素,swift中的String初看起来相当简洁、易用(官方教程),真正大量使用时,却有点摸不着头脑。 第一、String.Index的概念让人费解,不知道它是如何构造出来的,Range<String.Index>就更奇怪了。第二、swift标准库中的方法很少,习惯了NSString中那些强大的功能,难免就要用一下bridge,而两者又有一些不能匹配的东西。 直到看完了这篇文章(
http://oleb.net/blog/2014/07/swift-strings/),才算真正的明白了String的奥妙之处。
这篇文章讲的更好:https://developer.apple.com/swift/blog/?id=30
Character
swift中的Character是个奇怪的东西,它是个perceived character,或者说是个grapheme cluster。没有找到合适的中文解释。
举例说明:
这个字符串是
café,
\u{E9}就是最后一个字符
é
这个字符串也是
café,
\u{301}是最后一个字符的上标注
再看一个例子,韩文中的
한字(由三个韩文字符拼成):
对于用户来讲,这两个Character也是完全一样的。都会打印出
한
因为,多个unicode code point可以组合出一个字符,swift的字符串就利用这个特性,向右寻找最大的组合形成一个Character。
String
String就是一堆Character的集合。每个Character所占用的内存空间不定,注定了String不能用普通的数组来存储内容,实际用的是双向链表。
String.Index
既然String是个双向链表,那么,访问其中的某个元素,或者substring,就要用指针了。 就是Index。
startIndex 相当于链表的 head指针, endIndex相当于tail指针。
有个全局函数可以方便指针操作: advance
advance(s.startIndex,3)
实际上就是调用了3次 successor
String 与 NSString 的自动桥接
只要 import Foundation,NSString的
大部分功能都可以被String直接使用,而且,不需要做显式类型转换。 为什么说是大部分功能呢? 因为它们的存储方法不同,NSString的随机访问功能无法支持,例如:characterAtIndex:。若要使用这个功能,必须显示转换成NSString类型。
NSRange 和 Range<String.Index>
NSString中对于字符串区间,可以用NSRange来表示,而String用的是Range<String.Index>。 对于后者,乍一看有点奇怪,其实它就是一个起始指针加上一个偏移量。因为String.Index本质上是一个指针,那么,字符串a的Index对于字符串b就没有任何意义,这一点需要注意。
参考文档:
详细的概念阐述,精辟!
swift 标准库中的 String 参考手册:
一些简单又好玩儿的例子: