Swift中的字符串(String)是一个Unicode编码、16位字符的字符序列。其和Objective-C中的(NSString)看上去稍微有点不太一样,在Objective-C中,我们定义一个字符串时一般这样:
NSString* aString = @"A String";而在Swift中,一般这样:
let aString = "A String"可以看出,在Swift中,定义一个字符串不再需要加上@符号。
不管在Objective-C中还是在Swift中,字符串都是表现出了「值类型语义」,即使在Objective-C中,我们定义一个字符串时仍要加上指针*符号。
在Swift中,字符串被定义成了struct类型,所表现出的也是正常的「值类型」。然而其内部实现却和传统的struct完全不同。真正的字符串内容其实是存放在堆中的,String的内部包含了一个「内容指针」指向堆上的内容。为什么他还保留了struct的特征?主要是其内部采用了特殊的实现方式:
Copy-on-Write 共享技术
在我们定义字符串时,相同内容的字符串只保留同一份堆内存,然后使用「内容指针」指向堆内存。这样,多个struct里的「内容指针」指向了同一份堆内存,即提高了效率,又节省了内存。
同样的,在字符串复制、赋值给其他变量/常量时,只会复制栈上的struct结构体,其中的「内容指针」保持不变,即仍指向同一份堆内存。
而在字符串内容改变时,会先将原来堆内存拷贝一份,并使「内容指针」指向新的对内存地址,然后再更改堆内存中的内容。这样,在完成更改的时候又不会影响到其他「内容指针」相同的变量,保持了「值类型」特征。
而正因此,每当我们需要修改一个字符串时,Swift都会先复制一份,然后再修改,所以,字符串的修改成本会略高一些。因此,我们应该尽量避免一些不必要的字符串修改,在修改字符串时尽量使用append和appendContentsOf方法,并设置适当的Capacity,而不是使用+=符号拼接字符串。
简单使用
初始化
// 以字面量的形式初始化
let aString = "A String"
//上面这代码等价于:
// let aString:String = "A String"
// 使用String的初始化器初始化
let anotherString = String("What")
// 初始化空字符串,以下两种方式初始化的字符串是相等的
let emptyString = ""
let anotherEmptyString = String()字符串拼接
// 可以简单的使用`+`号拼接字符串
var combinedString = aString + " " + anotherString //A String What
// 相当于:combinedString = combinedString + "TF"
combinedString += "TF" //A String WhatTF
let aChar: Character = "!"
// Append a Char,会更改自身的值
combinedString.append(aChar) //A String WhatTF!
// Append a String,会更改自身的值
combinedString.appendContentsOf("XXX") //A String WhatTF!XXX字符串插值
let num = 100
let string = "Hello"
let combinedString = "Num is: \(num), and String is: \(string)"
// "Num is: 100, and String is: Hello"在上面的例子中,num作为\(num)、string作为\(string)被插入到一个字符串常量中。 当创建字符串执行插值计算时此占位符会被替换为num、string的实际值。
我们可以在任何可以使用字符串字面量的时候使用。
判断字符串值是否相等
在Swift中判断值相等使用==操作符,当然String也不例外:
let emptyString = ""
let anotherEmptyString = String()
if emptyString == anotherEmptyString { //相等,输出:emptyString == anotherEmptyString
print("emptyString == anotherEmptyString")
}
let aString = "Hello"
let anotherString = "Hel" + "lo"
if aString == anotherString { //相等,输出:aString == anotherString
print("aString == anotherString")
}遍历字符串的值
for character in "Dog!????".characters {
print(character)
}
// D
// o
// g
// !
// ????判断字符串是否为空
let emptyString = ""
if emptyString.isEmpty {
print("emptyString is Empty")
}
let anotherEmptyString = String()
if anotherEmptyString.isEmpty {
print("anotherEmptyString is Empty")
}
let notEmptyString = " "
if notEmptyString.isEmpty {
print("notEmptyString is Empty")
} else {
print("notEmptyString is not Empty")
}
let anotherNotEmptyString = "Hello"
if anotherNotEmptyString.isEmpty {
print("anotherNotEmptyString is Empty")
} else {
print("anotherNotEmptyString is not Empty")
}截取字符串
在Swift中字符串的下标使用String.CharacterView.Index,而不是Int。
下标不能使用初始化器初始化,获取方式如下:
let string = "Hello, This is a swift string.";
let startIndex = string.startIndex // 0
let endIndex = string.endIndex // 30
let afterStartIndex = startIndex.successor() // 1
let beforeEndIndex = endIndex.predecessor() // 29
let advancedIndex = startIndex.advancedBy(10) // 10
let limitedAdvancedIndex = startIndex.advancedBy(100, limit: endIndex) // 30
let anotherLimitedAdvancedIndex = endIndex.advancedBy(-100, limit: startIndex) // 0截取字符串使用Index或Range<Index>,Range<Index>的创建方法如下:
let range = Range(startIndex ..< endIndex) // 0..<30
// 或
let anotherRange = startIndex ..< endIndex // 0..<30截取字符串:
string.substringToIndex(string.startIndex.advancedBy(5))
// Hello
string.substringFromIndex(string.endIndex.advancedBy(-13))
// swift string.
let range = string.startIndex.advancedBy(7) ..< string.endIndex.advancedBy(-13)
string.substringWithRange(range)
// This is a
string[range]
// This is a判断是否包含字符串
if string.containsString("swift") {
print("Contains")
}查找字符串
let range:Range? = string.rangeOfString("swift") // 17..<22let range:Range? = string.rangeOfString("swifty") // nil