条件転送文は、コードの制御を転送してコードが実行される順序を変更します。Swift には 5 つの制御転送文があります。

  • continue
  • break
  • fallthrough
  • return
  • throw

continuebreakfallthrough 文は、以下で説明しています。return 文は Functions で、throw 文は Propagating Errors Using Throwing Functions で説明されています。

continue

continue 文は、実行中のループを停止して、次の周回の初めから再開します。ループを出てしまうのではなく、現在の周回を完了したということです。

NOTE
条件と加算がある for ループでは、continue 文の後にループの加算が評価されます。ループは通常どおり継続し、ループ内のコードのみスキップされます。

次の例は、難解なパズルフレーズを作成するために、小文字の文字列からすべての母音とスペースを削除しています。

let puzzleInput = "great minds think alike"
var puzzleOutput = ""
for character in puzzleInput.characters {
    switch character {
    case "a", "e", "i", "o", "u", " ":
        continue
    default:
        puzzleOutput.append(character)
    }
}
print(puzzleOutput)
// "grtmndsthnklk" と出力

このコードでは、母音とスペースに一致したときに continue キーワードを呼び出してループの現在の周回を終了し、次の周回の初めにジャンプしています。出力するすべての文字と一致するブロックでなく、母音とスペース文字に一致する(無視する)switch ブロックでこれを使用しています。

break

break 文は、即座に制御フロー文全体の実行を終了します。break 文は、switch やループ文の実行をすぐに終わらせたいときに、switch 文またはループ文の内側で使用することができます。

ループ文での break

ループ文の内側で使用されるとき、break はループの実行を即座に終了し、ループの閉じ括弧 (}) の直後のコードに制御を転送します。ループの現在の周回でのコードはそれ以上実行されず、ループの次の周回も開始されません。

switch 文での break

switch 文の内側で使用されるとき、break は switch 文の実行を即座に終了し、switch 文の閉じ括弧 (}) の直後のコードに制御を転送します。

これを switch 文の複数のケースで使用することができます。Swift の switch 文は、網羅的、かつ空のケースを許容しないため、意図を明確にするために、わざと一致させて無視させるケースが必要になることがあります。無視したいケースの本体に、break 文のみを記述します。このケースが switch 文で一致したとき、ケース内の break 文が switch 文の実行を即座に終了させます。

NOTE
コメントのみを含む switch ケースは、コンパイル時エラーとして報告されます。コメントはステートメント(文)ではなく、無視させる switch ケースにすることはできていません。switch ケースを無視するには、常に break 文を使用してください。

次の例は Character 値の switch で、4 つの言語のうち 1 つの数値記号を表現しているかを判定します。複数の値が 1 つの switch ケースで簡潔にカバーされています。

let numberSymbol: Character = "三"  // 簡体字での数値 3
var possibleIntegerValue: Int?
switch numberSymbol {
case "1", "١", "一", "๑":
    possibleIntegerValue = 1
case "2", "٢", "二", "๒":
    possibleIntegerValue = 2
case "3", "٣", "三", "๓":
    possibleIntegerValue = 3
case "4", "٤", "四", "๔":
    possibleIntegerValue = 4
default:
    break
}
if let integerValue = possibleIntegerValue {
    print("The integer value of \(numberSymbol) is \(integerValue).")
} else {
    print("An integer value could not be found for \(numberSymbol).")
}
// "The integer value of 三 is 3." と出力

この例では、numberSymbol がラテン語、アラビア語、中国語、タイ語での 1 〜 4 を表す数値記号であるかを判定します。一致する場合、switch 文のケースのうち 1 つが、オプショナル Int? 変数の possibleIntegerValue に適切な整数値を設定します。

この例では、switch 文の実行完了後に、値があることを確認するためにオプショナルバインディングを使用しています。変数 possibleIntegerValue は、オプショナル型であるため暗黙的に初期値が nil であり、オプショナルバインディングは switch 文の 4 つのケースによって  possibleIntegerValue が実際の値に設定されているときにのみ成功します。

可能性があるすべての Character 値を列挙することは現実的でないため、一致しないすべての文字を対象とする default ケースとしています。この default ケースにはアクションを実行する必要が無く、本体として break 文が記述されています。default ケースに一致してすぐに、break 文は switch 文の実行を終了し、if let 文からコードの実行を継続します。

フォールスルー

Swift の switch 文は、各ケースの最下部を通過して次のケースにフォールスルーしません。そうではなく、最初に一致したケースを完了後すぐに switch 文全体の実行を終了します。対照的に、C でフォールスルーを防ぐためには、すべての switch ケースの最後に明示的な break 文を置く必要があります。デフォルトでフォールスルーすることがない Swift の switch 文は、C と比較して簡潔で予測しやすく、誤って複数の switch ケースを実行してしまうことを防ぎます。

