Appearance
Swift 入门(7):字符串与日期
字符串和日期是开发中最常用的数据类型。Swift 提供了强大且安全的操作方式。
字符串(String)
创建字符串
swift
let s1 = "Hello"
let s2 = String("World")拼接
swift
let name = "Alice"
let greeting = "Hello, " + name
print(greeting) // Hello, Alice字符串插值
swift
let age = 20
print("My age is \(age)") // My age is 20遍历字符
swift
for ch in "Swift" {
print(ch)
}字符串长度
swift
let text = "Hello"
print(text.count) // 5子串
swift
let str = "Hello Swift"
let start = str.startIndex
let end = str.index(str.startIndex, offsetBy: 4)
let sub = str[start...end]
print(sub) // Hello常用方法
swift
let msg = " swift "
print(msg.uppercased()) // " SWIFT "
print(msg.lowercased()) // " swift "
print(msg.trimmingCharacters(in: .whitespaces)) // "swift"
print(msg.contains("sw")) // true字符串替换与链式调用
replacingOccurrences 方法
swift
// 单个替换
let text = "Hello World"
let newText = text.replacingOccurrences(of: " ", with: "-")
print(newText) // "Hello-World"
// 多个替换的链式调用
let original = "a+b/c=d"
let result = original
.replacingOccurrences(of: "+", with: "-")
.replacingOccurrences(of: "/", with: "_")
.replacingOccurrences(of: "=", with: "")
print(result) // "a-b_cd"什么是 Data 类型?
Data 是 Swift Foundation 框架中的核心类型,用于表示二进制数据。
swift
import Foundation // Data 来自 Foundation 框架
// Data 的本质:字节数组
let data1 = Data([0x48, 0x65, 0x6C, 0x6C, 0x6F]) // "Hello" 的字节表示
print(data1) // 5 bytes
// 常见的 Data 创建方式
let data2 = "Hello".data(using: .utf8)! // 字符串 → Data
let data3 = Data(count: 10) // 创建 10 字节的空 Data
let data4 = Data(base64Encoded: "SGVsbG8=")! // Base64 → DataData 的来源和用途
| 来源 | 方法 | 用途 |
|---|---|---|
| 字符串转换 | "text".data(using: .utf8) | 文本数据处理 |
| 网络请求 | URLSession 响应 | API 数据接收 |
| 文件读取 | Data(contentsOf: url) | 文件内容读取 |
| 图片处理 | UIImage.pngData() | 图片数据转换 |
| JSON 序列化 | JSONSerialization.data() | 对象 → JSON 数据 |
实战:Base64URL 编码转换
swift
// 完整的 Data → Base64URL 流程
func dataToBase64URL(_ data: Data) -> String {
// 1. Data → 标准 Base64 字符串
var s = data.base64EncodedString()
// 2. 标准 Base64 → Base64URL
s = s.replacingOccurrences(of: "+", with: "-")
.replacingOccurrences(of: "/", with: "_")
.replacingOccurrences(of: "=", with: "")
return s
}
// 使用示例
let textData = "Hello World".data(using: .utf8)!
let base64url = dataToBase64URL(textData)
print(base64url) // "SGVsbG8gV29ybGQ"
// 更简洁的写法(一行完成)
return data.base64EncodedString()
.replacingOccurrences(of: "+", with: "-")
.replacingOccurrences(of: "/", with: "_")
.replacingOccurrences(of: "=", with: "")反向转换:Base64URL → Data
swift
// Base64URL 解码函数
func base64URLToData(_ s: String) -> Data {
// 1. Base64URL → 标准 Base64
var t = s.replacingOccurrences(of: "-", with: "+") // - → +
.replacingOccurrences(of: "_", with: "/") // _ → /
// 2. 计算并添加填充字符
let pad = (4 - t.count % 4) % 4 // 计算需要多少个 = 填充
if pad > 0 {
t.append(String(repeating: "=", count: pad)) // 添加 = 填充
}
// 3. 标准 Base64 → Data
return Data(base64Encoded: t) ?? Data()
}数据转换过程详解
完整的双向转换流程:
swift
// 原始数据
let originalText = "Hello World!"
let originalData = originalText.data(using: .utf8)!
print("原始数据: \(originalText)") // "Hello World!"
// 第一步:Data → Base64URL
let base64url = originalData.base64EncodedString()
.replacingOccurrences(of: "+", with: "-")
.replacingOccurrences(of: "/", with: "_")
.replacingOccurrences(of: "=", with: "")
print("Base64URL: \(base64url)") // "SGVsbG8gV29ybGQh"
// 第二步:Base64URL → Data(你的代码)
let decodedData = base64URLToData(base64url)
let decodedText = String(data: decodedData, encoding: .utf8)!
print("解码结果: \(decodedText)") // "Hello World!"填充计算逻辑解析
Base64 编码要求长度是 4 的倍数,不足时用 = 填充:
swift
// 填充计算公式:(4 - length % 4) % 4
let examples = [
("SGVsbG8", 7), // 7 % 4 = 3, 需要 1 个 =
("SGVsbG8g", 8), // 8 % 4 = 0, 不需要填充
("SGVsbG8gV2", 10), // 10 % 4 = 2, 需要 2 个 =
]
for (base64url, length) in examples {
let pad = (4 - length % 4) % 4
let padded = pad > 0 ? base64url + String(repeating: "=", count: pad) : base64url
print("\(base64url) → \(padded) (添加 \(pad) 个 =)")
}
// 输出:
// SGVsbG8 → SGVsbG8= (添加 1 个 =)
// SGVsbG8g → SGVsbG8g (添加 0 个 =)
// SGVsbG8gV2 → SGVsbG8gV2== (添加 2 个 =)实际应用:JWT Token 解析
swift
// JWT Token 通常使用 Base64URL 编码
func decodeJWTPayload(_ token: String) -> [String: Any]? {
let parts = token.components(separatedBy: ".")
guard parts.count == 3 else { return nil }
// 解码 payload 部分(第二部分)
let payloadData = base64URLToData(parts[1])
// JSON 解析
return try? JSONSerialization.jsonObject(with: payloadData) as? [String: Any]
}
// WebAuthn 挑战码解析
func decodeChallenge(_ challengeString: String) -> Data {
return base64URLToData(challengeString)
}Data 的常用方法
swift
let data = "Hello".data(using: .utf8)!
// 基本属性
print(data.count) // 5 (字节数)
print(data.isEmpty) // false
// 转换方法
let string = String(data: data, encoding: .utf8) // Data → 字符串
let base64 = data.base64EncodedString() // Data → Base64
let array = [UInt8](data) // Data → 字节数组
// 操作方法
var mutableData = data
mutableData.append("!".data(using: .utf8)!) // 追加数据
print(String(data: mutableData, encoding: .utf8)!) // "Hello!"方法解析表
| 方法 | 作用 | 示例 |
|---|---|---|
base64EncodedString() | Data → Base64 字符串 | "SGVsbG8=" |
replacingOccurrences(of:with:) | 替换所有匹配的子串 | "a+b" → "a-b" |
| 链式调用 | 多个方法连续执行 | .method1().method2() |
Base64 vs Base64URL 对比
swift
let data = "Hello World".data(using: .utf8)!
// 标准 Base64
let base64 = data.base64EncodedString()
print(base64) // "SGVsbG8gV29ybGQ="
// Base64URL(URL 安全)
let base64url = data.base64EncodedString()
.replacingOccurrences(of: "+", with: "-") // + → -
.replacingOccurrences(of: "/", with: "_") // / → _
.replacingOccurrences(of: "=", with: "") // 移除填充
print(base64url) // "SGVsbG8gV29ybGQ"为什么需要 Base64URL?
swift
// ❌ 标准 Base64 在 URL 中会有问题
let url1 = "https://api.com/token=SGVsbG8+V29/bGQ=" // + 和 / 在 URL 中有特殊含义
// ✅ Base64URL 是 URL 安全的
let url2 = "https://api.com/token=SGVsbG8-V29_bGQ" // - 和 _ 在 URL 中安全实际应用场景
swift
// JWT Token 编码
func encodeJWTPayload(_ payload: [String: Any]) -> String {
guard let data = try? JSONSerialization.data(withJSONObject: payload) else {
return ""
}
return data.base64EncodedString()
.replacingOccurrences(of: "+", with: "-")
.replacingOccurrences(of: "/", with: "_")
.replacingOccurrences(of: "=", with: "")
}
// WebAuthn 挑战码处理
func processChallenge(_ challengeData: Data) -> String {
return challengeData.base64EncodedString()
.replacingOccurrences(of: "+", with: "-")
.replacingOccurrences(of: "/", with: "_")
.trimmingCharacters(in: CharacterSet(charactersIn: "="))
}日期(Date)
当前时间
swift
let now = Date()
print(now) // 2025-09-14 12:34:56 +0000日期格式化
swift
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let now = Date()
let str = formatter.string(from: now)
print(str) // 2025-09-14 20:34:56字符串转日期
swift
let formatter = DateFormatter()
formatter.dateFormat = "yyyy/MM/dd"
if let date = formatter.date(from: "2025/09/14") {
print(date)
}日期计算
swift
let now = Date()
let tomorrow = now.addingTimeInterval(24 * 60 * 60)
print(tomorrow)小结
- 字符串:拼接
+,插值\(var),常用方法uppercased、contains、trimmingCharacters。 - 日期:
Date()获取当前时间,DateFormatter用于格式化和解析。