Swift 字符(Character)全解析(2025 版)
“一个 Character = 一个用户可见字符(User-Perceived Character)”
掌握 Character vs Unicode、遍历、emoji、区域标志,写出 真正国际化 的文本处理代码!
一、什么是 Character?
Character是 Swift 中表示“一个用户可见字符”的类型,它不是固定字节,而是一个扩展字形簇(Extended Grapheme Cluster)
let a: Character = "A" // 1 个 Character
let emoji: Character = "rocket" // 1 个 Character(即使多个 Unicode 标量)
let flag: Character = "China" // 1 个 Character(🇨🇳 = Regional Indicator C + N)
二、Character vs 其他类型
| 类型 | 含义 | 示例 |
|---|---|---|
Character | 一个用户可见字符 | "A", "rocket", "é" |
Unicode.Scalar | 单个 Unicode 码点 | U+0061 ("a"), U+1F680 ("rocket") |
UInt32 | 码点值 | 97 |
String | 多个 Character | "Hello" |
let char: Character = "cafe"
let scalar: Unicode.Scalar = "é" // U+00E9
三、创建 Character
let a: Character = "A"
let rocket: Character = "rocket"
let snowman: Character = "snowman"
// 从 String 取第一个 Character
let first = "Swift".first! // "S"
let last = "Swift".last! // "t"
// 强制转换(谨慎!)
let c = Character("X")
四、遍历字符串中的 Character
let str = "Hello, Swift! rocket"
for char in str {
print(char) // 每个用户可见字符
}
// 输出:H e l l o , S w i f t ! rocket
关键:
for-in遍历的是Character,不是字节或码点
五、复杂字符解析(重点!)
1. 组合字符(Combining Characters)
let eAcute = "e\u{301}" // e + ́ (结合重音符号) = é
print(eAcute.count) // 1(一个 Character)
print(eAcute.unicodeScalars.count) // 2(两个标量)
2. Emoji + 皮肤修饰符
let thumbsUp = "thumbs up light skin tone" // thumbs up + light skin tone
print(thumbsUp.count) // 1
3. 家庭 Emoji
let family = "man woman girl boy" // 4 人 + ZWJ = 1 个家庭
print(family.count) // 1
4. 区域标志(国旗)
let cn = "\u{1F1E8}\u{1F1F3}" // 🇨🇳 = Regional Indicator C + N
print(cn) // China
print(cn.count) // 1
六、Character 的属性与方法
| 属性/方法 | 说明 |
|---|---|
.isEmoji | 是否为 Emoji |
.isLetter | 是否为字母 |
.isNumber | 是否为数字 |
.isWhitespace | 是否为空白 |
.unicodeScalars | 所有 Unicode 标量 |
.uppercased() | 转为大写 |
.lowercased() | 转为小写 |
let c: Character = "5"
c.isNumber // true
c.isLetter // false
let rocket: Character = "rocket"
rocket.isEmoji // true
七、Character 与 String 互转
// Character → String
let char: Character = "A"
let str = String(char) // "A"
// String → Character 数组
let chars = Array("Swift") // ["S", "w", "i", "f", "t"]
// 取第一个 Character
if let first = "Hello".first {
print(first) // H
}
八、常见错误 & 避坑
| 错误 | 正确做法 |
|---|---|
str[0] | 错误!String 不支持下标 |
str[i] | 错误!必须用 index |
str.count 按字节 | 错误!count 是 Character 数 |
for c in str { c += "!" } | 错误!Character 是 let |
正确遍历并修改:
var result = ""
for c in "hello" {
result += c.uppercased()
}
print(result) // HELLO
九、高级:自定义 Character 操作
extension Character {
var isVowel: Bool {
return "aeiouAEIOU".contains(self)
}
func repeated(times: Int) -> String {
return String(repeating: self, count: times)
}
}
let c: Character = "A"
print(c.isVowel) // true
print(c.repeated(times: 3)) // AAA
十、实战:字符处理工具箱
struct CharacterUtils {
// 统计 emoji 数量
static func countEmojis(in text: String) -> Int {
return text.filter { $0.isEmoji }.count
}
// 移除所有组合标记
static func removeCombiningMarks(from text: String) -> String {
return text.unicodeScalars
.filter { $0.properties.isAlphabetic || $0.properties.isDecimalDigit }
.map { Character($0) }
.map { String($0) }
.joined()
}
// 反转字符串(正确处理 emoji)
static func reverse(_ text: String) -> String {
return String(text.reversed())
}
}
// 测试
let text = "Hello rocket café China!"
print(CharacterUtils.countEmojis(in: text)) // 2
print(CharacterUtils.reverse(text)) // !anihC éfac tekor olleH
十一、性能提示
| 场景 | 推荐 |
|---|---|
| 频繁遍历 | for c in str(Character) |
| 需要码点 | for s in str.unicodeScalars |
| 大量拼接 | var result = ""; result.reserveCapacity(n) |
| 临时子串 | 用 Substring,最后转 String |
十二、Character 速查表
| 操作 | 代码 |
|---|---|
| 创建 | let c: Character = "A" |
| 遍历 | for c in str { } |
| 判 Emoji | c.isEmoji |
| 大写 | c.uppercased() |
| 转 String | String(c) |
| 取第一个 | str.first |
| Unicode 标量 | c.unicodeScalars |
十三、练习题(当场写!)
// 1. 写一个函数:统计字符串中 emoji 数量
func countEmojis(_ s: String) -> Int {
// 你的代码
}
// 2. 实现 Character 的 isConsonant 扩展(非元音字母)
extension Character {
var isConsonant: Bool {
// 你的代码
}
}
// 3. 反转字符串,正确处理 "rocket café"
func reverseString(_ s: String) -> String {
// 你的代码
}
答案(展开查看)
点击查看答案
// 1.
func countEmojis(_ s: String) -> Int {
return s.filter { $0.isEmoji }.count
}
// 2.
extension Character {
var isConsonant: Bool {
let vowels = "aeiouAEIOU"
return self.isLetter && !vowels.contains(self)
}
}
// 3.
func reverseString(_ s: String) -> String {
return String(s.reversed())
}
总结:Character 黄金法则
| 法则 | 说明 |
|---|---|
1. Character = 用户可见字符 | 不是字节,不是码点 |
2. for-in 遍历 Character | 自动处理组合字符 |
3. count 是字符数 | 不是字节数 |
4. emoji、国旗、皮肤修饰符 = 1 个 Character | 不要拆分 |
5. 需要码点时用 unicodeScalars | 精确控制 |
你已完全掌握 Swift Character!
回复关键词继续学习:
Swift Unicode 深入Swift 文本布局原理Swift 正则与 CharacterSwiftUI Text + Character
现在就写一个函数:输入 "Hello rocket!" → 输出 ["H","e","l","l","o"," ","rocket","!"](Character 数组)!