Skip to content

基本

一般的なデータ型を扱い、基本的な構文を書く方法について説明します。

Swiftは、整数用のInt、浮動小数点数用のDouble、真偽値用のBool、テキスト用のStringなど、多くの基本的なデータ型を提供しています。また、コレクション型としてArraySetDictionaryの強力なバージョンを提供しており、それらについては[コレクション型](Collection Types)のセクションで説明されています。

Swiftでは、値を保存し参照するために識別名を持つ変数を使用します。また、値を変更できない変数(定数)を広範囲で利用します。これらの定数は、変更の必要がない値を扱う際に、コードをより安全で意図を明確にするために使用されます。

おなじみの型に加えて、Swiftはタプルのような高度な型も導入しています。タプルを使うと、複数の値をグループ化して扱ったり、関数から複数の値を1つの複合値として返すことができます。

さらに、Swiftは値が存在しない場合を処理するためのオプショナル型も導入しています。オプショナル型は、「値が存在し、xに等しい」という状態と「値が全く存在しない」という状態のどちらかを表現します。

Swiftは型安全な言語です。つまり、コードで扱える値の型を明確にするのを手助けします。例えば、コードのある部分がStringを必要とする場合、型安全性によりIntを誤って渡すことを防ぎます。同様に、非オプショナルなStringを必要とするコードに対して、オプショナルなStringを誤って渡すことも防ぎます。型安全性は、開発プロセスの早い段階でエラーを発見し修正するのに役立ちます。

定数と変数

定数と変数は、特定の型の値(例: 数値10や文字列"Hello")を名前(例: maximumNumberOfLoginAttemptswelcomeMessage)に関連付けます。定数の値は一度設定すると変更できませんが、変数は将来的に異なる値を設定できます。

定数と変数の宣言

定数と変数は使用する前に宣言する必要があります。定数はletキーワード、変数はvarキーワードを使って宣言します。以下は、ユーザーが行ったログイン試行回数を追跡するために定数と変数を使用する例です。

swift
let maximumNumberOfLoginAttempts = 10
var currentLoginAttempt = 0

このコードは次のように読み取れます:

maximumNumberOfLoginAttemptsという新しい定数を宣言し、その値を10に設定します。その後、currentLoginAttemptという新しい変数を宣言し、その初期値を0に設定します。」

この例では、許可されるログイン試行の最大回数は定数として宣言されています。なぜなら、この最大値は変更されないからです。一方、現在のログイン試行回数を記録するカウンタは変数として宣言されています。この値はログイン試行が失敗するたびに増加する必要があるためです。

コード内で保存される値が変更されない場合は、常にletキーワードを使用して定数として宣言してください。値が変化する場合のみ変数を使用します。

定数や変数を宣言する際、上記の例のように宣言の一部として値を与えることができます。また、プログラム内の後で初期値を設定することも可能です。ただし、最初に値を読み取る前に確実に値が設定されている必要があります。

swift
var environment = "development"
let maximumNumberOfLoginAttempts: Int
// maximumNumberOfLoginAttemptsはまだ値を持っていません。

if environment == "development" {
    maximumNumberOfLoginAttempts = 100
} else {
    maximumNumberOfLoginAttempts = 10
}
// これでmaximumNumberOfLoginAttemptsには値が設定され、読み取ることができます。

この例では、最大ログイン試行回数は定数であり、その値は環境に依存します。開発環境では値が100に設定され、それ以外の環境では値が10に設定されます。if文の両方の分岐がmaximumNumberOfLoginAttemptsに値を初期化しており、この定数が必ず値を持つことを保証しています。このように初期値を設定する方法については[定数の宣言](Constant Declaration)を参照してください。

1行で複数の定数や変数をカンマで区切って宣言することもできます:

swift
var x = 0.0, y = 0.0, z = 0.0

型アノテーション

定数や変数を宣言する際に、型アノテーションを指定することで、その定数や変数が保持できる値の種類を明確にすることができます。型アノテーションは、定数または変数名の後にコロン(:)を置き、その後にスペースと使用する型の名前を書くことで指定します。

以下の例では、welcomeMessageという変数に型アノテーションを指定して、この変数がString型の値を保持できることを示しています:

swift
var welcomeMessage: String

この宣言におけるコロンは「〜の型は〜」を意味し、上記のコードは次のように読むことができます:

welcomeMessageという名前の変数をString型として宣言します。」

String型」という表現は、「任意のString値を保持できる」という意味です。これは、「格納可能な値の種類」と考えることができます。

これで、welcomeMessage変数にはエラーなく任意の文字列値を設定できるようになります:

swift
welcomeMessage = "Hello"

同じ型の関連する複数の変数を、1行でカンマ区切りで宣言し、最後の変数名の後に1つの型アノテーションを指定することもできます:

swift
var red, green, blue: Double

注意

実際には型アノテーションを書く必要がある場面は稀です。定数や変数を定義する際に初期値を指定すると、Swiftはその定数や変数に使用する型をほぼ常に推論できます。型安全性と型推論については後述します。上記のwelcomeMessageの例では、初期値が指定されていないため、型アノテーションを使って型を指定しています。

定数と変数の命名

定数や変数の名前には、Unicode文字を含むほぼすべての文字を使用できます:

swift
let π = 3.14159
let 你好 = "你好世界"
let 🐶🐮 = "dogcow"

ただし、名前に空白文字、数学記号、矢印、プライベート用Unicodeスカラー値、線やボックス描画文字を含めることはできません。また、名前を数字で始めることはできませんが、名前の途中に数字を含めることは可能です。

一度特定の型の定数または変数を宣言すると、同じ名前で再宣言することはできません。また、その型とは異なる型の値を保持するように変更することもできません。さらに、定数を変数に変更したり、変数を定数に変更することもできません。

