Swift-字符串和字符

Swift的String类型是用Foundation的NSString类来桥接的。 Foundation还扩展了String以公开NSString定义的方法。 这意味着,如果您导入Foundation,则可以在String上访问这些NSString方法,而不进行转换。

初始化字符串

var emptyString = ""               // empty string literal
var anotherEmptyString = String()  // initializer syntax
// these two strings are both empty, and are equivalent to each other

判断字符串是否为空

if emptyString.isEmpty {
    print("Nothing to see here")
}
// Prints "Nothing to see here"

可变字符串

您可以指定特定的字符串是否可以通过将其赋值给变量(在这种情况下可以修改)或常量(在这种情况下不能修改)来决定是否修改(或改变):

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 modified

这种方法不同于Objective-C和Cocoa中的字符串变量,您可以在两个类(NSString和NSMutableString)之间进行选择,以指示字符串是否可以进行改变。

字符串是值类型

Swift的String类型是一个值类型。 如果创建一个新的字符串值,那么该字符串值在传递给函数或方法时或者在赋给常量或变量时被复制。 在每种情况下,将创建现有String值的新副本,并传递或分配新副本,而不是原始版本。
Swift的按默认值复制String的行为确保当一个函数或方法传递一个String值时,很明显你拥有该精确的String值,而不管它来自哪里。 您可以确信,您传递的字符串不会被修改,除非您自己修改它。

字符

您可以通过使用for-in循环遍历其字符属性来访问字符串的各个字符值:

for character in "Dog!🐶".characters {
    print(character)
}
// D
// o
// g
// !
// 🐶

或者,您可以通过提供字符类型注释,从单字符字符串文字创建独立的字符常量或变量:

let exclamationMark: Character = "!"

可以通过将字符值数组作为参数传递给它的初始化器来构造字符串值:

let catCharacters: [Character] = ["C", "a", "t", "!", "🐱"]
let catString = String(catCharacters)
print(catString)
// Prints "Cat!🐱"

拼接字符串和字符

字符串值可用加法运算符(+)一起添加(或连接),以创建新的字符串值:

let string1 = "hello"
let string2 = " there"
var welcome = string1 + string2
// welcome now equals "hello there"

您还可以使用附加赋值运算符(+ =)将String值附加到现有的String变量:

var instruction = "look over"
instruction += string2
// instruction now equals "look over there"

您可以使用String类的append()方法将Character值拼接到String变量:

let exclamationMark: Character = "!"
welcome.append(exclamationMark)
// welcome now equals "hello there!"

注意:您不能将字符串或字符附加到现有的字符变量,因为字符值只能包含一个字符。

字符串插入

字符串插值是通过将常量,变量,文字和表达式的值包含在字符串文字中来从常量,变量,文字和表达式的混合构造新的String值的一种方法。 您插入到字符串文字中的每个项都包含在一对括号中,前缀为反斜杠:

let multiplier = 3
let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"
// message is "3 times 2.5 is 7.5"

在插入字符串中的括号内写入的表达式不能包含未转义的反斜杠(\),回车或换行符。 但是,它们可以包含其他字符串文字。

字符串字面量中的特殊字符

字符串文字可以包含以下特殊字符:

  • 转义的特殊字符\ 0(空字符),\(反斜杠),\ t(水平制表符),\ n(换行),\ r(回车) )
  • 任意Unicode标量,写为\ u {n},其中n是一个1-8位的十六进制数,值等于有效的Unicode代码点
let wiseWords = "\"Imagination is more important than knowledge\" - Einstein"
// "Imagination is more important than knowledge" - Einstein
let dollarSign = "\u{24}" // $, Unicode scalar U+0024
let blackHeart = "\u{2665}" // ♥, Unicode scalar U+2665
let sparklingHeart = "\u{1F496}" // 💖, Unicode scalar U+1F496

计数字符

要检索字符串中的字符值的计数,请使用字符串的characters属性的count属性:

