Swift 字符串和字符

2021-11-26 11:17:45 浏览数 (1)

目录

  1. 字符串字面量
  2. 初始化空字符串
  3. 字符串可变性
  4. 字符串是值类型
  5. 使用字符(Characters)
  6. 计算字符数量
  7. 连接字符串和字符
  8. 字符串插值
  9. 比较字符串
  10. 大写和小写字符串

介绍

Swift 字符串通过 String 类型来表示,也可以表示为 Character 类型值的集合。

Swift 的 String 和 Character 类型提供了一个快速的,兼容 Unicode 的方式来处理代码中的文本信息。

字符串连接操作只需要简单地通过 号将两个字符串相连即可。与 Swift 中其他值一样,能否更改字符串的值,取决于其被定义为常量还是变量。

Swift 的 String 类型与 OC 的 Foundation NSString 类进行了无缝桥接。可以在任意要求传入 NSString 实例作为参数的 API 中使用 String 类型的值进行替换。

1. 字符串字面量

字符串字面量是由双引号包裹着的具有固定顺序的文本字符。字符串字面量可以用于为常量和变量提供初始值。

代码语言:javascript复制
// 字符串字面量
let someString = "Some string literal value"

someString 常量通过字符串字面量进行初始化,Swift 因此推断其为 String 类型。

2. 初始化空字符串

为了构造一个很长的字符串,可以创建一个空字符串作为初始值。可以将空的字符串字面量赋值给变量,也可以初始化一个新的 String 实例:

代码语言:javascript复制
// 初始化空字符串
var emptyString = ""
var anotherEmptyString = String()
// 这两个字符串都为空,并且两者等价

可以通过检查其 Boolean 类型的 isEmpty 属性来判断该字符串是否为空:

代码语言:javascript复制
// 打印 "Nothing to see here"
if emptyString.isEmpty {
    print("Nothing to see here")
}

3. 字符串可变性

通过将一个特定字符串分配给一个变量(对其进行修改)或者常量(保证其不会被修改)来指定该字符串是否可以被修改:

代码语言:javascript复制
var variableString = "Horse"
variableString  = " and carriage"
// variableString 现在为 "Horse and carriage"
let constantString = "Highlander"
constantString  = " and another Highlander"
// 这会报告一个编译错误(compile-time error) - 常量不可以被修改。

在 OC 和 Cocoa 中,通过选择两个不同的类 ( NSString 和NSMutableString )来指定该字符串是否可以被修改,Swift 中的字符串是否可以修改仅通过定义的是变量还是常量来决定,实现了多种类型可变性操作的统一。

4. 字符串是值类型

Swift 的 String 类型是值类型。如果创建了一个新的字符串值,那么当其进行常量、变量赋值操作或在函数/方法中传递时,会进行值拷贝。在不同情况下,都会对已有字符串值创建新副本,并对该新副本进行传递或赋值。

和 OC 中的 NSString 不同,在 OC 中创建了一个 NSString 实例,并将其传递给一个函数/方法,或者赋给一个变量,永远都是传递或赋值同一个NSString 实例的一个引用。除非特别要求其进行值拷贝,否则字符串不会进行赋值新副本操作。

Swift 默认字符串拷贝的方式保证了在函数/方法中传递的是字符串的值,其明确独有该字符串的值,无论它来自哪里。你可以放心传递的字符串本身不会被改,除非是自己更改它。

在实际编译时,Swift 编译器会优化字符串的使用,使实际的复制只发生在绝对必要的情况下,这意味着你始终可以将字符串作为值类型的同时获得极高的性能。

5. 使用字符(Characters)

Swift 的 String 类型表示特定序列的字符值的集合。每一个字符值代表一个 Unicode 字符。你可利用 for-in 循环来遍历字符串中的每一个字符:

代码语言:javascript复制
for character in "Dog!????" {
    print(character)
}
// D
// o
// g
// !
// ?
// ?
// ?
// ?

另外,通过标明一个 Character 类型注解并通过字符字面量进行赋值,可以建立一个独立的字符常量或变量:

代码语言:javascript复制
let yenSign: Character = "¥"

6. 计算字符数量

通过 count 属性可以获取该字符串的字符数量。

代码语言:javascript复制
let unusualMenagerie = "Koala ????, Snail ????, Penguin ????, Dromedary ????"
print("unusualMenagerie has (unusualMenagerie.count) characters")
// unusualMenagerie has 52 characters

7. 连接字符串和字符

字符串和字符的值可以通过加法运算符 ( ) 相加在一起并创建一个新的字符串值:

代码语言:javascript复制
let string1 = "hello"
let string2 = " there"
let character1: Character = "!"
let character2: Character = "?"

let stringPlusCharacter = string1   "(character1)"
// 等于 "hello!"
let stringPlusString = string1   string2
// 等于 "hello there"
let characterPlusString = "(character1)"   string1
// 等 于 "!hello"
let characterPlusCharacter = "(character1)"   "(character2)"
// 等于 "!?"

8. 字符串插值

字符串插值是一种全新的构建字符串的方式,可以在其中包含常量、变量、字面量和表达式。你插入的字符串字面量的每一项都被包裹在以反斜线为前缀的圆括号中:

代码语言:javascript复制
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) 并包含在字符串字面量中。

你插值字符串中写在括号中的表达式不能包含非转义双引号 (") 和反斜杠 (),

并且不能包含回车或换行符。

9. 比较字符串

Swift 提供了三种方式来比较字符串的值:字符串相等,前缀相等和后缀相等。

字符串相等

如果两个字符串以同一顺序包含完全相同的字符,则认为两者字符串相等:

代码语言:javascript复制
let quotation = "We're a lot alike, you and I."
let sameQuotation = "We're a lot alike, you and I."
if quotation == sameQuotation {
    print("These two strings are considered equal")
}
// prints "These two strings are considered equal"

前缀/后缀相等

通过调用字符串的 hasPrefix/hasSuffix 方法来检查字符串是否拥有特定前缀/后缀。两个方法均需要以字符串作为参数传入并返回 Boolean 值。两个方法均执行基本字符串和前缀/后缀字符串之间逐个字符的比较操作。

下面的例子以一个字符串数组表示:

代码语言:javascript复制
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"
]

你可以利用 hasPrefix 方法使用 romeoAndJuliet 数组来计算话剧中第一幕的场景数:

代码语言:javascript复制
var act1SceneCount = 0
for scene in romeoAndJuliet {
    if scene.hasPrefix("Act 1 ") {
        act1SceneCount  = 1
    }
}
print("There are (act1SceneCount) scenes in Act 1")
// prints "There are 5 scenes in Act 1"

同样,可使用 hasSuffix 方法来计算发生在 Capulet 公馆和 Lawrence 牢房内以及周围的场景数。

代码语言:javascript复制
var mansionCount = 0
var cellCount = 0
for scene in romeoAndJuliet {
    if scene.hasSuffix("Capulet's mansion") {
        mansionCount  = 1
    }  else if scene.hasSuffix("Friar Lawrence's cell") {
        cellCount  = 1
    }
}
print("(mansionCount) mansion scenes; (cellCount) cell scenes")
// prints "6 mansion scenes; 2 cell scenes"

10. 大写和小写字符串

你可以通过字符串的 uppercaseString 和 lowercaseString 属性来访问一个字符串的大写/小写版本。

代码语言:javascript复制
let normal = "Could you help me, please?"
let shouty = normal.uppercased()
// shouty 值为 "COULD YOU HELP ME, PLEASE?"
let whispered = normal.lowercased()
// whispered 值为 "could you help me, please?"

0 人点赞