控制转移
本教程共 93 篇 · 第 26 篇 · 更新于 2026-08-08 · 约 9 分钟阅读
本节目标:用 break 跳出、用 continue 跳过本轮、用 fallthrough 主动贯穿,并在嵌套结构里用标签精准指定作用对象。
循环和 switch 默认都是“走完为止”。但现实里你常需要在中途做点特殊操作:某个条件满足就整个人退出循环,或者本轮不想要了直接进下一轮。Swift 用一组“控制转移语句”干这件事,它们能改变代码执行的默认顺序。
1-1 continue:本轮到此为止,下一轮继续
continue 的意思是“当前这轮我处理完了,跳到下一次迭代的开头”。它不会结束整个循环,只结束当前这一轮。
let puzzleInput = "great minds think alike"
var puzzleOutput = ""
let charactersToRemove: [Character] = ["a", "e", "i", "o", "u", " "]
for character in puzzleInput {
if charactersToRemove.contains(character) {
continue
}
puzzleOutput.append(character)
}
print(puzzleOutput)
这段代码想去掉所有元音和空格。遇到要删的字符就 continue,直接跳到下一个字符,不执行后面的 append。最终拼出 "grtmndsthnklk"。
Tip把
continue理解为“这轮我不玩了,下一个谁来”。它特别适合“过滤掉不想要的元素”这类任务,把判断和跳过写在一行,主干逻辑不会被打断。
1-2 break:整个结构立刻结束
break 更彻底:它立刻终止所在的那个循环或 switch,后面的轮次和代码一概不跑。
在循环里,break 跳出整个循环,控制权交到循环后面的代码。在 switch 里,break 用来“匹配但故意什么都不做”(基础章节讲过)。
for number in 1...10 {
if number == 5 {
break
}
print(number)
}
打印 1、2、3、4,遇到 5 就 break,整个循环结束,永远不会到 6。注意它和 continue 的区别:continue 只是跳过本轮,循环还会继续;break 是连循环都不要了。
1-3 fallthrough:主动贯穿到下一个 case
Swift 的 switch 默认不贯穿(基础章节强调过)。但如果你想模拟 C 语言那种“一个 case 跑完接着跑下一个 case”的行为,可以显式写 fallthrough。
let integerToDescribe = 5
var description = "数字 \(integerToDescribe) 是"
switch integerToDescribe {
case 2, 3, 5, 7, 11, 13, 17, 19:
description += "一个质数,同时还是"
fallthrough
default:
description += "一个整数。"
}
print(description)
5 是质数,命中第一个 case,追加文字后用 fallthrough 主动掉进 default,再追加“一个整数。”。最终得到“数字 5 是一个质数,同时还是一个整数。”
Warning
fallthrough不会重新检查下一个 case 的条件,它是无条件地、硬性地跳进下一个 case 的语句体。这和 C 的默认贯穿一致,用的时候心里要有数,别以为它会再匹配一次。绝大多数 Swift 代码根本不需要 fallthrough,只在刻意模拟贯穿行为时才用。
1-4 嵌套结构带来的歧义
当循环套循环、或循环里套 switch,break 和 continue 到底作用于哪一层,就成了问题。默认情况下,break 只结束最内层的那个结构。
for i in 1...3 {
for j in 1...3 {
if j == 2 {
break
}
print("i=\(i), j=\(j)")
}
}
这里的 break 只跳出内层 j 循环。外层 i 循环照常三轮,所以会打印 i=1, j=1、i=2, j=1、i=3, j=1。如果你本意是想让 j==2 时连外层一起停,这个写法就错了。这种歧义在嵌套深的时候特别容易误判。
1-5 带标签语句:指名道姓地控制
为解决上面的歧义,Swift 允许给循环或条件语句加一个标签(label)。标签写在关键字前面,后面跟冒号,然后才是结构本身。
gameLoop: while square != finalSquare {
diceRoll += 1
if diceRoll == 7 { diceRoll = 1 }
switch square + diceRoll {
case finalSquare:
break gameLoop
case let newSquare where newSquare > finalSquare:
continue gameLoop
default:
square += diceRoll
square += board[square]
}
}
gameLoop: 是贴在 while 上的标签。break gameLoop 明确表示“跳出这个 while 循环”,而不是跳出里面的 switch;continue gameLoop 表示“直接进入 while 的下一轮”。标签让控制流向一目了然,不再有“到底作用于哪层”的猜测。
Note标签不是必须用的。只有一层循环时,普通
break/continue就够清楚。只有在嵌套结构里需要精确指定目标时,标签才显出价值。给标签起个有意义的名字(如gameLoop、outerLoop)比用loop1强得多,读代码的人一眼就懂。
1-6 另外两个控制转移语句
Swift 还有 return 和 throw,它们也属于控制转移,但作用对象不同:return 结束整个函数并返回(下一模块讲函数时细说),throw 抛出错误提前退出(错误处理章节会讲)。本章聚焦在循环和 switch 内部常用的 break、continue、fallthrough。
1-7 continue 不能用于 switch
有一点要拎清:break 在循环和 switch 里都能用,但 continue 只能用在循环里。switch 没有“下一轮”的概念,所以在 switch 里写 continue 会编译报错。如果你在 switch 里想“跳过剩下的、去处理下一个数据”,那说明你大概率把 switch 放在了循环里——这时 continue 跳的是外层循环,不是 switch 本身。
1-8 使用建议
控制转移语句用得好能救命,用过头会让流程变得难追。几条经验:
第一,尽量让循环只有一个出口。满屏 break 的代码,读的人很难理清何时退出。能用条件自然结束,就别到处 break。
第二,标签只在真正嵌套时才加。一层循环用 break 足够清楚,乱加标签反而显得你在怀疑自己。
第三,fallthrough 是稀有物。绝大多数 Swift 代码不需要它,遇到别人写的 fallthrough 多看一眼,确认他是真的想要贯穿行为。
记住一个核心区别:continue 是“跳过本轮”,break 是“结束整个”,fallthrough 是“硬闯下一个 case”。配合标签,你就能在任意复杂的嵌套里收放自如。下一章看 guard,它用另一种思路做“提前退出”。
1-9 控制转移与函数返回的关系
break、continue、fallthrough 管的是“循环和 switch 内部”的流向,而函数层面还有个更彻底的退出方式:return。return 不管你嵌套了多少层循环,直接结束整个函数。所以当你在深层循环里发现“可以结束了,而且后面也不用做了”,与其层层 break,不如直接 return(如果语义允许)。
同理,throw 能抛出错误提前退出。这些“退出通道”级别不同:continue 最轻(只跳本轮),break 中等(结束当前结构),return/throw 最重(结束整个函数)。理解这个层级,你就能在合适的粒度上控制流程,不滥用也不欠缺。
控制转移语句本质上是在帮你对“流程”做精细手术。用得克制,代码读起来像顺流而下;用得泛滥,代码就会跳来跳去像断了线的珠子。一个朴素的标准是:如果不用 break/continue 也能把逻辑写清楚,那就不用。把判断写进循环条件本身,往往比在循环体里到处插 break 更清晰。工具在手,分寸在心。