let unusualMenagerie = "Koala 🐨, Snail 🐌, Penguin 🐧, Dromedary 🐪"
print("unusualMenagerie has \(unusualMenagerie.characters.count) characters")
// Prints "unusualMenagerie has 40 characters"

访问和修改字符串

  • 您可以通过其方法和属性或通过使用下标语法来访问和修改字符串。
  • 每个String值都有一个相关的索引类型String.Index,它对应于字符串中每个字符的位置。
  • 如上所述,不同的字符可能需要不同数量的内存来存储,因此为了确定哪个字符在特定位置,您必须从该字符串的开头或结尾遍历每个Unicode标量。 因此,Swift字符串不能用整数值索引。
  • 使用startIndex属性访问字符串的第一个字符的位置。 endIndex属性是字符串中最后一个字符之后的位置。 因此,endIndex属性不是字符串下标的有效参数。 如果String为空,startIndex和endIndex相等。
  • 使用String的index(before :)和index(after :)方法之前,可以访问给定索引前后的索引。 要访问远离给定索引的索引,可以使用索引(_:offsetBy :)方法,而不是多次调用这些方法。
  • 您可以使用下标语法来访问特定String索引处的字符。
let greeting = "Guten Tag!"
greeting[greeting.startIndex]
// G
greeting[greeting.index(before: greeting.endIndex)]
// !
greeting[greeting.index(after: greeting.startIndex)]
// u
let index = greeting.index(greeting.startIndex, offsetBy: 7)
greeting[index]
// a

使用characters属性的indices属性访问字符串中各个字符的所有索引。

for index in greeting.characters.indices {
    print("\(greeting[index]) ", terminator: "")
}
// Prints "G u t e n   T a g ! "

注意:您可以在符合Collection协议的任何类型上使用startIndex和endIndex属性和索引(before :),index(after :)和index(_:offsetBy :)方法。 这包括String,如下所示,以及集合类型,如Array,Dictionary和Set。

插入和删除

要在指定索引处将单个字符插入到字符串中,请使用insert(_:at :)方法,并在指定索引处插入另一个字符串的内容,请使用insert(contents Of:a :)方法。

var welcome = "hello"
welcome.insert("!", at: welcome.endIndex)
// welcome now equals "hello!"

welcome.insert(contentsOf:" there".characters, at: welcome.index(before: welcome.endIndex))
// welcome now equals "hello there!"

要从指定索引的字符串中删除单个字符,请使用remove(at :)方法,并删除指定范围内的子字符串,请使用removeSubrange(_ :)方法:

welcome.remove(at: welcome.index(before: welcome.endIndex))
// welcome now equals "hello there"

let range = welcome.index(welcome.endIndex, offsetBy: -6)..<welcome.endIndex
welcome.removeSubrange(range)
// welcome now equals "hello"

注意:您可以在符合RangeReplaceableCollection协议的任何类型上使用insert(:at :),insert(contentsOf:at :),remove(at :)和removeSubrange( :)方法。 这包括String,以及集合类型,如Array,Dictionary和Set。

比较字符串

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

字符串和字符相等

字符串和字符相等性通过“等于”运算符(==)和“不等于”运算符(!=)进行检查。

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(_ :)方法,它们都接受一个类型为String的参数,并返回一个布尔值。

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"
]
你可以使用haseprefix(_ :)方法和romeoAndJuliet数组来计算播放的Act 1中的场景数量:
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"

注意:hasPrefix(_ :)和hasSuffix(_ :)方法在每个字符串中的扩展字形集群之间执行逐个字符的规范等价比较,如字符串和字符平等中所述。

字符串的Unicode表示形式

使用三种其他符合Unicode的表示之一访问字符串值:

  • 一组UTF-8代码单元(使用字符串的utf8属性访问)
  • 一组UTF-16代码单元(使用字符串的utf16属性访问)
  • 21位Unicode标量值的集合,等同于字符串的UTF-32编码形式(使用字符串的unicodeScalars属性访问)

推荐阅读更多精彩内容