英文版PDF下载地址http://download.csdn.net/detail/tsingheng/7480427
字符串是一组字符的有序序列,比如“hello,china”或者“albatross”。Swfit里字符串用String表示,String也是字符类型Charactar的集合类型。Swift的String和Charactor类型提供了快速的,符合Unicode编码规范的方式来处理文本。创建或者操作的语法都非常轻便易读,跟C的语法也很相似。String链接只需要使用简单的加号,定义成变量还是常量决定了其能否可以改变,这跟其他类型是一样的。
除了简单的语法,Swift的String类型也是一种很高效,很现代的一种字符串实现。所有的字符串被解析成Unicode编码字符,而且支持使用Unicode的各种表示方式来获取。
NOTE Swift的String类型是建立在NSString的基础之上的,如果你使用了Cocoa或者CocoaTouch框架,String除了拥有本章将要介绍的一些特性外还支持NSString的所有api接口。你还可以在任何需要使用NSString对象的地方使用String值。
1.字符串字面值
你可以使用字符串字面值来定义String。字符串字面值是一个由双引号包围的一个固定文本字符串。
字符串字面值可以用来为常量或者变量提供初始值 let someString = "某个字符串字面值";
注意Swift可以推断出来常量someString是String类型,因为我们使用了字符串字面值来给他初始化。字符串字面值可以包含以下特殊字符:
转义的特殊字符,\0(空字符),\\(反斜杠),\t(制表符),\n(换行符),\r(回车符),\"(双引号)和\'(单引号)
单字节Unicode标量,写作\xnn,nn是一个两位的十六进制数
两字节Unicode标量,写作\unnnn,nnnn是一个四位的十六进制数
四字节Unicode标量,写作\Unnnnnnnn,nnnnnnnn是一个八位的十六进制数
下面代码对各种特殊字符都举了例子。常量wiseWords包含两个转义的双引号字符。常量dollarSign,blackHeart和sparklingHeart演示了三种不同的Unicode标量格式:
let wiseWords = "\"Imagination is more important than knowledge\" - Einstein" // "Imagination is more important than knowledge" - Einstein let dollarSign = "\x24" // $, Unicode scalar U+0024 let blackHeart = "\u2665" // ♥, Unicode scalar U+2665 let sparklingHeart = "\U0001F496" // 特殊字符显示不出来, Unicode scalar U+1F4962.初始化一个空的字符串
如果想在开始的时候创建一个空的字符串,后面再慢慢加长,一种方式是使用空字符串字面值来初始化,另一种是调用String的初始化器来初始化。
var emptyString = "" // empty string literal var anotherEmptyString = String() // initializer syntax // these two strings are both empty, and are equivalent to each other你可以通过String的isEmpty属性来查看是否是空字符串:
if emptyString.isEmpty { println("Nothing to see here") } // prints "Nothing to see here"3.字符串可变性
你可以通过把字符串对象赋给常量还是变量来决定他是否可以被修改。
var variableString = "Horse" variableString += " and carriage" // variableString is now "Horse and carriage" let constantString = "Highlander" constantString += " and another Highlander" // this reports a compile-time error - a constant string cannot be modifiedNOTE 这个跟OC里面表示字符串是否可以被修改的方式不一样,OC里是通过使用NSString和NSMutableString来表示的。
4.字符串是值类型
Swift的字符串是一种值类型。如果你创建了一个字符串,并且当做参数传给函数或者方法的时候是赋值一份传递的,或者赋值给其他常量或者变量都是重新复制一份的。在这些情况下都会根据原字符串创建一个新的字符串,传递参数或者赋值的时候使用的都是新创建的字符串。
NOTE 这个特性跟Cocoa的NSString不一样。如果在Cocoa里面你创建一个NSString对象,再传递给函数或者方法或者赋值给其他变量,传递或者赋值的都是这个对象的引用,没有创建新的字符串,除非你显示的说需要。
Swift的这个特性可以保证函数或者方法得到传递过来的字符串后自己就拥有那个字符串了,而不用管这个字符串从哪儿来,而且不用担心这个字符串被别人修改,只有我自己能修改。
在这些场景背后,Swift编译器优化了字符串的使用,只有当确实需要复制的时候才会去复制。也就是说你使用值类型的string的时候总能得到很好的性能。
5.使用字符
Swift的字符串表示了一组字符的有序集合。各个Character字符值表示了一个单独的Unicode。你可以使用for-in遍历获取字符串中各个单独的字符:
for character in "Dog!表情没办法显示" { println(character) } // D // o // g // ! // 表情没办法显示或者还能使用单个字符的字符串字面值来创建一个字符类型常量或变量如 let yenSign: Charactor = "¥"
6.字符计数
如果要查询字符串里面字符的数量,可以调用全局函数countElements并且传递字符串作为参数
let unusualMenagerie = "Koala 表情, Snail <span style="font-family: Arial, Helvetica, sans-serif;">表情</span>, Penguin 表情, Dromedary 表情" println("unusualMenagerie has \(countElements(unusualMenagerie)) characters") // prints "unusualMenagerie has 40 characters"NOTE 对于同一个Unicode字符来说不同的Unicode字符串和不同的表现形式需要的内存大小是不一样的。所以字符串中各个字符所占用的内存是不一样的。所以字符串长度就不能不按顺序遍历各个字符来计算了。如果你使用了特别长的字符串,注意countElements函数会按顺序遍历字符串中的字符来计算字符数量。
还要注意countElements函数返回的结果跟对应的NSString的length属性并不总是相等的。NSString的length属性是基于UTF-16形式的字符串中16位单元的个数,而不是字符串中Unicode字符的数量。Swift的String类型跟NSString的length对应的是utf16count属性。
7.连接字符串和字符
字符串和字符可以使用加号连接组成一个新的字符串
let string1 = "hello" let string2 = " there" let character1: Character = "!" let character2: Character = "?" let stringPlusCharacter = string1 + character1 // equals "hello!" let stringPlusString = string1 + string2 // equals "hello there" let characterPlusString = character1 + string1 // equals "!hello" let characterPlusCharacter = character1 + character2 // equals "!?"
你还可以使用+=运算符将字符串或字符追加到一个已有的字符串变量后面
var instruction = "look over" instruction += string2 // instruction now equals "look over there" var welcome = "good morning" welcome += character1 // welcome now equals "good morning!"NOTE 不能把字符串或字符追加到字符后面哦,因为字符类型只能包含单个字符。
8.字符串填补
字符串填补可以通过在一个字符串字面值中加入混合的常量变量,字面量和表达式来创建新的字符串值。每个加入字符串字面值的对象都要加上一对括号和反斜杠前缀:
let multiplier = 3 let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)" // message is "3 times 2.5 is 7.5"上面资历中multiplier的值被已\(multiplier)的形式插入到字符串字面值当中。当字符串填补计算过以后这个地方将会用multiplier的实际值来代替以创建一个实际的字符串。
在字符串的后面multiplier还是一个表达式的一部分。这个表达式计算Double(multiplier)*2.5的值并且插入结果7.5到字符串中。这里表达式被写作\(Double(multiplier)*2.5)加入字符串字面值中。
NOTE 通过使用这种方式填补进字符串常量的表达式不能包含未经转义的双引号或者反斜杠,也不能包含回车或者换行。
9.字符串比较
Swift提供三种字符串比较方式:相等,前缀相等和后缀相等
相等
如果两个字符串包含相同的字符并且排序也相同,就被认为是相等的。
let quotation = "We're a lot alike, you and I." let sameQuotation = "We're a lot alike, you and I." if quotation == sameQuotation { println("These two strings are considered equal") } // prints "These two strings are considered equal"前缀相等和后缀相等
如果要检查字符串是否有特殊的前缀和后缀,调用字符串的hasPrefix和hasSuffix方法,两个方法都有一个字符串类型参数,返回布尔值。两个方法都对原字符串与前缀字符串或后缀字符串进行一个一个字符的比对。效果应该是和JAVA的startWith和endWidth一样吧。
下面的例子把前两幕罗密欧与朱丽叶的地点作为一个数组:
let romeoAndJuliet = [ "Act 1 Scene 1: Verona, A public place", "Act 1 Scene 2: Capulet's mansion", "Act 1 Scene 3: A room in Capulet's mansion", "Act 1 Scene 4: A street outside Capulet's mansion", "Act 1 Scene 5: The Great Hall in Capulet's mansion", "Act 2 Scene 1: Outside Capulet's mansion", "Act 2 Scene 2: Capulet's orchard", "Act 2 Scene 3: Outside Friar Lawrence's cell", "Act 2 Scene 4: A street in Verona", "Act 2 Scene 5: Capulet's mansion", "Act 2 Scene 6: Friar Lawrence's cell" ]你可以对remeoAndJuliet数组使用hasPrefix方法来计算第一幕有几场
var act1SceneCount = 0 for scene in romeoAndJuliet { if scene.hasPrefix("Act 1 ") { ++act1SceneCount } } println("There are \(act1SceneCount) scenes in Act 1") // prints "There are 5 scenes in Act 1"同样的道理可以使用hasSuffix来计算有几场在Capulets mansion和Lawrence's cell附近拍摄
var mansionCount = 0 var cellCount = 0 for scene in romeoAndJuliet { if scene.hasSuffix("Capulet's mansion") { ++mansionCount } else if scene.hasSuffix("Friar Lawrence's cell") { ++cellCount } } println("\(mansionCount) mansion scenes; \(cellCount) cell scenes") // prints "6 mansion scenes; 2 cell scenes"10.字符串字母大小写转换
你可以通过字符串的uppercaseString和lowercaseString属性来获得相应的大写或者小写版本:
let normal = "Could you help me, please?" let shouty = normal.uppercaseString // shouty is equal to "COULD YOU HELP ME, PLEASE?" let whispered = normal.lowercaseString // whispered is equal to "could you help me, please?"11.Unicode
Unicode是一种编码和表示文本的国际标准。他可以让你使用一种标准的形式表示任何语言的任何字符,从外部资源例如文本文件或者web页面读或者写这些字符。
Swift的字符串和字符类型都是完全兼容Unicode标准的。他们支持几种不同的Unicode编码。
Unicode术语
在Unicode中每一个字符可以被表示未一个或多个unicode标量。一个Unicode标量是一个对应字符或表情的唯一的21位数字,比如U+0016对应小写拉丁字母a,或者U+1F425代表表情符号xxx。
当一个Unicode字符串被写入文本文件或者其他方式存储的时候,这些unicode标量被一种Unicode格式编码。每种格式将字符串编码成块,也就是代码单元。这些格式包括UTF-8格式(使用8位代码单元编码字符串),UTF-16格式(使用16位代码单元编码字符串)。
字符串的Unicode表示法
Swift提供了几种不同的方式来使用字符串的Unicode表示法。
你可以使用for-in语句遍历字符串的各个字符作为Unicode字符。
或者,可以通过以下三种之一的其他Unicode兼容表示法来获取字符串。
UTF-8代码单元集合(通过字符串的utf8属性)
UTF-16代码单元集合(通过字符串的utf16属性)
21位Unicode标量值集合(通过字符串的unicodeScalars属性)
下面例子列举了各种不同的表示法,字符串由字符D,o,g,!,和表情狗狗字符(这里显示不了。Unicode标量U+1f436)
let dogString = "Dog!狗狗";
UTF-8
你可以通过遍历字符串的utf8属性来获取UFT-8表示法。这个属性返回的是UTF8View类型,是UInt8值的集合。字符串里面各个字节表示如下:
for codeUnit in dogString.utf8 { print("\(codeUnit) ") } print("\n") // 68 111 103 33 240 159 144 182上面例子前四个数字codeUnit值是68,111,103,33表示了字符D,o,g,和!,这些字符的UTF-8表示与ASCII表示是一样的。最后四个codeUnit值是240,159,144,182是狗狗表情字符的四字节的表示。
你可以通过遍历字符串的utf16属性来获取UTF16表示法。这个属性返回的是UTF16View类型,是UInt16值的集合。字符串里面各个字节表示如下:
for codeUnit in dogString.utf16 { print("\(codeUnit) ") } print("\n") // 68 111 103 33 55357 56374前四个数字还是一样的,68,111,103,33,表示了字符D,o,g,!。这些字符的UTF-16代码单元和UTF-8表示法是一样的。
最后两个值是55357和56374是狗狗表情字符的UTF-16表示。分别代表了值U+D83D和U+DC36。
Unicode标量
你可以通过遍历字符串的unicodeScalars属性来获取Unicode标量表示。这个属性返回的结果是UnicodeScalarView类型,是UnicodeScalar值的集合。UnicodeScalar是任何21位非前替换或者后替换的代码。
各个UnicodeScalar有一个可以返回自己21位置的属性value,结果使用UInt32值来表示。
for scalar in dogString.unicodeScalars { print("\(scalar.value) ") } print("\n") // 68 111 103 33 128054前四个value属性设置都还是68,111,103,33。最后一个128054是十六进制数1F436,正好就是狗狗表情字符的Unicode标量U+1F436。
还有另外一种可以获取UnicodeScalar的value属性的方式,就是使用这个字符来创建新的字符串值,比如字符串填补:
for scalar in dogString.unicodeScalars { println("\(scalar) ") } // D // o // g // ! // 狗狗表情本章完。下章地址: 6.集合属性