条件転送文は、コードの制御を転送してコードが実行される順序を変更します。Swift には 5 つの制御転送文があります。
continue
break
fallthrough
return
throw
continue
、break
、fallthrough
文は、以下で説明しています。return
文は Functions で、throw
文は Propagating Errors Using Throwing Functions で説明されています。
continue
continue
文は、実行中のループを停止して、次の周回の初めから再開します。ループを出てしまうのではなく、現在の周回を完了したということです。
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
文の実行を即座に終了させます。
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
が正しく素数として確認されます。
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 マス目に止まるちょうどの数が出るまでサイコロを振る必要があります。
ゲームボードは以前と同じです。
finalSquare
、board
、square
、diceRoll
の値は以前と同じように初期化されます。
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
条件に戻ります。
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.