为什么 Swift 的控制流值得单开一篇?
- 语法糖多:区间、stride、tuple、where、guard、defer......
 - 安全严苛:switch 必须 exhaustive、case 不能空、默认不贯穿。
 - 表达能力强:if/switch 可以当表达式用,一行赋值即可。
 - 场景丰富:从日常循环到资源清理、API 可用性检查,全覆盖。
 
For-In 循环:从"会写"到"写对"
基本形态
            
            
              swift
              
              
            
          
          // 遍历数组
let fruits = ["apple", "orange", "banana"]
for fruit in fruits {
    print("我喜欢吃\(fruit)")
}
        字典遍历注意顺序
            
            
              swift
              
              
            
          
          let legCount = ["ant": 6, "snake": 0, "cat": 4]
// 字典无序!同一台机器多次运行顺序都可能不同
for (animal, legs) in legCount {
    print("\(animal) 有 \(legs) 条腿")
}
        区间与"忽略值"
            
            
              swift
              
              
            
          
          // 闭区间 ...  包含两端
for i in 1...5 {
    print("5 x \(i) = \(5 * i)")
}
// 半开区间 ..<  忽略最后一项
let minutes = 0..<60          // 0~59
for tick in minutes where tick % 5 == 0 {
    // 只打印 0/5/10/.../55
    print("表盘刻度 \(tick)")
}
// 如果根本不想用下标,用 _ 占位
var base = 1
for _ in 1...10 {            // 3 的 10 次方
    base *= 3
}
print("3^10 = \(base)")     // 59049
        stride 灵活跳步
            
            
              swift
              
              
            
          
          // 开区间 stride(from:to:by:)
for degree in stride(from: 0, to: 360, by: 30) {
    print("旋转 \(degree)°")
}
// 闭区间 stride(from:through:by:)
for rate in stride(from: 0.5, through: 1.5, by: 0.25) {
    print("汇率 \(rate)")
}
        While 与 Repeat-While:何时选谁?
| 场景 | 推荐 | 
|---|---|
| 可能一次都不执行 | while | 
| 至少执行一次 | repeat-while | 
蛇梯棋:同一逻辑两种写法
            
            
              swift
              
              
            
          
          let finalSquare = 25
var board = Array(repeating: 0, count: finalSquare + 1)
// 梯子
board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
// 蛇
board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08
// ----- while 版 -----
var square = 0, diceRoll = 0
while square < finalSquare {
    diceRoll += 1
    if diceRoll == 7 { diceRoll = 1 }          // 模拟 1~6 骰子
    square += diceRoll
    if square < board.count { square += board[square] }
}
print("while 版到达终点")
// ----- repeat-while 版 -----
square = 0; diceRoll = 0
repeat {
    square += board[square]   // 先结算梯子/蛇
    diceRoll += 1
    if diceRoll == 7 { diceRoll = 1 }
    square += diceRoll
} while square < finalSquare
print("repeat-while 版到达终点")
        经验:
- 必须先"爬梯子/滑蛇"再"掷骰子"时,用 
repeat-while可以省一次越界检查。 - 其余情况 
while可读性更高。 
条件语句:if / guard / switch 全维度对比
if 表达式(Swift 5.9+)
            
            
              swift
              
              
            
          
          let temp = 26
// 一行赋值,不再需要三目嵌套
let advice = if temp <= 0 { "穿羽绒服" }
             else if temp >= 30 { "短袖+冷饮" }
             else { "正常穿衣" }
print(advice)   // 正常穿衣
        注意:
- 所有分支必须返回同一类型,否则需要显式标注类型。
 - 可以抛错:
let level = if temp > 100 { throw TempError.boiling } else { "ok" } 
guard:提前退出,减少金字塔
            
            
              swift
              
              
            
          
          func buy(age: Int, stock: Int) {
    guard age >= 18 else {
        print("未成年禁止购买")
        return
    }
    guard stock > 0 else {
        print("库存不足")
        return
    }
    // 以下代码一定是成年人且有库存
    print("购买成功")
}
        guard 与 if 的区别:
- 必须带 
else; else内必须中断控制流(return/break/continue/throw/fatalError);- 解绑变量作用域延续到后续代码,避免多层嵌套。
 
switch:模式匹配大杀器
区间 & 复合值
            
            
              swift
              
              
            
          
          let score = 87
switch score {
case 90...100: print("优秀")
case 80..<90:  print("良好")
case 60..<80:  print("及格")
default:       print("不及格")
}
        tuple + where 条件
            
            
              swift
              
              
            
          
          let point = (2, 2)
