HR's Blog

Swimming 🏊 in the sea🌊of code!

0%

String

.

1
let someString = "some string literal value" + "other string"

多行字符串

1
2
3
4
let multiline = """
one line
two line
"""

如果你只是想换行让文本更易读,而不是想在字符串中真正的换行可以在要换行的地方加上\

1
2
3
4
5
6
let str1 = ""
let str2 = " "

let value = str1.isEmpty //true
let value2 = str2.isEmpty //false

Characters

1
2
3
4
5
for character in "Dog!狗" {
print(character)
}
D o g ! 🐶

1
2
let exclamationMark: Character = "!"

Grapheme Clusters


通常在OC中我们访问相应位置的字符使用Int类型像数组一样就可以访问,但是针对于特别的情况OC中就显得力不从心,例如像e带音节,单独的e带音节是233,但是也有分开单独e字幕加音节,他们显示的东西完全是相同的,再者像Emoji表情,里面包含皮肤的Emoji其实也是由有个字符组合一起显示的效果。这个时候直接使用OC的int类型来访问字符,或者计算字符的总长度就会出问题。(oc中可能认为第二种情况的e是两个字符)

但是在swift中用.count访问他们的时候,swift会认为只是一个字符,不管你用什么方式输入e加音节这个字符。而且上图的emoji表情,swift count的结果也是认为只是一个字符。因为这些改动导致,swfit的获取子字符串的range就变得和OC不一样了。

1
2
3
4
5
let cafeNormal = "café"
let cafeCombining = "cafe\u{0301}"

cafeNormal.count //4
cafeCombining.count //4

获取实际字符数量。

1
2
3
4
5
6
7
8
9
cafeNormal.unicodeScalars.count //4
cafeCombining.unicodeScalars.count //5
//遍历
for codePoint in cafeCombining.unicodeScalars {
print(codePoint.value)
}

//99 97 102 101 769

Indexing Strings

直接传入Int值来取Swift的字符串会报错。你必须使用特殊的Index type来操作Strings字符串。例如代表字符串的起始位置

1
2
3
let firstIndex = cafeCombining.startIndex
let firstChar = cafeCombining[firstIndex]

同理如果你要取得最后一个字符

1
2
3
4
5
6
7
8
9
let lastIndex = cafeCombining.endIndex
let lastChar = cafeCombining[lastIndex]

//你会得到一个错误的提示fatal error: Can't form a Character from an empty String
//因为endIndex获取的位置是字符串的末尾,末尾以后没有字符串,所以提示错误

let lastIndex = cafeCombining.index(before: cafeCombining.endindex)
let lastChar = cafeCombining[lastIndex]

offset from the first character

1
2
3
4
5
let fourthIndex = cafeCombining.index(cafeCombining.startIndex, offsetBy:3)
let fourthChar = cafeCombining[fourthIndex] //得到é

这个é其实是两个编码组成的,所以`fourthChar.unicodeScalars.count`会等于2.

combining characters字符串的相等问题


其他语言里 认为这两个字符串是不相等,但是他们其实现实的字符是一样的,但是在Swift里面认为他们是相等的,原理就是swift里面使用了一种canonicalization的技术,而且会三倍速度的提升比起之前的检测相等。其实在swift内部就是把字符串统一称为一种然后再做比较。

String as bi-directional collections.

反向字符串Swift直接提供了reversed()方法,但是返回的不是String类型而是reversed colletion类型。这其实是一种机制的方法,这种类型直接引用字符串的地址,而不是重新创建他们。

但是如果我想获得String类型怎么办?swift提供了以下方法。

1
2
let backwardsNameString = String(backwardsName) //这样介绍了在原来的字符串上反响引用,而为你的字符串申请了新的内存地址。

SubStrings字符串

1
2
3
4
let fullName = "Matt Galloway"
let spaceIndex = fullName.index(of: " ")!
let firstName = fullName[fullName.startIndex..<spaceIndex] // "Matt”

以上的代码中firstName也和reversed方法一样只是提供在原始字符串上的引用。而你得到的firstName也不是直接的String类型,而是基本上功能和String一样的SubString。这样也同样为了节省内存。如果要获得字符串结束在原有的字符串上的引用。

1
2
let lastNameString = String(lastName)

Encoding

见HTTP里面的UTF-8

Range表示一个范围

1
2
3
4
5
let underFive = 0.0..<5.0
underFive.contains(3.14) // true
underFive.contains(6.28) // false
underFive.contains(5.0) // false

1
2
3
4
5
6
for n in 3..<5 {
print(n)
}
// Prints "3"
// Prints "4"

“Working with Cocoa Data Types in Using Swift with Cocoa and Objective-C”

Excerpt From: Apple Inc. “The Swift Programming Language (Swift 4.1).” iBooks.

https://stackoverflow.com/questions/39677330/how-does-string-substring-work-in-swift