Swift 字符串与字符完全导读(一):从字面量到 Unicode 的实战之旅

前言

Swift 的 String 看起来"像 NSString 的弟弟",但骨子里是一套全新的 Unicode 抽象模型。

String 与 Character 的本质

  • String:由"扩展字形簇"(extended grapheme cluster)构成的有序集合。
  • Character:一个扩展字形簇,人类眼中的"一个字符",占用的字节数可变。
swift 复制代码
// 1 个 Character,由 2 个 Unicode 标量合成
let eAcute: Character = "é"                 // "é"
let eCombining: Character = "\u{65}\u{301}" // "e" + "́" 组合
print(eAcute == eCombining) // true,两者字形簇等价

字符串字面量:单行、多行、转义、扩展分隔符

单行字面量

swift 复制代码
let msg = "Hello, Swift" // 类型自动推断为 String

多行字面量

swift 复制代码
let html = """
           <div>
               <p>Hello</p>
           </div>
           """ // 缩进 4 空格会被自动去掉,因为闭合 """ 在最左侧第 12 列
           // 闭合"""左侧的空格会被删除,每一行左侧的同等长度的空格都会被删除

换行控制技巧

swift 复制代码
let sql = """
          SELECT * FROM user \
          WHERE age > 18
          """ // 反斜杠让源码换行,但字符串里无换行

转义序列

swift 复制代码
let special = "双引号:\",制表:\t,换行:\n,Unicode:\u{1F496}"

扩展分隔符(#)

场景:正则、JSON 模板里想保留原始反斜杠。

swift 复制代码
let raw = #"Raw \n still two characters"#
let needEscape = #"Use \#n to enable line break"#
print(raw)       // 输出:Raw \n still two characters
print(needEscape)// 输出:Use
                 //       to enable line break

多行 + 扩展分隔符

swift 复制代码
let mlRaw = #"""
            Line 1
            Line 2
            """#

空字符串的 3 种创建方式

swift 复制代码
let a = ""
let b = String()
let c = String("") // 与前两种等价
print(a.isEmpty) // true

可变性:let 与 var 的抉择

swift 复制代码
let immutable = "can't change"
// immutable += "!" // ❌ Compile-time error

var mutable = "hello"
mutable += ", world" // ✅

值类型:写时复制(COW)到底发生了什么

swift 复制代码
func foo(_ s: String) {
    var local = s   // 此时未复制,共享同一块缓冲区
    local += "!"    // 突变触发复制,O(n) 成本
    print(local)
}

底层优化:仅当本地突变或跨线程时才真正拷贝,因此作为入参传递时无需担心性能。

字符集合:遍历、提取、构造

swift 复制代码
let word = "Swift"
for ch in word {
    print(ch, terminator: "-") // S-w-i-f-t-
}

let single: Character = "A"
let fromChars = String([single, "B", "C"]) // "ABC"

字符串拼接的 5 种姿势

swift 复制代码
let left  = "Hello"
let right = "World"

// 1. 加法
let s1 = left + ", " + right

// 2. 加法赋值
var s2 = left
s2 += ", " + right

// 3. append(Character)
var s3 = left
s3.append(",")
s3.append(" ")
s3.append(Character(right)) // 仅当 right 长度=1 时安全

// 4. append(contentsOf: String)
var s4 = left
s4.append(contentsOf: ", \(right)")

// 5. 多行拼接注意最后一行换行
let goodStart = """
                Line 1
                Line 2
                """
let end       = """
                Line 3
                """
let merged = goodStart + end // 3 行,无意外合并

字符串插值:最灵活的"模板引擎"

swift 复制代码
let name = "Swift"
let year = 2025
let msg = "Hello, \(name)! In \(year + 1) we will rock."
print(msg) // Hello, Swift! In 2026 we will rock.

// 在扩展分隔符中使用插值
let rawLog = #"Level \#(name) recorded at \#(Date())"#

扩展场景:今天就能用上的 3 个小工具

彩色命令行日志

swift 复制代码
func log(_ info: String) {
    print(#"\u{1B}[32m[INFO]\#(info)\u{1B}[0m"#)
}
log("Server started") // 终端绿色输出

快速 Mock JSON

swift 复制代码
let userId = 9527
let json = #"""
           {"id": \#(userId), "name": "Alice"}
           """#
print(json) // 直接贴进 Postman 即可

多行 SQL 模板

swift 复制代码
let table = "user"
let sql = """
          SELECT *
          FROM \(table)
          WHERE status = 'active'
            AND created_at > ?
          """
相关推荐
HarderCoder3 小时前
Swift 字符串与字符完全导读(二):Unicode 视图、索引系统与内存陷阱
swift
非专业程序员Ping12 小时前
一文读懂字体文件
ios·swift·assembly·font
wahkim16 小时前
移动端开发工具集锦
flutter·ios·android studio·swift
非专业程序员Ping1 天前
一文读懂字符、字形、字体
ios·swift·font
东坡肘子1 天前
去 Apple Store 修手机 | 肘子的 Swift 周报 #0107
swiftui·swift·apple
非专业程序员2 天前
iOS/Swift:深入理解iOS CoreText API
ios·swift
xingxing_F2 天前
Swift Publisher for Mac 版面设计和编辑工具
开发语言·macos·swift
YGGP3 天前
【Swift】LeetCode 438. 找到字符串中所有字母异位词
swift
QWQ___qwq4 天前
Swift中.gesture的用法
服务器·microsoft·swift