单元1 · Swift 环境与基础语法
Playground、print、变量、常量、类型推断、字符串插值
- 输出:print 输出;字符串插值 \(变量)。
- 变量:let 常量、var 变量;类型推断。
- 输入:readLine + Int() + if let 解包。
实训1.1 Hello World 与输出
编写第一个 Swift 程序,输出问候语。
print 输出;Swift 源码无需 main 入口也可直接执行。
print("Hello, Swift!")
print("Swift 是 Apple 推出的现代语言")
print("输出", 42, separator: " | ")
实训1.2 变量与常量
用 let 声明常量、var 声明变量并输出。
let 不可变(推荐);var 可变;类型推断。
let name = "Swift"
var version = 5.9
version = 6.0
print("语言:\(name)")
print("版本:\(version)")
实训1.3 数据类型与插值
声明 Int/Double/Bool/String 并输出类型。
显式类型注解;字符串插值 \(变量)。
let count: Int = 42
let price: Double = 59.9
let isActive: Bool = true
let name: String = "Swift"
print("计数:\(count),类型:\(type(of: count))")
print("价格:\(price)")
print("是否激活:\(isActive)")
print("问候:\(name) 开发者")
实训1.4 输入与类型转换
读取用户输入并转换为整数,输出计算结果。
readLine 读取;Int() 转换返回 Optional;! 强制解包需谨慎。
print("请输入一个整数:", terminator: "")
if let input = readLine(), let n = Int(input) {
print("\(n) 的平方是 \(n * n)")
} else {
print("输入无效")
}
单元2 · 数据类型与运算符
数值类型、算术/比较/逻辑、类型转换、Optional
- 运算:Int 整除截断;% 取余。
- Optional:if let/guard let/?? 三种解包。
- 转换:Int()/Double() 转换返回 Optional。
实训2.1 基础运算
给定整数 17 和 5,输出和、差、积、商、余数、幂。
Int 除法截断;% 取余;pow 幂运算。
let a = 17
let b = 5
print("和:\(a + b)")
print("差:\(a - b)")
print("积:\(a * b)")
print("整除商:\(a / b)")
print("余数:\(a % b)")
print("2 的 10 次方:\(pow(2.0, 10.0))")
实训2.2 浮点运算
计算半径为 7.5 的圆的周长与面积。
Double.pi 圆周率;String(format:) 控制精度。
import Foundation
let r = 7.5
let circumference = 2 * Double.pi * r
let area = Double.pi * r * r
print("周长:\(String(format: "%.4f", circumference))")
print("面积:\(String(format: "%.4f", area))")
实训2.3 比较与逻辑运算
a=8、b=12,输出 a>b、a!=b、a<10 && b>10、!(a==8)。
== 相等;&& 与、|| 或、! 非。
let a = 8
let b = 12
print("a > b:\(a > b)")
print("a != b:\(a != b)")
print("a<10 && b>10:\(a < 10 && b > 10)")
print("!(a == 8):\(!(a == 8))")
实训2.4 Optional 解包
演示 Optional 的 if let、guard let、?? 三种解包方式。
if let 条件解包;guard let 提前返回;?? 提供默认值。
func parseNumber(_ s: String) -> Int? {
Int(s)
}
let s1 = "42"
let s2 = "abc"
if let n = parseNumber(s1) {
print("\(s1) 解析为 \(n)")
}
let value = parseNumber(s2) ?? -1
print("兜底值:\(value)")
func printValue(_ s: String) {
guard let n = parseNumber(s) else {
print("\(s) 无法解析")
return
}
print("guard 解包:\(n)")
}
printValue("100")
单元3 · 流程控制:分支结构
if/else、switch、三元、范围
- if:else if 链式判断。
- switch:无需 break;支持范围与元组匹配。
- 三元:?: 简洁条件表达式。
实训3.1 if 判断成绩等级
成绩 score=85,输出等级:>=90 优秀、>=80 良好、>=60 及格、否则不及格。
if/else if/else;Swift 括号可省略。
let score = 85
if score >= 90 {
print("优秀")
} else if score >= 80 {
print("良好")
} else if score >= 60 {
print("及格")
} else {
print("不及格")
}
实训3.2 switch 判断星期
用 switch 把数字 1-7 映射为星期。
switch 无需 break;case 可多值;default 兜底。
let day = 4
switch day {
case 1:
print("星期一")
case 2:
print("星期二")
case 3:
print("星期三")
case 4:
print("星期四")
case 5:
print("星期五")
case 6:
print("星期六")
case 7:
print("星期日")
default:
print("无效输入")
}
实训3.3 switch 范围匹配
用 switch + Range 匹配成绩等级。
case 90...100 范围匹配;... 闭区间、..< 半开区间。
let score = 85
switch score {
case 90...100:
print("优秀")
case 80..<90:
print("良好")
case 60..<80:
print("及格")
case 0..<60:
print("不及格")
default:
print("非法分数")
}
实训3.4 三元与元组匹配
用三元判断奇偶,用元组 switch 判断象限。
三元 ?:;switch 支持元组与 where 守卫。
let n = 15
print(n % 2 == 0 ? "偶数" : "奇数")
let point = (3, -2)
switch point {
case (0, 0):
print("原点")
case (_, 0):
print("x 轴上")
case (0, _):
print("y 轴上")
case (let x, let y) where x > 0 && y > 0:
print("第一象限")
case (let x, let y):
print("其它位置:(\(x), \(y))")
}
单元4 · 循环结构
for-in、while、repeat-while、break/continue、stride
- for-in:遍历范围与集合。
- stride:步长遍历;倒序。
- 控制:break/continue;while。
实训4.1 for 求和 1 到 100
用 for-in 计算 1+2+...+100 并输出。
for x in 1...100 遍历;闭区间。
var sum = 0
for i in 1...100 {
sum += i
}
print("1 到 100 的和:\(sum)")
实训4.2 打印乘法表
输出 9x9 乘法表,每行一个乘数。
嵌套 for;print 不换行用 terminator 参数。
for i in 1...9 {
var row = ""
for j in 1...i {
row += "\(j)x\(i)=\(i * j) "
}
print(row)
}
实训4.3 stride 与步长
用 stride 输出偶数序列,演示倒序遍历。
stride(from:to:by:) 半开;stride(from:through:by:) 含端点。
print("2 到 10 的偶数:")
for n in stride(from: 2, through: 10, by: 2) {
print(n, terminator: " ")
}
print()
print("倒序 5 到 1:")
for n in stride(from: 5, through: 1, by: -1) {
print(n, terminator: " ")
}
print()
实训4.4 break 与 continue
输出 1 到 20 中能被 3 整除的数,遇到 15 用 break 结束。
break 终止循环;continue 跳过当前迭代。
for i in 1...20 {
if i == 15 {
break
}
if i % 3 != 0 {
continue
}
print(i, terminator: " ")
}
print()
var sum = 0
var n = 1
while n <= 10 {
if n % 2 == 0 {
n += 1
continue
}
sum += n
n += 1
}
print("1..10 奇数之和:\(sum)")
单元5 · 数组与字典
数组、字典、Set、集合方法、遍历
- 数组:append/insert/count/max/sorted。
- 高阶:map/filter/reduce/contains。
- 字典/Set:键值对、去重、集合运算。
实训5.1 数组基础操作
创建数组,添加元素、遍历、求最大值、排序。
数组字面量;append 添加;sorted 排序;max() 最值。
var nums = [12, 45, 7, 89, 33]
nums.append(60)
nums.insert(25, at: 0)
print("大小:\(nums.count)")
print("最大值:\(nums.max()!)")
print("最小值:\(nums.min()!)")
print("排序:\(nums.sorted())")
for (index, value) in nums.enumerated() {
print("[\(index)] = \(value)")
}
实训5.2 数组高阶方法
用 map、filter、reduce、contains 处理数组。
map 映射、filter 筛选、reduce 归约。
let nums = [3, 1, 4, 1, 5, 9, 2, 6]
let doubled = nums.map { $0 * 2 }
print("翻倍:\(doubled)")
let evens = nums.filter { $0 % 2 == 0 }
print("偶数:\(evens)")
let sum = nums.reduce(0, +)
print("总和:\(sum)")
print("包含 5:\(nums.contains(5))")
print("去重:\(Set(nums).sorted())")
实训5.3 字典 Dictionary
创建字典存年龄,增删改查并遍历。
字典字面量 [key: value];updateValue 更新;removeValue 删除。
var ages = ["张三": 20, "李四": 22]
ages["王五"] = 24
ages["李四"] = 23
ages.removeValue(forKey: "王五")
for (name, age) in ages {
print("\(name):\(age) 岁")
}
print("张三年龄:\(ages["张三"] ?? 0)")
print("键列表:\(ages.keys.sorted())")
实训5.4 Set 集合运算
用 Set 做并集、交集、差集运算。
Set 无序去重;union/intersection/subtracting。
let a: Set = [1, 2, 3, 4]
let b: Set = [3, 4, 5, 6]
print("并集:\(a.union(b).sorted())")
print("交集:\(a.intersection(b).sorted())")
print("差集:\(a.subtracting(b).sorted())")
let words = ["ruby", "swift", "ruby", "kotlin", "swift"]
let unique = Set(words)
print("去重后:\(unique.sorted())")
单元6 · 函数与闭包
函数定义、参数标签、默认参数、闭包、高阶函数
- 函数:func + 参数标签 + -> 返回。
- 参数:默认参数;... 可变参数。
- 闭包:{ } 语法;$0/$1;尾随闭包。
实训6.1 定义求和函数
定义 add 函数返回两数之和并调用输出。
func 定义;-> 返回类型;参数标签。
func add(_ a: Int, _ b: Int) -> Int {
a + b
}
func greet(name: String) -> String {
"你好,\(name)!"
}
print("add(10, 20) = \(add(10, 20))")
print("add(3, 7) = \(add(3, 7))")
print(greet(name: "小明"))
实训6.2 默认参数与可变参数
定义带默认参数与可变参数的函数。
参数默认值;... 收集可变参数为数组。
func greet(name: String, greeting: String = "你好") -> String {
"\(greeting),\(name)!"
}
func sumAll(_ numbers: Int...) -> Int {
numbers.reduce(0, +)
}
print(greet(name: "小明"))
print(greet(name: "小红", greeting: "早上好"))
print("sumAll(1,2,3,4) = \(sumAll(1, 2, 3, 4))")
实训6.3 闭包基础
定义闭包并作为参数传递,使用尾随闭包语法。
闭包 { 参数 in 表达式 };尾随闭包;$0/$1 简写。
let double: (Int) -> Int = { x in
x * 2
}
print("double(5) = \(double(5))")
let nums = [1, 2, 3, 4, 5]
let doubled = nums.map { $0 * 2 }
print("map 翻倍:\(doubled)")
let evens = nums.filter { $0 % 2 == 0 }
print("filter 偶数:\(evens)")
实训6.4 高阶函数与捕获
编写接收闭包参数的函数,演示闭包捕获变量。
闭包可捕获上下文变量;escaping 闭包延迟执行。
func applyTwice(_ x: Int, op: (Int) -> Int) -> Int {
op(op(x))
}
let inc = { (x: Int) -> Int in x + 1 }
print("applyTwice(3, +1) = \(applyTwice(3, op: inc))")
var counter = 0
let incrementCounter = {
counter += 1
}
incrementCounter()
incrementCounter()
print("闭包捕获计数:\(counter)")
单元7 · 字符串与集合操作
字符串方法、字符、正则、字符串插值
- 字符串:uppercased/split/replacingOccurrences。
- 插值:\(表达式);多行字符串。
- 字符:for ch in s 遍历字符。
实训7.1 字符串常用方法
对字符串做大小写、替换、拆分、拼接、长度统计。
uppercased/lowercased/replacingOccurrences/split/count。
var s = " Hello, Swift "
s = s.trimmingCharacters(in: .whitespaces)
print("去掉空格:|\(s)|")
print("大写:\(s.uppercased())")
print("小写:\(s.lowercased())")
print("替换:\(s.replacingOccurrences(of: "Swift", with: "iOS"))")
print("字符数:\(s.count)")
let parts = s.split(separator: ",")
print("拆分:\(parts)")
实训7.2 字符串插值与格式化
演示字符串插值、多行字符串与格式化。
\(表达式) 插值;""" 多行;String(format:)。
import Foundation
let name = "Swift"
let total = 42
let percent = 85.5
print("语言:\(name),版本:\(6.0)")
print("总计:\(total),完成度:\(String(format: "%.1f%%", percent))")
let multiline = """
第一行
第二行
"""
print(multiline)
实训7.3 字符串与字符遍历
遍历字符串中的字符,统计元音字母数量。
for ch in s 遍历字符;contains 判断。
let text = "Swift Programming"
var vowelCount = 0
let vowels: Set<Character> = ["a", "e", "i", "o", "u", "A", "E", "I", "O", "U"]
for ch in text {
if vowels.contains(ch) {
vowelCount += 1
}
}
print("元音字母数:\(vowelCount)")
实训7.4 字符串查找与替换
查找子串、替换、拆分并统计词频。
range(of:) 查找;components 按分隔符拆分;Dictionary 统计。
import Foundation
let text = "swift is powerful swift is concise swift is fun"
let words = text.components(separatedBy: " ")
var freq: [String: Int] = [:]
for w in words {
freq[w, default: 0] += 1
}
for (word, count) in freq.sorted(by: { $0.value > $1.value }) {
print("\(word):\(count)")
}
if let range = text.range(of: "concise") {
let index = text.distance(from: text.startIndex, to: range.lowerBound)
print("concise 首次出现位置:\(index)")
}
单元8 · 类与结构体
class/struct、属性、方法、继承、协议
- 类:class 引用类型;init 构造器。
- 结构体:struct 值类型拷贝。
- 继承/协议:override + super;protocol 多态。
实训8.1 定义类与实例
定义 Student 类,包含属性与方法,实例化调用。
class 引用类型;init 构造器;方法定义。
class Student {
var name: String
var score: Double
init(name: String, score: Double) {
self.name = name
self.score = score
}
func info() -> String {
"\(name),成绩 \(score) 分"
}
}
let stu = Student(name: "小明", score: 92.5)
print(stu.info())
实训8.2 结构体与值类型
定义 struct 并说明值类型语义。
struct 值类型(拷贝);class 引用类型(共享)。
struct Point {
var x: Double
var y: Double
func distance() -> Double {
(x * x + y * y).squareRoot()
}
}
var p1 = Point(x: 3, y: 4)
print("距离:\(p1.distance())")
var p2 = p1 // 值拷贝
p2.x = 10
print("p1.x:\(p1.x),p2.x:\(p2.x)(互不影响)")
实训8.3 继承与重写
定义 Animal 基类与 Dog 子类,子类重写方法。
class 继承;override 重写;super 调用父类。
class Animal {
var name: String
init(name: String) {
self.name = name
}
func speak() -> String {
"动物叫声"
}
}
class Dog: Animal {
override func speak() -> String {
"\(super.speak()):汪汪!"
}
}
let dog = Dog(name: "旺财")
print(dog.speak())
实训8.4 协议 Protocol
定义协议并让类遵循,实现多态。
protocol 定义接口;类遵循后实现;多态分发。
protocol Describable {
var description: String { get }
func describe() -> String
}
class Document: Describable {
var title: String
init(title: String) {
self.title = title
}
var description: String {
"文档:\(title)"
}
func describe() -> String {
"\(description),可打印"
}
}
let doc = Document(title: "Swift 教程")
print(doc.describe())
print("遵循协议:\(doc is Describable)")
单元9 · 错误处理与文件
do/catch、throw、可选链、文件读写简介
- 错误:throws/do-catch/throw。
- 可选链:?. 安全访问;?? 默认值。
- 文件:String write/read;FileManager。
实训9.1 错误处理
用 do/catch 捕获错误,throw 抛出错误。
throws 标记函数;do/catch 捕获;Error 协议定义错误类型。
enum ScoreError: Error {
case outOfRange(Int)
}
func grade(_ score: Int) throws -> String {
guard score >= 0 && score <= 100 else {
throw ScoreError.outOfRange(score)
}
switch score {
case 90...100: return "优秀"
case 60..<90: return "及格"
default: return "不及格"
}
}
do {
print(try grade(95))
print(try grade(120))
} catch {
print("错误:\(error)")
}
实训9.2 可选链与强制解包
用 optional chaining 与 ?? 安全访问可选属性。
?. 可选链;?? 默认值;避免强制解包。
class Author {
var name: String
init(name: String) { self.name = name }
}
class Book {
var title: String
var author: Author?
init(title: String, author: Author? = nil) {
self.title = title
self.author = author
}
}
let b1 = Book(title: "Swift 教程", author: Author(name: "张三"))
let b2 = Book(title: "未署名书籍")
print("b1 作者:\(b1.author?.name ?? "未知")")
print("b2 作者:\(b2.author?.name ?? "未知")")
实训9.3 文件读写
用 String API 写入与读取文本文件。
write(to:) 写入;contentsOfFile 读取;FileManager 管理文件。
import Foundation
let path = "notes.txt"
let content = "第一行内容\n第二行内容"
try? content.write(toFile: path, atomically: true, encoding: .utf8)
if let read = try? String(contentsOfFile: path, encoding: .utf8) {
print("文件内容:")
print(read)
}
let fm = FileManager.default
print("文件存在:\(fm.fileExists(atPath: path))")
实训9.4 defer 与作用域
用 defer 延迟执行清理逻辑,验证执行顺序。
defer 在作用域结束时执行;可多个 defer 逆序执行。
func process() {
print("开始处理")
defer {
print("清理资源(最后执行)")
}
defer {
print("第二个 defer(逆序先执行)")
}
print("处理中...")
}
process()
var total = 0
for i in 1...5 {
total += i
}
print("闭包内作用域示例:\(total)")
单元10 · 泛型与协议
泛型函数、泛型类型、where 约束、常用协议
- 泛型:
类型参数;inout 交换。 - 约束:T: Comparable 协议约束。
- 协议:Equatable/Hashable 支持比较。
实训10.1 泛型函数
编写交换两个值的泛型函数。
func swapValues<T>(_ a: inout T, _ b: inout T) {
let temp = a
a = b
b = temp
}
var x = 10
var y = 20
swapValues(&x, &y)
print("交换后:x=\(x),y=\(y)")
var s1 = "Hello"
var s2 = "World"
swapValues(&s1, &s2)
print("字符串交换:\(s1) \(s2)")
实训10.2 泛型类型
定义泛型 Stack(栈),实现 push/pop。
泛型类 struct Stack
struct Stack<T> {
private var items: [T] = []
mutating func push(_ item: T) {
items.append(item)
}
mutating func pop() -> T? {
items.popLast()
}
var isEmpty: Bool { items.isEmpty }
}
var stack = Stack<Int>()
stack.push(1)
stack.push(2)
stack.push(3)
print("出栈:\(stack.pop()!)")
print("出栈:\(stack.pop()!)")
实训10.3 泛型约束
用 where 约束泛型必须遵循协议,比较大小。
T: Comparable 约束;泛型可调用协议方法。
func findMax<T: Comparable>(_ a: T, _ b: T) -> T {
a > b ? a : b
}
print("最大:\(findMax(10, 20))")
print("最大:\(findMax(3.14, 2.71))")
print("最大:\(findMax("apple", "banana"))")
实训10.4 常用协议
用 Equatable、Hashable 协议支持相等比较与 Set 存储。
Equatable 提供 ==;Hashable 支持 Set/字典键。
struct User: Equatable, Hashable {
var id: Int
var name: String
}
let u1 = User(id: 1, name: "Alice")
let u2 = User(id: 1, name: "Alice")
let u3 = User(id: 2, name: "Bob")
print("u1 == u2:\(u1 == u2)")
print("u1 == u3:\(u1 == u3)")
let users: Set<User> = [u1, u2, u3]
print("Set 去重后数量:\(users.count)")
单元11 · 并发与异步
async/await、Task、DispatchQueue 简介
- async:async/await 异步函数。
- 并发:async let 并行;TaskGroup。
- GCD:DispatchQueue 后台任务。
实训11.1 async/await 基础
定义 async 函数并用 await 调用。
async 标记异步函数;await 等待结果。
func fetchData() async -> String {
try? await Task.sleep(nanoseconds: 1_000_000_000)
return "数据加载完成"
}
Task {
let result = await fetchData()
print(result)
}
实训11.2 async let 并发
用 async let 并行执行多个异步任务。
async let 并发启动;await 同时等待多个结果。
func fetchUser() async -> String {
try? await Task.sleep(nanoseconds: 500_000_000)
return "用户数据"
}
func fetchPosts() async -> String {
try? await Task.sleep(nanoseconds: 500_000_000)
return "帖子数据"
}
Task {
async let user = fetchUser()
async let posts = fetchPosts()
let result = await "用户:\(user),帖子:\(posts)"
print(result)
}
实训11.3 TaskGroup 并发集合
用 TaskGroup 并发处理多个任务并汇总结果。
withTaskGroup 创建任务组;addTask 添加任务。
func download(_ name: String) async -> String {
try? await Task.sleep(nanoseconds: 300_000_000)
return "\(name) 下载完成"
}
Task {
let results = await withTaskGroup(of: String.self) { group in
for i in 1...3 {
group.addTask {
await download("文件\(i)")
}
}
var list: [String] = []
for await r in group {
list.append(r)
}
return list
}
print(results)
}
实训11.4 DispatchQueue 简介
用 GCD 在后台队列执行任务并回到主队列。
DispatchQueue.global 后台;asyncAfter 延迟;main 主队列。
import Foundation
print("开始")
DispatchQueue.global().async {
Thread.sleep(forTimeInterval: 0.5)
print("后台任务执行完毕")
DispatchQueue.main.async {
print("回到主队列更新 UI")
}
}
RunLoop.main.run(until: Date(timeIntervalSinceNow: 1.0))
单元12 · 综合项目实训
综合运用 Swift 知识完成项目
- 综合:struct、字典、闭包、错误处理组合。
- 工程化:sorted、reduce、格式化输出。
实训12.1 学生成绩统计
用结构体与数组处理学生成绩,输出平均与排名。
struct + 数组 + sorted + reduce 组合。
struct Student {
let name: String
let chinese: Double
let math: Double
var average: Double { (chinese + math) / 2 }
}
let students = [
Student(name: "张三", chinese: 90, math: 85),
Student(name: "李四", chinese: 78, math: 92),
Student(name: "王五", chinese: 88, math: 76)
]
let sorted = students.sorted { $0.average > $1.average }
print("姓名\t语文\t数学\t平均")
for s in sorted {
print("\(s.name)\t\(s.chinese)\t\(s.math)\t\(String(format: "%.1f", s.average))")
}
let avg = students.map(\.average).reduce(0, +) / Double(students.count)
print("全班平均:\(String(format: "%.1f", avg))")
print("第一名:\(sorted.first!.name)")
实训12.2 词频统计器
统计文本单词出现次数,输出出现最多的单词。
components 拆词 + Dictionary 统计 + sorted 排序。
import Foundation
let text = "swift is powerful swift is concise swift is fun"
let words = text.components(separatedBy: " ")
var freq: [String: Int] = [:]
for w in words {
freq[w, default: 0] += 1
}
let sorted = freq.sorted { $0.value > $1.value }
for (word, count) in sorted {
print("\(word):\(count)")
}
if let top = sorted.first {
print("出现最多:\(top.key),\(top.value) 次")
}
实训12.3 待办事项管理器
用结构体实现待办事项:添加、标记完成、过滤未完成。
struct + mutating 方法 + filter 过滤。
struct Todo {
var id: Int
var title: String
var done: Bool = false
mutating func toggle() {
done.toggle()
}
}
var todos = [
Todo(id: 1, title: "学习 Swift 语法"),
Todo(id: 2, title: "完成实训项目"),
Todo(id: 3, title: "复习集合")
]
todos[1].toggle()
print("待办清单:")
for t in todos {
let mark = t.done ? "✓" : " "
print("[\(mark)] \(t.id). \(t.title)")
}
let pending = todos.filter { !$0.done }
print("未完成数:\(pending.count)")
实训12.4 简易计算器
实现支持 + - * / 的计算器:解析表达式并计算。
components 解析 + switch 分发 + 错误处理。
import Foundation
enum CalcError: Error {
case badFormat
case unknownOperator(String)
case divideByZero
}
func calculate(_ expr: String) throws -> Double {
let parts = expr.split(separator: " ").map(String.init)
guard parts.count == 3 else { throw CalcError.badFormat }
guard let a = Double(parts[0]), let b = Double(parts[2]) else {
throw CalcError.badFormat
}
switch parts[1] {
case "+": return a + b
case "-": return a - b
case "*": return a * b
case "/":
guard b != 0 else { throw CalcError.divideByZero }
return a / b
default:
throw CalcError.unknownOperator(parts[1])
}
}
for expr in ["10 + 5", "10 * 3", "10 / 0", "abc + 1"] {
do {
print("\(expr) = \(try calculate(expr))")
} catch {
print("\(expr) -> 错误:\(error)")
}
}