C スタイルのフォールスルーが必要な場合には、個別に fallthrough キーワードでこの動作にすることができます。次の例では、数値の説明テキストを fallthrough を使って作成しています。

let integerToDescribe = 5
var description = "The number \(integerToDescribe) is"
switch integerToDescribe {
case 2, 3, 5, 7, 11, 13, 17, 19:
    description += " a prime number, and also"
    fallthrough
default:
    description += " an integer."
}
print(description)
// "The number 5 is a prime number, and also an integer." と出力

この例は String 変数 description を宣言して初期値を代入しています。その後、switch 文で integerToDescribe の値を扱っています。integerToDescribe の値がリストにある素数の場合、description の末尾にテキストを追加し、数値が素数であることを追記します。そして、fallthrough キーワードによって default ケースに入ります。default ケースが description の末尾にテキストを追加して、switch 文が完了します。

integerToDescribe の値が素数のリストに無い場合、最初の switch ケースに一致しません。具体的なケースが他に無いため、integerToDescribe は default ケースに一致します。

switch 文の実行完了後、数値の説明が print(_:separator:terminator:) 関数で出力されます。この例では、数値 5 が正しく素数として確認されます。

NOTE
fallthrough キーワードは、フォールスルーした後の switch ケースの条件をチェックしません。fallthrough キーワードは、C の標準 switch 文と同様、単に次のケース(または default ケース)ブロック内に移動してコードを実行します。

ラベル付きステートメント

Swift では、複雑な制御フロー構造にするために、ループや条件文を他のループや条件文でネストすることができます。一方で、ループや条件文は break 文を使用して実行を早々に終了することができます。従って、break 文で終了したいループや条件文を明確にすることは有益です。同じように、複数ネストされたループがある場合、continue 文が影響するループを明確にできることは有益です。

この目的を達成するために、ループ文または条件文にラベルを付けることができます。条件文では、ラベル付きステートメントの実行を終了するために、break 文にラベルを付けることができます。ループ文では、ラベル付きステートメントの実行を終了または継続するために、break または continue 文にラベルを付けることができます。

ラベル付きステートメントは、文のキーワードと同じ行にラベルとコロンを置いて示します。次の例は、このシンタックスの while ループです。すべてのループや switch 文で仕組みは同じです。

label name: while condition {
    statements
}

続く例では、この章ですでに見た「蛇と梯子」ゲームの while ループにラベル付きの break と continue 文を使用しています。今回は、ゲームに追加のルールがあります。

  • 勝利するためには、ちょうど 25 マス目に止まる必要があります。

サイコロを振って 25 マス目を越える場合、25 マス目に止まるちょうどの数が出るまでサイコロを振る必要があります。

ゲームボードは以前と同じです。

image: snakesAndLadders_2x

finalSquareboardsquarediceRoll の値は以前と同じように初期化されます。

let finalSquare = 25
var board = [Int](count: finalSquare + 1, repeatedValue: 0)
board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08
var square = 0
var diceRoll = 0

このバージョンでは、ゲームのロジックを実装するために while ループと switch 文を使用しています。while ループには gameLoop ラベルがあり、蛇と梯子ゲームのメインループであることを示しています。

ちょうど 25 マス目に止まる必要があることを反映して、while ループの条件は while square != finalSquare です。

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]
    }
}
print("Game over!")

各ループの初めにサイコロを振ります。すぐにプレイヤーを移動せず、switch 文で移動の結果を確認し、移動できるかを判断します。

  • サイコロを振ってプレイヤーが最後のマスに止まった場合、ゲーム終了です。break gameLoop 文は、while ループの外側のコード 1 行目に制御を転送し、ゲームを終了します。
  • サイコロを振ってプレイヤーが最後のマスを越えた場合、移動せずに、あらためてサイコロを振ります。continue gameLoop 文は、現在の while ループの周回を終了し、ループの次の周回を開始します。
  • 他のケースでは、サイコロを振って移動します。プレイヤーは diceRoll の数だけ前に進み、蛇と梯子のゲームロジックをチェックします。そしてループを終了し、制御は次のターンが必要かを確認するために while 条件に戻ります。
NOTE

break 文が gameLoop ラベルを使わない場合、while 文ではなく、switch 文を抜けることになります。gameLoop ラベルを使うことで、どのステートメントが終了するかが明確になります。

ループの次の周回にジャンプするために continue gameLoop を呼び出すときに、厳密には gameLoop ラベルを使用する必要はありません。ゲームにはループが 1 つしかないため、どのループに continue 文が影響するのか曖昧ではありません。一方で、continue 文に gameLoop ラベルを使用しても悪影響はありません。そうすることで、並びで使用する break 文のラベルと調和し、読んで理解する際にゲームのロジックがより明確になります。


Portions of this page are translations based on work created and shared by Apple and used according to terms described in the Creative Commons Attribution 4.0 International License.