switch point {
case (0, 0):                  print("原点")
case (let x, 0):              print("在 x 轴,x=\(x)")
case (0, let y):              print("在 y 轴,y=\(y)")
case (let x, let y) where x == y:  print("在对角线 x=y 上")
default:                      print("其他")
}
        值绑定与复合 case
            
            
              swift
              
              
            
          
          // 复合 case 共享同一段代码
switch "e" {
case "a", "e", "i", "o", "u": print("小写元音")
case "b", "c", "d", "f", "g": print("部分辅音")
default: print("其他字符")
}
// 复合 case 也支持绑定,但要保证类型一致
switch (2, 0) {
case (let d, 0), (0, let d):   // 两个 pattern 都绑定 d 且类型一致
    print("到轴距离为 \(d)")
default:
    break
}
        贯穿:显式 fallthrough
            
            
              swift
              
              
            
          
          let integerToDescribe = 5
var description = "数字 \(integerToDescribe) 是"
switch integerToDescribe {
case 2, 3, 5, 7, 11, 13, 17, 19:
    description += " 质数,且"
    fallthrough          // 继续执行下一个 case
default:
    description += " 是整数。"
}
print(description)   // 数字 5 是 质数,且 是整数。
        控制转移语句:continue / break / fallthrough / return / throw
continue & break 的最常见误区
            
            
              swift
              
              
            
          
          // 去掉小写元音与空格
let puzzleInput = "great minds think alike"
let vowels: Set<Character> = ["a", "e", "i", "o", "u", " "]
var output = ""
for ch in puzzleInput {
    if vowels.contains(ch) {
        continue          // 立即进入下一轮
    }
    output.append(ch)
}
print(output)   // grtmndsthnklk
        带标签的语句:精确跳出血腥嵌套
            
            
              swift
              
              
            
          
          var finalSquare = 25
var square = 0
gameLoop: while true {
    let dice = Int.random(in: 1...6)
    switch square + dice {
    case finalSquare:
        print("刚好到达,游戏胜利")
        break gameLoop      // 跳出 while,不是跳出 switch
    case let n where n > finalSquare:
        print("点数太大,重新掷")
        continue gameLoop   // 继续 while 下一轮
    default:
        square += dice
    }
}
        defer:作用域退出时的"扫尾"利器
            
            
              swift
              
              
            
          
          func updateScore() {
    var score = 10
    if Bool.random() {
        score += 5
        defer { print("本次加分已落地,当前分数:\(score)") }  // 1️⃣ 先写后执行
        defer { score -= 100 }                                // 2️⃣ 再写先执行
        print("离开 if 前 score=\(score)")                      // 15
    }
    print("离开函数前 score=\(score)")                          // -85
}
updateScore()
        规则小结:
- 同一作用域多个 
defer以栈顺序执行(先注册后执行)。 - 无论正常 return、break、continue、throw 都会执行;进程崩溃除外。
 - 典型场景:文件句柄/锁/数据库事务配对释放。
 
API 可用性检查:让旧系统安心升级
            
            
              swift
              
              
            
          
          if #available(iOS 15, macOS 12, *) {
    // 仅 iOS15+/macOS12+ 能走到这里
    print("iOS15+/macOS12+")
} else {
    // 低版本走兼容方案
    print("iOS15以下或者macOS12以下或者其他系统,比如Linex、visionOS")
}
// guard 写法,提前 return
func useNewAPI() {
    guard #available(macOS 12, *) else { return }
    // 以下代码编译器保证只在 macOS12+ 运行
}
        总结
| 控制流元素 | 关键记忆点 | 
|---|---|
| for-in | 可遍历任何 Sequence;字典无序;stride 可跳步 | 
| while vs repeat-while | 是否"先检查" | 
| if 表达式 | 同类型、可抛错、可函数返回值 | 
| guard | 必须 else 中断,解绑变量作用域外可用 | 
| switch | exhaustive、默认不贯穿、支持 tuple/where/值绑定 | 
| defer | 栈式延迟,资源清理黄金搭档 | 
| #available | 编译期+运行期双重保险 | 
扩展思考:把知识迁移到日常开发
- 
日志场景
用
defer在函数出口统一打印耗时,避免早期 return 漏埋点。 - 
资源池
文件句柄获取后立刻写
defer { fclose(fp) },再也不怕忘记关文件。 - 
交互式 UI
利用
stride(from: 0, to: 360, by: 30)生成圆形按钮坐标,一行代码搞定数学。 - 
数据校验
多层
guard提前返回,把"非法输入"挡在门外,主流程保持一级缩进。 
控制流不是"写得出",而是"写得对、写得优雅"。