swift相对于JS,
- 除了
String
类型外,还多一种Character
(C语言中称之为Char
)类型 - JS中字符串既可以用单引号也可以用双引号来表示字符串,而swift中 String 和 Character 均使用双引号 表示
- swift中的 String 类型是一种快速,现代化的字符串实现,每一个字符串都是由编码无关的 Unicode 字符组成,并支持访问字符的多种Unicode表达形式
- Swift 中 String 是 值类型
- swift 中 String 访问字符的方法对学JS的我看来很操蛋
1.多行字符
表示方式是:
let quotation = """
这是第一行
这是第二行
""";
个人感觉这个就是JS中简陋版的字符串模板,一些示例
#1 一行写不下, 可以用 '\' 进行换行
let quotation = """
这是第一行,\
这还是第一行的内容,太长了就换一行
这是第二行
""";
#2 最底下的 """ 的决定空格数 或者说缩进
let quotation = """
这是第一行,
这是第二行
这是第3行
"""; // 注意这个前面有4个空格,因为放置位置在此.
// 等价于
let quotation = """
这是第一行,
这是第二行
这是第3行
""";
#3 对 """ 进行转义
# 如果字符串中正好存在 """ 转义方式有2种: \""" 或者 \"\"\"
let threeDoubleQuotationMarks = """
Escaping the first quotation mark \"""
Escaping all three quotation marks \"\"\"
"""
#4 多个多行字符串结合
let badStart = """
one
two
"""
let end = """
three
"""
print(badStart + end)
// 打印两行:
// one
// twothree
// 如果想要换行 则需要注意这样写
let goodStart = """
one
two
"""
let end = """
three
"""
print(goodStart + end)
// 打印三行:
// one
// two
// three
2.需要转义的字符
字符串字面量需转义的字符:
-
\0
:空字符 -
\\
: 反斜杠 -
\t | \n | \r
: 水平制表符 | 换行符 | 回车符 -
\"
: 双引号 -
\'
: 单引号 - Unicode 标量:
\u{n}
,n
是任意1-8位16进制数,且可用的Unicode位码
示例:
let wiseWord = "\"想象力比知识更重要\" - 爱因斯坦"
let dollarSign = "\u{24}" // $ Unicode标量为 U+0024
let sparklingHeart = "\u{1F496}" // 💖,Unicode 标量 U+1F496
3.字符串插值(string interpolation)
使用 \(variables || expression)
的形式进行插值操作, 这个等同于JS中的 ${}
let count = 5
print("I have \(count) apples") // I have 5 apples
4.字符串的可变性
这里只提一点,就是swift中用 let
声明的表示常量,这和JS中的 const
一样,但是JS中也有 let
关键词,注意别混淆了,因此在swift中下面做法是错误的:
let greet = "hello"
greet += " world" // error 常量字符串不可以被修改
5.Character 类型
注意有些语言中,这个类型称之为 Char
,声明时用单引号,但是swift中Character类型用 双引号 进行声明
let aChar: Character = "A"
let charArray: [Character] = ["a", "b", "c"]
另外一般认为String类型是character类型的集合, swift中可以使用 for-in
对字符串进行遍历操作
let str = "Dog!🐶"
for character in "Dog!🐶" {
print(character)
}
// D
// o
// g
// !
// 🐶
// 另外可以通过 type(of:) 方法来判断是否是Character类型
for char in "Dog!🐶" {
print(type(of: char))
}
// 打印
// Character (重复5遍)
String 和 Character 类型之间的一些转换和方法
#1 将Character数组转换为字符串
# 使用 String 构造器即可
let cat: [Character] = ["C", "A", "T"]
let catStr = String(cat) // "CAT"
#2 将Character字符添加到String中
# 使用 append 方法
var greet = "hello"
let exclamationMark = "!"
greet.append(exclamationMark) // 现在greet变为了 "hello!"
6.Unicode
个人感觉这部分比较麻烦。
- swift中的
String
类型是基于 Unicode 标量 建立的。 - swift中的
Character
类型代表一个可扩展的字形群,一个可扩展的字形群是一个或多个可生成人类刻度的字符Unicode标量的有序排列(好拗口)
通俗讲一个字符的写法可能由Unicode组成的写法不一样,但是最后结果是一样的:
let eAcute: Character = "\u{E9}" // é
// 这个相当于对上面 é = e + ́ 的分解
let combinedEAcute: Character = "\u{65}\u{301}" // e 后面加上 ́
print(eAcute == combinedEAcute) // true
7.字符串的操作
swift中目前为止感觉语法最难看的部分来了,个人感觉这种设计太复杂了。
isEmpty 属性 判断字符串是否为空
let emptyString = ""
// 或者 let emptyString = String()
if emptyString.isEmpty {
print("这是一个空字符")
}
// "这是一个空字符"
字符串索引
因为不同字符可能会占用不同数量的内存空间,所以要知道 Character
的确定位置,就必须从 String
开头遍历每一个 Unicode 标量 直到结尾,因此, swift的字符串不能用整数做索引!!!
获取字符位置的方法大概有以下几种:
-
startIndex
: 获取String的第一个Character的索引, 注意其返回的不是一个Int类型,而是String.Index
类型 -
endIndex
: 获取字符串中最后一个Character的位置索引,注意endIndex
属性不能作为一个字符串的有效下标!!! -
index(before: String.Index)
: 获取某个字符前面的一个位置的索引 -
index(after: String.Index)
: 获取某个字符后面的一个位置的索引 -
index(_ i: String.Index, offsetBy: Int)
: 用来获取对应偏移量的索引,例如someStr.index(someStr.startIndex, offsetBy: 6)
获取开始位置偏移6位的字符 -
indices
: 这个属性会创建一个包含全部索引的范围(Range
),用来在一个字符串中访问单个字符 -
count
: 获取字符的数量
另外需要注意的是:
- 如果字符串为空,则 startIndex 等于 endIndex
#1 获取字符串的长度
let koala = "Koala 🐨"
print(koala.count) // 7 , 可以看出 这里 🐨 占一个字符
#2 开始索引
let greet = "hello world!"
print(greet[greet.startIndex]) // "h"
#3 endIndex 属性不能作为一个字符串的有效下标!!!
let greet = "hello world!"
print(greet[greet.endIndex]) // error Can't form a Character from an empty String
#4 获取最后一个字符
# 使用 index(before i: String.Index) 方法
let greet = "hello world!"
print(greet[greet.index(before: greet.endIndex)]) // "!"
#5 使用 index(after i: String.Index) 方法 获取第一个字符之后的字符
let greet = "hello world!"
print(greet[greet.index(after: greet.startIndex)]) // "e"
#6 使用 index(_ i: String.Index, offsetBy n: int) -> String.Index
let greet = "hello world!"
print(greet[greet.index(greet.startIndex, offsetBy: 4)]) // "o"
#7 使用 indices 创建 Range
let greet = "hello world!"
for index in greet.indices {
print("\(greet[index])", terminator: "|")
}
// h|e|l|l|o| |w|o|r|l|d|!|Index(_compoundOffset: 0, _cache: Swift.String.Index._Cache.utf16)
字符串增删改查
主要用到这几个方法:
-
insert(newElement: Character, at: String.Index)
: 可以在一个字符串的指定索引插入一个字符 -
insert(contentsOf: Collection, at: String.Index)
: 可以在一个字符串的指定索引插入一个字符段 -
remove(at:)
: 可以在一个字符串指定索引删除一个 -
removeSubrange(_ bounds: Range<String.Index>)
: 在一个字符串的指定索引删除一个子字符串这些方法都遵循
RangeReplaceableCollection
协议,还可以在集合中(比如 Array, Dictionary, Set )使用这些方法
示例:
var greet = "hello"
// 在尾部添加单个字符 '!'
greet.insert("!", at: greet.endIndex) // "hello!"
// 在 '!' 前添加 "world" 字符段
greet.insert(contentOf: "world", at: greet.index(greet.endIndex, offsetBy: -1)) // "hello world!"
// 在尾部移除单个字符 '!'
// 返回被移除的字符 "!"
// 同时greet 变为 "hello world"
greet.remove(at: greet.index(before: greet.endIndex))
// 移除 " world"
// 注意 removeSubrange 接受的参数类型是 Range<String> 类型
// 需要使用到前面学习的区间的表示法
let range = greet.index(greet.index(greet.endIndex, offsetBy: -6))..<greet.endIndex
greet.removeSubrange(range) // "hello"
SubString 类型
当从字符串中获取一个子字符串,得到的是一个 SubString
实例,而不是 String
类型,Swift中如果需要短时间内操作字符串,才会使用SubString
,如果要长时间保存结果,就把 SubString
转化为 String
的实例:
- 两者都在内存里保存字符集
- 两者不同之处在于性能优化,SubString 可以复用原 String的内存空间,或者另一个SubString 的内存空间
- String也有同样的优化,但是如果2个String共享内存的话,它们就会相等
下面示例使用方法:
-
index(of: Character) -> String.Index
: 用来查找某个字符的索引
var greet = "hello, world!"
let index = greet.index(of: ",") ?? greet.endIndex
let beginning = greet[..<index] // beginning 的值为 "hello"
print(type(of: beginning)) // 打印其类型为 "SubString"
// 将其转化为 String 类型, 以便长期存储
let newString = String(beginning)
本章中其它的字符串方法
-
hasPrefix(_ prefix: String)
: 字符串是否有某个前缀 -
hasSuffix(_ suffix: String)
: 字符串是否有某个后缀
let greet = "hello, world";
print(greet.hasPrefix("hell")) // true
print(greet.hasSuffix("world")) // true
另外swift中好像没有类似JS中的 substring
方法对字符进行截取,原生的小伙伴告诉我可以自定义:
extension String {
func substring(start: Int, end: Int = 0) -> String? {
if start > end && end != 0 {
return nil
}
let startIndex = self.index(self.startIndex, offsetBy: start)
let endIndex = end == 0 ? self.endIndex : self.index(self.startIndex, offsetBy: end)
return String(self[startIndex..<endIndex])
}
}
// 使用
let greet = "hello, world!"
greet.sub(start: 3, end: 7) // "lo,"
greet.sub(start: 3) // "lo, world!"
总结
这一章主要讲了swift中的2种(加上SubString应该是3种)类型,以及字符串索引的操作,最复杂的Unicode的相关表示法此处忽略了,待后面再学习。另外介绍了一些操作字符串的方法,还有大把的方法暂时还未接触,待学习。
网友评论