注意

Swiftの予約キーワードと同じ名前を定数や変数に付ける必要がある場合は、名前をバッククォート(`)で囲んで使用します。ただし、予約キーワードを名前として使用するのは、やむを得ない場合のみにしてください。

既存の変数の値を、互換性のある型の別の値に変更することは可能です。次の例では、friendlyWelcomeの値が"Hello!"から"Bonjour!"に変更されています:

swift
var friendlyWelcome = "Hello!"
friendlyWelcome = "Bonjour!"
// friendlyWelcomeは現在"Bonjour!"です。

変数とは異なり、定数の値は設定後に変更することはできません。変更しようとすると、コードのコンパイル時にエラーが報告されます:

swift
let languageName = "Swift"
languageName = "Swift++"
// これはコンパイル時エラーです:languageNameは変更できません。

定数と変数の出力

print(_:separator:terminator:)関数を使用して、定数や変数の現在の値を出力できます:

swift
print(friendlyWelcome)
// "Bonjour!"と出力されます。

print(_:separator:terminator:)関数はグローバル関数で、1つ以上の値を適切な出力先に出力します。例えば、Xcodeでは、この関数の出力はXcodeの「コンソール」ペインに表示されます。separatorおよびterminatorパラメータにはデフォルト値があるため、これらを省略して関数を呼び出すことができます。デフォルトでは、関数は行末に改行を追加して出力を終了します。改行を追加せずに値を出力するには、terminatorに空文字列を渡します:

swift
print(someValue, terminator: "")

デフォルト値を持つパラメータについての詳細は、[デフォルトパラメータ値](Default Parameter Values)を参照してください。

Swiftでは、定数や変数の名前を長い文字列内のプレースホルダーとして含め、それを現在の値に置き換える文字列補間を使用します。名前を括弧で囲み、その前にバックスラッシュを付けて補間します:

swift
print("The current value of friendlyWelcome is \(friendlyWelcome)")
// "The current value of friendlyWelcome is Bonjour!"と出力されます。

注意

文字列補間で使用できるすべてのオプションについては、[文字列補間](String Interpolation)を参照してください。

コメント

コード内にメモやリマインダーとして実行されないテキストを含めるには、コメントを使用します。コメントはコードがコンパイルされる際にSwiftコンパイラによって無視されます。

SwiftのコメントはCのコメントと非常によく似ています。1行コメントは二つのスラッシュ(//)で始まります:

swift
// これはコメントです。

複数行コメントはスラッシュとアスタリスク(/*)で始まり、アスタリスクとスラッシュ(*/)で終わります:

swift
/* これもコメントです。
複数行にわたって書かれています。 */

Swiftでは、Cとは異なり、複数行コメントを他の複数行コメント内にネスト(入れ子)することができます。ネストされたコメントは、最初のコメントブロックを開始し、その中で二つ目のコメントブロックを開始します。その後、二つ目のブロックを閉じてから最初のブロックを閉じます:

swift
/* これは最初の複数行コメントの始まりです。
    /* これは二つ目の、ネストされた複数行コメントです。 */
これは最初の複数行コメントの終わりです。 */

ネストされた複数行コメントを使用すると、既存の複数行コメントを含む大きなコードブロックを簡単かつ迅速にコメントアウトできます。

セミコロン

多くの他の言語とは異なり、Swiftではコード内の各文の後にセミコロン(;)を書く必要はありません。ただし、必要であれば書くことも可能です。ただし、1行で複数の文を書く場合は、セミコロンが必要です:

swift
let cat = "🐱"; print(cat)
// "🐱"と出力されます。

整数

整数とは、小数部分のない数値(例:42や-23)を指します。整数には、符号付き(正、ゼロ、負)と符号なし(正、ゼロ)のものがあります。

Swiftは8、16、32、および64ビット形式の符号付きおよび符号なし整数を提供します。これらの整数は、Cに似た命名規則に従っています。例えば、8ビットの符号なし整数はUInt8型であり、32ビットの符号付き整数はInt32型です。Swiftのすべての型と同様に、これらの整数型の名前は大文字で始まります。

整数の範囲

各整数型の最小値と最大値は、それぞれのminプロパティとmaxプロパティで取得できます:

swift
let minValue = UInt8.min  // minValueは0で、型はUInt8です。
let maxValue = UInt8.max  // maxValueは255で、型はUInt8です。

これらのプロパティの値は、適切なサイズの数値型(上記の例ではUInt8)であり、同じ型の他の値とともに式で使用できます。

Int

通常、コード内で使用する整数のサイズを特定する必要はありません。Swiftは追加の整数型Intを提供しており、これは現在のプラットフォームのネイティブなワードサイズと同じサイズです:

  • 32ビットプラットフォームでは、IntInt32と同じサイズです。
  • 64ビットプラットフォームでは、IntInt64と同じサイズです。

特定のサイズの整数を扱う必要がない限り、整数値には常にIntを使用してください。これにより、コードの一貫性と相互運用性が向上します。32ビットプラットフォームでも、Intは-2,147,483,648から2,147,483,647の範囲の値を格納でき、多くの整数範囲に十分な大きさです。

UInt

Swiftは符号なし整数型UIntも提供しており、これも現在のプラットフォームのネイティブなワードサイズと同じサイズです:

  • 32ビットプラットフォームでは、UIntUInt32と同じサイズです。
  • 64ビットプラットフォームでは、UIntUInt64と同じサイズです。

注意

UIntは、プラットフォームのネイティブなワードサイズと同じサイズの符号なし整数型が明確に必要な場合にのみ使用してください。そうでない場合は、値が非負であることがわかっている場合でもIntを使用する方が推奨されます。一貫してIntを使用することで、コードの相互運用性が向上し、異なる数値型間の変換の必要性を回避し、型推論と一致します。型安全性と型推論については、後述します。

浮動小数点数

浮動小数点数は、小数部分を持つ数値(例:3.14159、0.1、-273.15)です。

浮動小数点型は、整数型よりもはるかに広い範囲の値を表現でき、Int型で格納できる値よりもはるかに大きい値や小さい値を格納できます。Swiftは次の2つの符号付き浮動小数点数型を提供します:

  • Doubleは64ビットの浮動小数点数を表します。
  • Floatは32ビットの浮動小数点数を表します。

注意

Doubleは少なくとも15桁の小数点以下の精度を持ちますが、Floatの精度は最低6桁になる場合があります。どの浮動小数点型を使用するかは、コードで扱う値の性質や範囲によります。どちらの型でも適切な場合は、Doubleが推奨されます。

型安全性と型推論

Swiftは型安全な言語です。型安全な言語は、コードで扱える値の型を明確にすることを奨励します。例えば、コードの一部がStringを必要とする場合、誤ってIntを渡すことはできません。

Swiftが型安全であるため、コードのコンパイル時に型チェックが行われ、型の不一致がエラーとして検出されます。これにより、開発プロセスの早い段階でエラーを発見して修正することができます。

型チェックは、異なる型の値を扱う際のエラーを回避するのに役立ちます。ただし、すべての定数や変数を宣言する際に型を指定する必要があるわけではありません。必要な値の型を指定しない場合、Swiftは型推論を使用して適切な型を決定します。型推論により、コンパイラはコードのコンパイル時に特定の式の型を自動的に推測できます。これは、提供された値を調べるだけで行われます。

型推論のおかげで、SwiftではCやObjective-Cのような言語に比べて型宣言を大幅に減らすことができます。定数や変数は依然として明示的に型付けされていますが、その型を指定する作業の多くは自動で行われます。

型推論は、定数や変数を初期値で宣言する際に特に便利です。これは、定数や変数にリテラル値(リテラル)を割り当てることでよく行われます。リテラル値とは、ソースコードに直接記述される値(以下の例では423.14159など)のことです。

例えば、初期値としてリテラル値42を新しい定数に割り当てると、Swiftはその定数をInt型と推論します。なぜなら、その値が整数に見えるからです:

swift
let meaningOfLife = 42
// meaningOfLifeはInt型と推論されます

同様に、浮動小数点リテラルに型を指定しない場合、SwiftはDouble型を作成するものと推論します:

swift
let pi = 3.14159
// piはDouble型と推論されます

Swiftは、浮動小数点数の型を推論する際に常にDoubleを選択します(Floatではありません)。

整数リテラルと浮動小数点リテラルを式の中で組み合わせると、文脈に基づいてDouble型が推論されます:

swift
let anotherPi = 3 + 0.14159
// anotherPiもDouble型と推論されます

リテラル値3自体には明示的な型がありませんが、加算の一部として浮動小数点リテラルが含まれているため、適切な出力型としてDouble型が推論されます。

数値リテラル

整数リテラルは以下の形式で記述できます:

  • プレフィックスなしの10進数
  • 0bプレフィックスを持つ2進数
  • 0oプレフィックスを持つ8進数
  • 0xプレフィックスを持つ16進数

以下のすべての整数リテラルは10進数で17と同じ値です:

swift
let decimalInteger = 17
let binaryInteger = 0b10001       // 2進数で17
let octalInteger = 0o21           // 8進数で17
let hexadecimalInteger = 0x11     // 16進数で17

浮動小数点リテラルは、10進数(プレフィックスなし)または16進数(0xプレフィックス)として記述できます。必ず小数点の両側に数値(または16進数)が必要です。10進数の浮動小数点数は、オプションの指数を含むことができ、指数は大文字または小文字のeで指定します。一方、16進数の浮動小数点数では、指数が必須で、大文字または小文字のpで指定します。

指数がxである10進数の場合、基数の値は10ˣ倍されます:

  • 1.25e21.25 × 10²、すなわち125.0です。
  • 1.25e-21.25 × 10⁻²、すなわち0.0125です。

指数がxである16進数の場合、基数の値は倍されます:

  • 0xFp215 × 2²、すなわち60.0です。
  • 0xFp-215 × 2⁻²、すなわち3.75です。

以下のすべての浮動小数点リテラルは10進数で12.1875と同じ値です:

swift
let decimalDouble = 12.1875
let exponentDouble = 1.21875e1
let hexadecimalDouble = 0xC.3p0

数値リテラルには、読みやすくするための追加のフォーマットを含めることができます。整数と浮動小数点数の両方に、余分なゼロを追加したり、アンダースコアを含めたりすることが可能です。これらのフォーマットはリテラルの値に影響を与えません:

swift
let paddedDouble = 000123.456
let oneMillion = 1_000_000
let justOverOneMillion = 1_000_000.000_000_1

数値型の変換

コード内で使用するすべての汎用的な整数定数や変数には、Int型を使用してください。値が非負であるとわかっている場合でも同様です。一般的な状況でデフォルトの整数型を使用することで、定数や変数がコード内で即座に相互運用可能になり、整数リテラル値に対する推論型と一致します。

特定のタスクに明示的なサイズのデータ型が必要な場合や、外部ソースからのデータやパフォーマンス、メモリ使用量、その他の最適化が必要な場合にのみ、他の整数型を使用してください。このような場合に明示的なサイズの型を使用することで、意図しない値のオーバーフローを防ぎ、使用されるデータの性質を明確に記述できます。

整数の変換

整数定数や変数に格納できる数値の範囲は、数値型ごとに異なります。例えば、Int8型の定数または変数には-128から127の数値を格納でき、UInt8型には0から255の数値を格納できます。サイズ指定された整数型の範囲を超える数値を格納しようとすると、コードのコンパイル時にエラーが報告されます:

swift
let cannotBeNegative: UInt8 = -1
// UInt8は負の数を格納できないため、エラーが報告されます。
let tooBig: Int8 = Int8.max + 1
// Int8は最大値を超える数値を格納できないため、これもエラーになります。

各数値型が格納できる値の範囲が異なるため、数値型の変換はケースバイケースで明示的に行う必要があります。この明示的なアプローチにより、隠れた変換エラーを防ぎ、コード内で変換の意図を明確に示すことができます。

特定の数値型を別の型に変換するには、既存の値を使用して目的の型の新しい数値を初期化します。以下の例では、定数twoThousandUInt16型、定数oneUInt8型です。これらは同じ型ではないため、直接加算することはできません。この例では、UInt16(one)を呼び出してoneの値で初期化された新しいUInt16を作成し、元の値の代わりに使用しています:

swift
let twoThousand: UInt16 = 2_000
let one: UInt8 = 1
let twoThousandAndOne = twoThousand + UInt16(one)

加算の両側がUInt16型になったため、加算が許可されます。出力定数(twoThousandAndOne)は、UInt16型の2つの値の合計であるため、UInt16型と推論されます。

SomeType(ofInitialValue)は、Swift型のイニシャライザを呼び出して初期値を渡すデフォルトの方法です。この例では、UInt16にはUInt8値を受け取るイニシャライザがあるため、このイニシャライザが使用されてUInt8から新しいUInt16が作成されます。ただし、ここに渡せるのはUInt16がイニシャライザを提供する型だけです。既存の型を拡張して新しい型(独自の型定義を含む)を受け入れるイニシャライザを提供する方法については拡張を参照してください。

整数と浮動小数点数の変換

整数型と浮動小数点数型の間の変換は、明示的に行う必要があります:

swift
let three = 3
let pointOneFourOneFiveNine = 0.14159
let pi = Double(three) + pointOneFourOneFiveNine
// piは3.14159となり、型はDoubleと推論されます

ここでは、定数threeの値がDouble型の新しい値を作成するために使用されています。この変換により、加算の両側が同じ型になり、計算が許可されます。この変換がなければ、加算は許可されません。

浮動小数点数から整数への変換も明示的に行う必要があります。整数型は、DoubleまたはFloatの値を使って初期化することができます:

swift
let integerPi = Int(pi)
// integerPiは3となり、型はIntと推論されます

このように新しい整数値を初期化する際、浮動小数点数の値は常に切り捨てられます。例えば、4.75は4になり、-3.9は-3になります。

注意

数値定数や変数を組み合わせる際の規則は、数値リテラルを組み合わせる際の規則とは異なります。リテラル値3は、リテラル値0.14159と直接加算できます。リテラル値自体には明示的な型がないためです。これらの型は、コンパイラが評価する時点でのみ推論されます。

型エイリアス

型エイリアスは、既存の型に別名を付けるためのものです。typealiasキーワードを使用して型エイリアスを定義します。

型エイリアスは、外部ソースからの特定のサイズのデータを扱う場合など、既存の型を文脈的により適切な名前で参照したい場合に便利です:

swift
typealias AudioSample = UInt16

型エイリアスを定義すると、そのエイリアスを元の名前の代わりに使用できます:

swift
var maxAmplitudeFound = AudioSample.min
// maxAmplitudeFoundは現在0です

ここでは、AudioSampleUInt16のエイリアスとして定義されています。エイリアスであるため、AudioSample.minの呼び出しは実際にはUInt16.minを呼び出します。これにより、変数maxAmplitudeFoundに初期値0が設定されます。

ブール値

Swiftには、Boolという基本的なブール型があります。ブール値は論理的な値と呼ばれ、trueまたはfalseのいずれかのみを持つことができます。Swiftは、ブール定数値truefalseを提供します:

swift
let orangesAreOrange = true
let turnipsAreDelicious = false

orangesAreOrangeturnipsAreDeliciousの型は、それぞれがブールリテラル値で初期化されたことからBoolと推論されています。上記のIntDoubleと同様に、定数や変数をtrueまたはfalseで初期化する場合、Bool型を明示的に宣言する必要はありません。型推論により、Swiftのコードはより簡潔で読みやすくなります。

ブール値は、if文のような条件文で特に役立ちます:

swift
if turnipsAreDelicious {
    print("Mmm, tasty turnips!")
} else {
    print("Eww, turnips are horrible.")
}
// "Eww, turnips are horrible."と出力されます

条件文(例:if文)については、[制御フロー](Control Flow)で詳しく説明します。

Swiftの型安全性により、非ブール値をBoolの代わりに使用することはできません。次の例ではコンパイル時エラーが報告されます:

swift
let i = 1
if i {
    // この例はコンパイルできず、エラーが報告されます
}

しかし、以下の例は有効です:

swift
let i = 1
if i == 1 {
    // この例は正常にコンパイルされます
}

i == 1の比較結果はBool型であるため、この2番目の例は型チェックを通過します。i == 1のような比較については、[基本演算子](Basic Operators)で説明します。

Swiftの型安全性の他の例と同様、このアプローチは偶発的なエラーを回避し、特定のコードセクションの意図が常に明確であることを保証します。

タプル

タプルは、複数の値を1つの複合値にまとめます。タプル内の値は任意の型で構成でき、互いに同じ型である必要はありません。

次の例では、(404, "Not Found")はHTTPステータスコードを表すタプルです。HTTPステータスコードは、ウェブページをリクエストした際にウェブサーバーから返される特別な値です。存在しないウェブページをリクエストすると、ステータスコード404 Not Foundが返されます。

swift
let http404Error = (404, "Not Found")
// http404Errorは型(Int, String)を持ち、値は(404, "Not Found")です

この(404, "Not Found")タプルは、HTTPステータスコードを数値と人間が読める説明という2つの別個の値としてまとめます。このタプルは「型(Int, String)のタプル」と表現できます。

任意の型の組み合わせからタプルを作成することができ、任意の数の異なる型を含むことができます。例えば、(Int, Int, Int)(String, Bool)、さらには他のどのような組み合わせも使用できます。

タプルの内容を個別の定数や変数に分解して、通常通りアクセスすることができます:

swift
let (statusCode, statusMessage) = http404Error
print("The status code is \(statusCode)")
// "The status code is 404"と出力されます
print("The status message is \(statusMessage)")
// "The status message is Not Found"と出力されます

タプルの値の一部のみが必要な場合、タプルを分解する際にアンダースコア(_)を使用して不要な部分を無視できます:

swift
let (justTheStatusCode, _) = http404Error
print("The status code is \(justTheStatusCode)")
// "The status code is 404"と出力されます

また、インデックス番号を使用してタプル内の個々の要素値にアクセスすることもできます(インデックスは0から始まります):

swift
print("The status code is \(http404Error.0)")
// "The status code is 404"と出力されます
print("The status message is \(http404Error.1)")
// "The status message is Not Found"と出力されます

タプルを定義する際に個々の要素に名前を付けることもできます:

swift
let http200Status = (statusCode: 200, description: "OK")

要素に名前を付けた場合、その名前を使って値にアクセスできます:

swift
print("The status code is \(http200Status.statusCode)")
// "The status code is 200"と出力されます
print("The status message is \(http200Status.description)")
// "The status message is OK"と出力されます

タプルは特に関数の戻り値として役立ちます。例えば、ウェブページの取得を試みる関数が、処理の成功または失敗を説明するために(Int, String)型のタプルを返すことができます。異なる型の2つの値を持つタプルを返すことで、単一の値しか返せない場合よりも、関数の結果に関する有用な情報を提供できます。詳細は[複数の戻り値を持つ関数](Functions with Multiple Return Values)を参照してください。

注意

タプルは、関連する値の簡単なグループ化に適しています。ただし、複雑なデータ構造を作成するには適していません。データ構造がより複雑になる場合は、タプルではなくクラスや構造体としてモデル化してください。詳細は[構造体とクラス](Structures and Classes)を参照してください。

オプショナル

オプショナルは、値が存在しない可能性がある場合に使用します。オプショナルは次の2つの可能性を表します:指定された型の値が存在し、オプショナルをアンラップしてその値にアクセスできる場合、または値が全く存在しない場合です。

例えば、値が欠けている可能性がある場合の例として、SwiftのInt型には、文字列値をInt値に変換しようとするイニシャライザがあります。ただし、一部の文字列のみが整数に変換可能です。文字列"123"は数値123に変換できますが、文字列"hello, world"には対応する数値がありません。以下の例では、このイニシャライザを使用して文字列をIntに変換しようとしています:

swift
let possibleNumber = "123"
let convertedNumber = Int(possibleNumber)
// convertedNumberの型は"オプショナルなInt"です

上記のコードでは、イニシャライザが失敗する可能性があるため、IntではなくオプショナルなIntを返します。

オプショナル型を記述するには、オプショナルが含む型の名前の後ろにクエスチョンマーク(?)を付けます。例えば、オプショナルなIntの型はInt?です。オプショナルなIntは、常にInt値を持つか、まったく値を持たないかのいずれかです。それ以外の値(例えばBoolString)を含むことはできません。

nil

オプショナル変数を値がない状態にするには、特別な値nilを代入します:

swift
var serverResponseCode: Int? = 404
// serverResponseCodeには実際のInt値404が含まれています
serverResponseCode = nil
// serverResponseCodeは現在値を持たなくなりました

デフォルト値を指定せずにオプショナル変数を定義すると、その変数は自動的にnilに設定されます:

swift
var surveyAnswer: String?
// surveyAnswerは自動的にnilに設定されます

オプショナルに値が含まれているかどうかを調べるには、if文を使用してオプショナルをnilと比較します。この比較には「等しい」演算子(==)または「等しくない」演算子(!=)を使用します。

オプショナルが値を持つ場合、それは「nilではない」と見なされます:

swift
let possibleNumber = "123"
let convertedNumber = Int(possibleNumber)

if convertedNumber != nil {
    print("convertedNumber contains some integer value.")
}
// "convertedNumber contains some integer value."と出力されます

非オプショナルの定数や変数でnilを使用することはできません。コード内の定数や変数が、特定の条件下で値を持たない場合に対応する必要がある場合は、適切な型のオプショナル値として宣言します。非オプショナル値として宣言された定数や変数は、nilを持たないことが保証されます。非オプショナル値にnilを代入しようとすると、コンパイル時にエラーが発生します。

オプショナルと非オプショナルの値を分離することで、欠けている可能性のある情報を明示的にマークでき、欠けている値を処理するコードを簡単に記述できます。オプショナルを非オプショナルとして誤って扱うことはできません。このような間違いはコンパイル時にエラーとなります。一度値をアンラップすると、その値を処理する他のコードはnilを確認する必要がないため、コードの複数箇所で同じ値を繰り返しチェックする必要がなくなります。

オプショナル値にアクセスする際、コードは常にnilと非nilの両方の場合を処理します。値が欠けている場合には、以下のような処理が可能です:

  • 値がnilの場合、値を操作するコードをスキップする。
  • nil値を伝播する(nilを返す、またはオプショナルチェーンの?.演算子を使用する)。
  • フォールバック値を提供する(??演算子を使用する)。
  • プログラムの実行を停止する(!演算子を使用する)。

注意

Objective-Cでは、nilは存在しないオブジェクトへのポインタです。一方、Swiftでは、nilは特定の型の値が存在しないことを示すものであり、ポインタではありません。オプショナルの型はオブジェクト型だけでなく任意の型に対してnilを設定できます。

オプショナルバインディング

オプショナルバインディングを使用して、オプショナルに値が含まれているかを確認し、値が存在する場合に一時的な定数または変数としてその値を利用可能にします。オプショナルバインディングは、ifguard、およびwhile文と組み合わせて使用でき、オプショナル内の値をチェックして、その値を定数または変数に抽出する操作を1つのアクションで行います。ifguard、およびwhile文の詳細は[制御フロー](Control Flow)を参照してください。

if文でのオプショナルバインディングは次のように記述します:

swift
if let <#constantName#> = <#someOptional#> {
   <#statements#>
}

オプショナルのセクションにあったpossibleNumberの例を、強制アンラップではなくオプショナルバインディングを使って書き直すと、以下のようになります:

swift
if let actualNumber = Int(possibleNumber) {
    print("The string \"\(possibleNumber)\" has an integer value of \(actualNumber)")
} else {
    print("The string \"\(possibleNumber)\" couldn't be converted to an integer")
}
// "The string "123" has an integer value of 123"と出力されます

このコードは以下のように読めます:

Int(possibleNumber)によって返されたオプショナルなIntに値が含まれている場合、その値をactualNumberという名前の新しい定数に設定します。」

変換が成功すると、actualNumber定数はif文の最初のブロック内で利用可能になります。この定数はオプショナル内の値で初期化されており、対応する非オプショナル型を持ちます。この例では、possibleNumberの型はInt?ですが、actualNumberの型はIntになります。

オプショナルに含まれる値にアクセスした後、元のオプショナル定数または変数を参照する必要がない場合、新しい定数または変数に元と同じ名前を使用できます:

swift
let myNumber = Int(possibleNumber)
// ここではmyNumberはオプショナルな整数です
if let myNumber = myNumber {
    // ここではmyNumberは非オプショナルな整数です
    print("My number is \(myNumber)")
}
// "My number is 123"と出力されます

このコードは、myNumberに値が含まれているかを確認することから始まります。もしmyNumberに値が含まれていれば、新しい定数myNumberにその値が設定されます。if文の内部でmyNumberを記述すると、この新しい非オプショナルな定数を参照します。if文の前後でmyNumberを記述すると、元のオプショナル整数定数を参照します。

このようなコードは非常に一般的であるため、オプショナル値をアンラップする際に短縮形を使用できます。アンラップする定数や変数の名前を単独で記述します。この場合、新しいアンラップされた定数や変数は、オプショナル値と同じ名前を暗黙的に使用します:

swift
if let myNumber {
    print("My number is \(myNumber)")
}
// "My number is 123"と出力されます

オプショナルバインディングでは定数だけでなく変数も使用できます。例えば、if var myNumberと記述することで、if文の最初のブロック内でmyNumberの値を操作することができます。この場合、myNumberに対する変更はそのローカル変数にのみ適用され、アンラップされた元のオプショナル定数や変数には影響しません。

1つのif文に、複数のオプショナルバインディングとブール条件を必要に応じて含めることができます。それらをコンマで区切ります。オプショナルバインディングの値のいずれかがnilであるか、ブール条件がfalseと評価される場合、if文全体の条件はfalseと見なされます。次のif文は等価です:

swift
if let firstNumber = Int("4"), let secondNumber = Int("42"), firstNumber < secondNumber && secondNumber < 100 {
    print("\(firstNumber) < \(secondNumber) < 100")
}
// "4 < 42 < 100"と出力されます

if let firstNumber = Int("4") {
    if let secondNumber = Int("42") {
        if firstNumber < secondNumber && secondNumber < 100 {
            print("\(firstNumber) < \(secondNumber) < 100")
        }
    }
}
// "4 < 42 < 100"と出力されます

if文でオプショナルバインディングによって作成された定数や変数は、そのif文の内部でのみ有効です。一方、guard文で作成された定数や変数は、guard文の後に続くコードの行で使用できます。この点については[早期終了](Early Exit)を参照してください。

フォールバック値の提供

値が欠けている場合の別の処理方法は、nil合体演算子(??)を使用してデフォルト値を提供することです。??の左側のオプショナルがnilでない場合、その値がアンラップされて使用されます。そうでなければ、??の右側の値が使用されます。例えば、以下のコードでは、名前が指定されていればその名前で挨拶し、nilであれば一般的な挨拶を使用します。

swift
let name: String? = nil
let greeting = "Hello, " + (name ?? "friend") + "!"
print(greeting)
// "Hello, friend!"と出力されます

??を使用してフォールバック値を提供する方法の詳細は、[nil合体演算子](Nil-Coalescing Operator)を参照してください。

強制アンラップ

プログラマのエラーや状態の破損など、nilが回復不能な失敗を表す場合、オプショナルの名前の末尾に感嘆符(!)を付けることで、基になる値にアクセスできます。これはオプショナルの値を強制アンラップ(force unwrapping)することと呼ばれます。非nilの値を強制アンラップすると、そのアンラップされた値が得られます。nilの値を強制アンラップすると、ランタイムエラーが発生します。

!は実質的にfatalError(_:file:line:)の短縮形です。例えば、以下のコードは同等の2つのアプローチを示しています:

swift
let possibleNumber = "123"
let convertedNumber = Int(possibleNumber)

let number = convertedNumber!

guard let number = convertedNumber else {
    fatalError("The number was invalid")
}

上記のコードの両方のバージョンは、convertedNumberが常に値を持つことに依存しています。この要件をコードの一部として、上記のいずれかのアプローチを使用して記述することで、コードは実行時にその要件が真であることを確認できます。

データ要件の強制や実行時の前提条件のチェックに関する詳細は、[アサーションと前提条件](Assertions and Preconditions)を参照してください。

暗黙的にアンラップされたオプショナル

前述のとおり、オプショナルは定数や変数が「値を持たない」ことを許容することを示します。オプショナルはif文を使って値が存在するかどうかをチェックでき、値が存在する場合にはオプショナルバインディングを使って条件付きでアンラップし、その値にアクセスできます。

場合によっては、プログラムの構造から、オプショナルが一度値を設定された後は常に値を持つことが明らかなことがあります。このような場合、アクセスするたびにオプショナルの値をチェックしてアンラップする必要を取り除くことは有用です。なぜなら、その値が常に存在すると安全に仮定できるからです。

このようなオプショナルは、暗黙的にアンラップされたオプショナルとして定義されます。暗黙的にアンラップされたオプショナルを記述するには、オプショナルにしたい型の後にクエスチョンマーク(String?)ではなく感嘆符(String!)を付けます。使用時にオプショナルの名前の後に感嘆符を付けるのではなく、宣言時にオプショナルの型の後に感嘆符を付けます。

暗黙的にアンラップされたオプショナルは、オプショナルが最初に定義された直後にその値が存在することが確認され、それ以降のすべての時点で値が存在すると確実に仮定できる場合に有用です。Swiftにおける暗黙的にアンラップされたオプショナルの主な用途は、クラスの初期化時です。これは[アンオウンド参照と暗黙的にアンラップされたオプショナルプロパティ](Unowned References and Implicitly Unwrapped Optional Properties)で説明されています。

変数が後でnilになる可能性がある場合は、暗黙的にアンラップされたオプショナルを使用しないでください。変数のライフタイム中にnil値をチェックする必要がある場合は、常に通常のオプショナル型を使用してください。

暗黙的にアンラップされたオプショナルは、内部的には通常のオプショナルですが、アクセスするたびにオプショナル値をアンラップする必要なく、非オプショナルの値のように使用できます。以下の例は、オプショナルな文字列と暗黙的にアンラップされたオプショナルな文字列が、ラップされた値に明示的にStringとしてアクセスする際の動作の違いを示しています:

swift
let possibleString: String? = "An optional string."
let forcedString: String = possibleString! // 明示的なアンラップが必要

let assumedString: String! = "An implicitly unwrapped optional string."
let implicitString: String = assumedString // 自動的にアンラップされる

暗黙的にアンラップされたオプショナルは、必要に応じてオプショナルを強制アンラップする許可を与えていると考えることができます。暗黙的にアンラップされたオプショナル値を使用すると、Swiftは最初にそれを通常のオプショナル値として使用しようとします。オプショナルとして使用できない場合、Swiftは値を強制アンラップします。上記のコードでは、implicitStringが明示的な非オプショナル型のStringであるため、assumedStringの値をimplicitStringに代入する前に、オプショナル値assumedStringが強制アンラップされます。以下のコードでは、optionalStringには明示的な型がないため、それは通常のオプショナルです。

swift
let optionalString = assumedString
// optionalStringの型は"String?"であり、assumedStringは強制アンラップされていません。

暗黙的にアンラップされたオプショナルがnilであり、そのラップされた値にアクセスしようとすると、ランタイムエラーが発生します。これは、値を持たない通常のオプショナルを感嘆符で強制アンラップした場合とまったく同じ結果になります。

暗黙的にアンラップされたオプショナルがnilかどうかは、通常のオプショナルと同じ方法でチェックできます:

swift
if assumedString != nil {
    print(assumedString!)
}
// "An implicitly unwrapped optional string."と出力されます

また、暗黙的にアンラップされたオプショナルをオプショナルバインディングと組み合わせて使用し、その値をチェックしてアンラップすることを1つの文で行うこともできます:

swift
if let definiteString = assumedString {
    print(definiteString)
}
// "An implicitly unwrapped optional string."と出力されます

エラーハンドリング

エラーハンドリングは、プログラムの実行中に遭遇する可能性のあるエラー状態に対応するために使用します。

オプショナルが値の有無を使用して関数の成功や失敗を伝えるのに対し、エラーハンドリングでは失敗の根本原因を特定し、必要に応じてエラーをプログラムの別の部分に伝播できます。

関数がエラー状態に遭遇すると、エラーをスローします。その関数を呼び出した側がエラーをキャッチして適切に対応します。

swift
func canThrowAnError() throws {
    // この関数はエラーをスローする場合があります
}

関数がエラーをスローできることを示すためには、宣言内にthrowsキーワードを含めます。エラーをスローする可能性のある関数を呼び出す際には、式の前にtryキーワードを付けます。

Swiftはエラーを現在のスコープ外に自動的に伝播させ、catch節で処理されるまで待ちます。

swift
do {
    try canThrowAnError()
    // エラーはスローされませんでした
} catch {
    // エラーがスローされました
}

do文は新しいスコープを作成し、エラーが1つ以上のcatch節に伝播することを可能にします。

以下は、エラーハンドリングを使用してさまざまなエラー状態に対応する例です:

swift
func makeASandwich() throws {
    // ...
}

do {
    try makeASandwich()
    eatASandwich()
} catch SandwichError.outOfCleanDishes {
    washDishes()
} catch SandwichError.missingIngredients(let ingredients) {
    buyGroceries(ingredients)
}

この例では、makeASandwich()関数は、きれいな皿がない場合や材料が不足している場合にエラーをスローします。makeASandwich()がエラーをスローできるため、この関数呼び出しはtry式でラップされています。do文でラップすることで、スローされたエラーは指定されたcatch節に伝播されます。

エラーがスローされなかった場合、eatASandwich()関数が呼び出されます。SandwichError.outOfCleanDishesエラーがスローされた場合はwashDishes()関数が呼び出されます。一方、SandwichError.missingIngredientsエラーがスローされた場合は、catchパターンによってキャプチャされた関連する[String]値を使用してbuyGroceries(_:)関数が呼び出されます。

エラーのスロー、キャッチ、伝播については[エラーハンドリング](Error Handling)で詳しく説明されています。

アサーションと前提条件

アサーションと前提条件は、実行時にチェックを行います。これらを使用して、次のコードを実行する前に重要な条件が満たされていることを確認します。アサーションまたは前提条件のブール条件がtrueと評価される場合、コードの実行は通常通り続行します。条件がfalseと評価される場合、プログラムの現在の状態は無効と見なされ、コードの実行は終了し、アプリが終了します。

アサーションと前提条件は、コードを書いている間に仮定や期待を表現するために使用されます。これらをコードの一部として含めることで、開発中に間違いや誤った仮定を見つける手助けとなり、前提条件は本番環境での問題検出に役立ちます。

実行時に期待を確認するだけでなく、アサーションや前提条件はコード内の有用なドキュメントとしても役立ちます。前述のエラーハンドリングで説明したエラー状態とは異なり、アサーションや前提条件は回復可能なエラーや予期されたエラーには使用されません。アサーションや前提条件の失敗は無効なプログラム状態を示します。そのため、失敗したアサーションをキャッチする方法はありません。無効な状態から回復することは不可能です。アサーションが失敗すると、プログラムのデータの少なくとも1つが無効ですが、その原因や他の状態が無効であるかどうかはわかりません。

アサーションや前提条件の使用は、無効な状態を引き起こしにくいコード設計の代わりにはなりません。ただし、有効なデータや状態を強制するために使用することで、無効な状態が発生した場合にアプリがより予測可能な方法で終了し、問題のデバッグが容易になります。仮定がチェックされない場合、この種の問題に気づくのが遅れる可能性があり、コードの別の場所でエラーが発生したり、ユーザーデータが静かに破損したりすることがあります。無効な状態が検出されるとすぐに実行を停止することで、その無効な状態による損害を最小限に抑えることができます。

アサーションと前提条件の違いは、それらがチェックされるタイミングにあります:アサーションはデバッグビルドでのみチェックされますが、前提条件はデバッグビルドと本番ビルドの両方でチェックされます。本番ビルドでは、アサーション内の条件は評価されません。これにより、開発プロセス中にアサーションをいくらでも使用しても、本番環境でのパフォーマンスに影響を与えません。

アサーションによるデバッグ

アサーションは、Swift標準ライブラリのassert(_:_:file:line:)関数を呼び出すことで記述します。この関数には、trueまたはfalseと評価される式と、条件がfalseの場合に表示されるメッセージを渡します。例えば:

swift
let age = -3
assert(age >= 0, "A person's age can't be less than zero.")
// このアサーションは失敗します。なぜなら、-3は>= 0ではないからです。

この例では、age >= 0trueと評価される、つまりageの値が負でない場合、コードの実行は続行されます。上記のコードのようにageの値が負の場合、age >= 0falseと評価され、アサーションが失敗してアプリケーションが終了します。

アサーションメッセージを省略することも可能です。例えば、条件を文章で繰り返すだけの場合などです:

swift
assert(age >= 0)

コード内で条件を既にチェックしている場合には、assertionFailure(_:file:line:)関数を使用してアサーションが失敗したことを示すことができます。例えば:

swift
if age > 10 {
    print("You can ride the roller-coaster or the ferris wheel.")
} else if age >= 0 {
    print("You can ride the ferris wheel.")
} else {
    assertionFailure("A person's age can't be less than zero.")
}

前提条件の強制

前提条件は、条件がfalseになる可能性があるものの、その条件がtrueでなければコードの実行を続行できない場合に使用します。例えば、配列のインデックスが範囲外ではないことや、関数に有効な値が渡されていることを確認するために使用します。

前提条件は、precondition(_:_:file:line:)関数を呼び出すことで記述します。この関数には、trueまたはfalseと評価される式と、条件がfalseの場合に表示されるメッセージを渡します。例えば:

swift
// サブスクリプトの実装内で...
precondition(index > 0, "Index must be greater than zero.")

また、preconditionFailure(_:file:line:)関数を呼び出して失敗が発生したことを示すこともできます。例えば、switch文のデフォルトケースが実行されたが、有効なすべての入力データが他のケースで処理されるべきだった場合などです。

注意

未チェックモード(-Ounchecked)でコンパイルした場合、前提条件はチェックされません。コンパイラは前提条件が常にtrueであると仮定し、それに基づいてコードを最適化します。ただし、fatalError(_:file:line:)関数は、最適化設定に関係なく常に実行を停止します。

プロトタイピングや初期開発中に、まだ実装されていない機能のスタブを作成するためにfatalError("Unimplemented")と記述することができます。fatalErrorはアサーションや前提条件とは異なり、最適化によって取り除かれることはないため、スタブ実装に遭遇した場合に実行が必ず停止することを保証します。