このページの実行方法
入門のOptionalと関数までを終えた方向けです。例ごとにmain.swiftの全体を置き換え、swift main.swift で実行します。成功例と失敗例の両方を試します。
Windowsでは 入門のコンパイル手順と同じく、main.swiftを書き換えるたびにコンパイルして実行します。
guardで早めに戻る
guard は「この条件が満たされないなら終了する」と書く構文です。else側ではreturnなどで現在の処理を抜けます。取り出した値はguardの後でも使えます。
main.swift(全体を置き換え)SWIFT
func greet(_ name: String?) {
guard let name = name, !name.isEmpty else {
print("名前を入力してください")
return
}
print("こんにちは、\(name)さん")
}
greet("Mity")
greet(nil)
greet("")実行結果OUTPUT
こんにちは、Mityさん
名前を入力してください
名前を入力してくださいOptional chaining
?. を使うと、途中の値がnilならアクセスを中止してnilを返します。?? は最後に表示する代替値を指定します。
main.swift(全体を置き換え)SWIFT
struct Profile { let city: String? }
let profile: Profile? = Profile(city: "東京")
let missing: Profile? = nil
print(profile?.city ?? "未登録")
print(missing?.city ?? "未登録")実行結果OUTPUT
東京
未登録失敗の理由を分ける
文字列を数値へ変換できない場合と、数値が範囲外の場合を別のエラーにします。呼び出し元はそれぞれに合う説明を表示できます。
main.swift(全体を置き換え)SWIFT
enum AgeError: Error {
case notNumber
case outOfRange
}
func parseAge(_ text: String) throws -> Int {
guard let age = Int(text) else { throw AgeError.notNumber }
guard (0...130).contains(age) else { throw AgeError.outOfRange }
return age
}
for text in ["20", "二十", "-1"] {
do {
let age = try parseAge(text)
print("受付: \(age)歳")
} catch AgeError.notNumber {
print("整数で入力してください")
} catch AgeError.outOfRange {
print("0〜130で入力してください")
} catch {
print("予期しないエラーです")
}
}実行結果OUTPUT
受付: 20歳
整数で入力してください
0〜130で入力してくださいtry?とdefer
try? は失敗をnilへ変換します。原因の説明が必要な入力処理ではdo-catchを使います。defer は現在のスコープを離れる直前に実行する処理で、途中のreturnやthrowがあっても呼ばれます。
main.swift(全体を置き換え)SWIFT
enum SampleError: Error { case failed }
func load(_ succeed: Bool) throws -> String {
defer { print("後片付け") }
if !succeed { throw SampleError.failed }
return "読み込み完了"
}
let result = try? load(false)
print(result ?? "読み込めませんでした")実行結果OUTPUT
後片付け
読み込めませんでしたtry! は失敗すると停止します。例外を無視して成功したことにするのではなく、呼び出し元に失敗を伝える方針を決めます。練習:数量の検証
文字列から1〜99の数量を取り出す関数を作ってください。"3"は3、"0"と"abc"は「数量が不正です」と表示します。
解答例と結果を確認する
まず自分で書いてから、処理の順番と結果を比べましょう。
main.swift(全体を置き換え)SWIFT
enum QuantityError: Error { case invalid }
func quantity(_ text: String) throws -> Int {
guard let value = Int(text), (1...99).contains(value) else {
throw QuantityError.invalid
}
return value
}
for text in ["3", "0", "abc"] {
do { print(try quantity(text)) }
catch { print("数量が不正です") }
}実行結果OUTPUT
3
数量が不正です
数量が不正です公式ドキュメントで確認する:Swift言語ガイド