Swift 5.8 日本語化計画 : Swift 5.8


Swift 言語のガイド


Swift の基本


一般的な種類のデータを操作し、基本的な構文を記述します。


Swift は iOS、macOS、 watchOS、及び tvOS アプリ開発のための新しいプログラミング言語です。C または Objective-C での開発経験がある場合は、Swift の多くの部分に慣れているでしょう。


Swift は整数用の Int 型、浮動小数点値用の Double 型や Float 型、ブール値の Bool 型、およびテキストデータ用の String 型などを含む、すべての基本的な C 言語と Objective-C の型の独自のバージョンを提供します。Swift はまた、コレクション型 で説明したように、3つの主要なコレクション型、Array 型と Set 型、 Dictionary 型の、強力なバージョンも提供します。


C と同様に、Swift は名前によって識別し、値を保存し参照するのに変数を使用します。Swift も値を変更できない変数を多用します。これらは定数として知られており、C の定数よりもはるかに強力です。定数は、変更する必要がない値をコードで処理するときの意図をより安全かつ明確にするために Swift 全体で使用されています。


おなじみの型に加えて、Swift は、タプル (tuples) のような、Objective-C では見られない高度な型を導入します。タプルにより、値のグループを作成し周りに渡すことができます。タプルを使用して、単一の混合値として関数から複数の値を返すようにできます。


Swift はまた、値が存在しない物を処理する optional の型も導入します。Optional は、"ここに値 があり、それが X に等しい" かまたは "値が全く ありません" と告げます。Optional を使用するのは Objective-C でポインタに nil を使用することに似ていますが、それらは型に働きますが、クラスには働きません。Optional は、より安全で Objective-C での nil ポインタよりも表現力が高いだけでなく、Swift の最も強力な機能の多くの中心になります。


Swift は 型安全 な言語であり、あなたのコードが操作できる値の型について明確にするのに役立ちます。あなたのコードの一部が String を必要とする場合は、型安全性は誤って Int をそれに渡すのを防ぐことができます。同様に、型安全性は、誤って optional でない String を必要とするコードの一部に optional の String を渡すのを防ぎます。型安全性は、あなたがエラーを catch して、できるだけ早期に開発プロセス中にエラーを修正するのに役立ちます。


定数と変数


定数と変数は、特定の型の値 (数 10"Hello" の文字列のように) に名前 (maximumNumberOfLoginAttempts または welcomeMessage のように) を関連付けます。それが一度設定されると、定数 の値は、変更できず、一方、変数 は、将来的に異なる値に設定できます。


定数と変数の宣言


定数と変数はそれらが使用される前に、宣言されなければなりません。let キーワードで定数を、var キーワードで変数を宣言します。定数および変数を、ユーザがログインしようとした回数を追跡するために使用する例をここに示します。


  1. let maximumNumberOfLoginAttempts = 10
  2. var currentLoginAttempt = 0


このコードは次のように読むことができます。


"maximumNumberOfLoginAttempts という新しい定数を宣言し、それに 10 の値を与えます。そして、 currentLoginAttempt という新しい変数を宣言し、それに初期値 0 を与えます"


この例では、最大値は決して変化しないので、許可されたログイン試行の最大数は、定数として宣言されています。ログイン試行を失敗するたびに、この値を一つ増分しなければならないため、現在のログイン試行カウンタは、変数として宣言されています。


一行に複数の定数や複数の変数を、カンマで区切って宣言することができます。


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



注意: コード内の格納された値は、変更するつもりがない場合は、常に let キーワードで定数として宣言して下さい。変更できるようにする必要がある場合のみ、値を保存するために変数を使用してください。


型注釈


定数または変数を宣言するときには、定数または変数が保存できる値の種類について明確にするため、型注釈 (Type Annotation) を提供できます。型注釈を書くには、定数や変数の名前の後にコロンを書き、空白を続け、使用する型の名前を続けます。


以下の例では、変数は String 値を保存できることを示すために、welcomeMessage という変数の型注釈を提供します。


var welcomeMessage: String


宣言の中のコロンは "...of type...、(...と言う型の...) "と言う意味であり、上記のコードは以下のように読むことができます:


"String 型である welcomeMessage という変数を宣言します。"


"String 型である" のフレーズは、"どんな String 値でも保存することができる。" を意味します。これを、保存できる "物の型" (あるいは "ものの種類")と言う意味だと考えられます。


welcomeMessage 変数は、エラーなしでどんな文字列値にでも設定できます。


welcomeMessage = "Hello"


単一の行に、カンマで区切って、同じ型の複数の関連した変数を定義でき、最後の変数名の後に、単一の型注釈を加えます。


var red, green, blue: Double


注意: 実際に型注釈を書く必要があることは稀でしょう。それが定義された時に、定数または変数の初期値を指定すると、Swift は、型安全性と型推論 で説明したように、その定数または変数に使用される型をほとんど常に推論できます。上記の welcomeMessage の例では、初期値が提供されておらず、welcomeMessage 変数の型は、初期値から推測されるのではなく、型注釈を使用して指定されています。


定数と変数の命名


定数と変数名は、Unicode 文字を含むほとんどの文字を含むことができます。


  1. let π = 3.14159
  2. let 你好 = "你好世界"
  3. let 🐶🐮 = "dogcow"


定数と変数名は空白文字、数学記号、矢印、個人的使用の Unicode スカラー値、またはラインおよびボックス描画文字を含むことはできません。また、数字で始めることは出来ませんが名前の別の場所に含めることができます。


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


注意: Swift の予約語と同じ名前を定数や変数に付ける必要がある場合は、キーワードをバックチック(`)で囲んで下さい。しかし、絶対に選択肢がない場合を除き、キーワードを名前として使用しないでください。


既存の変数の値を互換性のある型の別の値に変更できます。以下の例では、friendlyWelcome の値を "Hello!" から "BonJour!" へと変更しています:


  1. var friendlyWelcome = "Hello!"
  2. friendlyWelcome = "Bonjour!"
  3. // friendlyWelcome is now "Bonjour!"


変数とは違って、定数の値は一度設定されると、変更できません。これを実行しようとすると、コードがコンパイルされるときにエラーとして報告されます。


  1. let languageName = "Swift"
  2. languageName = "Swift++"
  3. // This is a compile-time error - languageName cannot be changed


定数と変数の印刷


print(_:separator:terminator:) 関数で、定数または変数の現在値を印刷できます。


  1. print(friendlyWelcome)
  2. // prints "Bonjour!"


print(_:separator:terminator:) 関数は、適切な出力先に、一つ以上の値を印刷するグローバル関数です。Xcode では、例えば、print(_:separator:terminator:) 関数は Xcode の "コンソール" ペインにその出力を印刷します。separator 及び terminator パラメータはデフォルト値を持っているので、この関数を呼び出すときはそれらを省略できます。デフォルトでは、関数は改行を追加して、行の印刷を終了します。その後で改行なしの値を印刷するには、terminator として空の文字列を渡しますー例えば、print(someValue, terminator: "")。デフォルト値を持つパラメータについては、デフォルトのパラメータ値 を参照してください。


Swift は、長い文字列内のプレースホルダとして定数または変数の名前を含むように 文字列の補間 を使用し、その定数または変数の現在値に置き換えることを Swift に促します。括弧内で名前を包み、開き括弧の前にバックスラッシュしてエスケープします:


  1. print("The current value of friendlyWelcome is \(friendlyWelcome)")
  2. // Prints "The current value of friendlyWelcome is Bonjour!"


注意: 文字列の補間で使用できるすべてのオプションは 文字列補間 で説明されています。


コメント


自分自身へのメモや忘備録として、コード内に実行できないテキストを含むようにコメントを使用します。コードがコンパイルされる時にコメントは Swift コンパイラによって無視されます。


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


// this is a comment


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


  1. /* this is also a comment,
  2. but is written over multiple lines */


C での複数行のコメントとは異なり、Swift での複数行のコメントは、他の複数行のコメント内に入れ子にすることができます。複数行のコメントブロックを開始してから最初のブロック内に第二の複数行コメントを開始することで、入れ子にされたコメントを書く事ができます。第二のブロックは、閉じられ、最初のブロックが続きます。


  1. /* this is the start of the first multiline comment
  2. /* this is the second, nested multiline comment */
  3. this is the end of the first multiline comment */


入れ子にされた複数行のコメントは、コードがすでに複数行のコメントを含んでいても、迅速かつ容易にコードの大きなブロックをコメントアウトすることを可能にします。



セミコロン


他の多くの言語と異なり、コード内の各文の後には Swift はセミコロン(;)を記述する必要はないですが、希望があれば書くことができます。しかし、単一の行に複数の独立した文を書きたい場合にはセミコロンが必要です。


  1. let cat = "🐱"; print(cat)
  2. // Prints "🐱"


整数


整数 (integer) は、42-23 などのように、小数部分がない全ての数字です。整数は符号付き(signed)(正、ゼロ、または負) かまたは符号なし(unsigned)(正またはゼロ)のどちらかです。


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



整数の境界


その minmax プロパティで、各整数型の最小値と最大値にアクセスできます。


  1. let minValue = UInt8.min // minValue is equal to 0, and is of type UInt8
  2. let maxValue = UInt8.max // maxValue is equal to 255, and is of type UInt8


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


Int


ほとんどの場合、コード内で使用するのに、整数の特定のサイズを選択する必要はありません。Swift は、現在のプラットフォームの固有のワードサイズと同じサイズの追加の整数型、Int を提供します:


整数の特定のサイズで作業する必要がない限り、常にコード内の整数値には Int を使用して下さい。これは、コードの一貫性と相互運用性を支援します。32 ビットプラットフォームでも、Int-2,147,483,6482,147,483,647 の間のどんな値でも格納でき、多くの整数の範囲について十分な大きさです。



UInt


Swift はまた、現在のプラットフォームの固有ワードサイズと同じサイズの符号なし整数型、UInt を提供します。


注意: UInt は、プラットフォームの固有ワードサイズと同じサイズの符号なし整数型が明確に必要な場合にのみ使用して下さい。そうでない場合、格納される値が負でないことが知られている場合でも、Int が望ましいです。整数値を Int に一貫して使用するのはコードの相互運用性を助け、異なる数の型の間での変換を避け、安全な型と型推論 で説明したように、整数型推論と一致します。


浮動小数点数


浮動小数点数 (Floating-point numbers) は小数部を持つ数字で、3.141590.1、および -273.15 などです。


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


注意: Double は、少なくとも 15 桁の精度を持っており、一方 Float の精度は 6 桁と少ないです。使用すべき適切な浮動小数点型は、コード内で作業する必要がある値の性質と範囲次第です。どちらの型でもよい状況では、Double が好ましいです。


安全な型と型推論


Swift は、安全な型 (type safe) の言語です。安全な型の言語は、コードが操作できる値の型を明確にすることを奨励します。コードの一部が String を必要としている場合、間違ってそれに Int 型を渡すことはできません。


Swift は、安全型であるため、コードをコンパイルする時、型のチェック (type checks) を行い、あらゆる型の不一致をエラーとしてフラグを立てます。これにより、エラーをキャッチし、できるだけ早期の開発プロセスでエラーを修正できます。


型チェックを使用すると、値の異なる型で作業しているときにエラーを回避できます。しかし、これは、宣言したすべての定数と変数の型を指定する必要があることを意味しません。必要とする値の型を指定しない場合は、Swift は作業すべき適切な型に型推論 (type inference) を使用します。型推論は、単にあなたが提供する値を調べることによって、コードをコンパイルするときに自動的に特定の式の型をコンパイラに推測できるようにします。


型推論があるので、Swift は、C や Objective-C のような言語よりはるかに少ない型宣言しか必要としません。定数と変数は、まだ明示的に型指定されていますが、それらの型を指定する作業の多くはもうすでにに行われています。


初期値で定数または変数を宣言するときに型推論は、特に便利です。これは多くの場合、それを宣言する時点で定数または変数に リテラル値(またはリテラル: literal) を代入することによって行われます。(リテラル値は、下記の例の 423.14159 などのようにソースコード内に直接表示される値です。)


例えば、それがどの型であるか言わずに新しい定数に 42 のリテラル値を代入した場合、整数のように見える数でそれをあなたが初期化したので、Int 型の定数にしたいことを Swift は推論します。


  1. let meaningOfLife = 42
  2. // meaningOfLife is inferred to be of type Int


同じように、浮動小数点リテラルの型を指定しない場合は、Swift はあなたが Double を作成しようとしていることを推論します:


  1. let pi = 3.14159
  2. // pi is inferred to be of type Double


浮動小数点数の型を推論するとき、Swift は、常に(Float というよりも) Double を選択します。


式の中で、整数と浮動小数点リテラルを結合する場合は、Double の型が文脈から推測されます。


  1. let anotherPi = 3 + 0.14159
  2. // anotherPi is also inferred to be of type Double


3 のリテラル値は、それ自体は、明示的な型を持っておらず、Double の適切な出力型は、追加部分の浮動小数点リテラルの存在から推測されます。


数値リテラル


整数リテラルは、以下のように書くことができます。


以下の整数リテラルはすべて、17 の十進数値を表します:


  1. let  decimalInteger = 17
  2. let  binaryInteger = 0b10001 // 17 in binary notation
  3. let  octalInteger = 0o21         // 17 in octal notation
  4. let  hexadecimalInteger = 0x11 // 17 in hexadecimal notation


浮動小数点リテラルは(接頭辞なしの)十進数、または (接頭辞 0x 付きの) 十六進数です。それらはいつも、小数点の両側に数 (または十六進数) を持っていなければなりません。十進小数点数はまた、オプションで累乗(exponent) があり、それは大文字または小文字の e が示し、十六進浮動小数点数では大文字または小文字の p が示します。


十進数の場合、累乗は exp の指数で示し、基本数は 10exp を乗じて示します。


十六進数の場合、累乗は exp の指数で示し、基本数は 2exp を乗じて示します。


以下の浮動小数点リテラルはすべて、12.1875 の十進小数値を示します。


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


数値リテラルは読みやすいように余分の書式設定を含めることができます。整数および浮動小数点数の両方とも、余分なゼロをつめ込まれ、また読みやすさを支援するため、アンダースコアを含めることができます。書式設定のどちらの型も、リテラルの基になる値に影響を与えません。


  1. let paddedDouble =  000123.456
  2. let oneMillion = 1_000_000
  3. let justOverOneMillion = 1_000_000.000_000_1


数値型変換


コード内のすべての汎用整数の定数と変数の型に Int を、これらが負でないことが知られている場合でも使用して下さい。日常の状況で、デフォルトの整数型を使用する事は、整数の定数や変数は、コード内ですぐに相互運用可能になり、整数リテラル値について推論された型と一致することを意味します。


外部ソースからの、明示的にされたサイズのデータのため、それらが具体的に当面のタスクのために必要とされる時にだけ他の整数型を使用するか、または性能、メモリ使用量、またはその他の必要な最適化のため使用して下さい。このような状況で明示的にされたサイズの型を使用すると、偶発的な値のオーバフローをキャッチするのに役立ち、また使用されているデータの性質について暗黙的に説明します。



整数変換


整数の定数または変数に格納できる数値の範囲は、各数値の型ごとに異なります。Int8 の定数や変数は -128127 の間の数を格納できるのに対し、UInt8 の定数や変数は 0255 の間の数を格納できます。サイズの整数型の定数や変数に収まらない数は、コードがコンパイルされる時にエラーとして報告されます。


  1. let cannotBeNegative: UInt8 = -1
  2. // UInt8 cannot store negative numbers, and so this will report an error
  3. let tooBig: Int8 = Int8.max + 1
  4. // Int8 cannot store a number larger than its maximum value,
  5. // and so this will also report an error



各数値型は、値の異なる範囲を格納できるので、ケースバイケースで、数値型の変換を選択しなければなりません。この選択のアプローチは、隠れた変換エラーを防止し、コード内の型変換の意図を明示的にするのに役立ちます。


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


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


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


SomeType(ofInitialValue) は Swift の型のイニシャライザを呼び出し、初期値を渡すためのデフォルトの方法です。舞台裏では、UInt16 には UInt8 値を受け入れるイニシャライザがあるので、このイニシャライザは、既存の UInt8 から新しい UInt16 を作るために使用されます。ただし、それは UInt16 がイニシャライザを提供している型である必要があり、ここでは どの型でも(Any type) 渡すことはできません。既存の型を拡張して (自分の定義した型を含む) 新しい型を受け入れるイニシャライザを提供することについては、拡張機能 で説明します。


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


整数と浮動小数点数の数値型の間の変換は、明示的に行わなければなりません。


  1. let three = 3
  2. let pointOneFourOneFiveNine = 0.14159
  3. let pi = Double(three) + pointOneFourOneFiveNine
  4. // pi equals 3.14159, and is inferred to be of type Double


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


浮動小数点の整数への変換も明示的に行わなければなりません。整数型は、Double または Float 値で初期化することができます。


  1. let integerPi = Int(pi)
  2. // integerPi equals 3, and is inferred to be of type Int


このように、新しい整数値を初期化するために使用すると、浮動小数点値は、常に切り捨てられます。これは 4.754 になることを意味し、-3.9-3 になる事を意味します。


注意: 数値定数と変数を結合する規則は、数値リテラルの規則とは異なります。リテラル値 3 は、それ自体の明示的な型を持っていないため、リテラル値 0.14159 に直接加算することができます。それらの型は、それらがコンパイラによって評価される時にだけ推論されます。

型エイリアス


型エイリアス は、既存の型の別名を定義します。typealias キーワードで、型エイリアスを定義して下さい。


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


typealias AudioSample = UInt16


型エイリアスを一度定義すると、元の名前を使用する所どこでもエイリアスを使用できます。


  1. var maxAmplitudeFound = AudioSample.min
  2. // maxAmplitudeFound is now 0


ここで、AudioSampleUInt16 型のエイリアスとして定義されています。それはエイリアスのため、 AudioSample.min への呼び出しは、実際には UInt16.min を呼び出し、maxAmplitudeFound 変数に初期値 0 を提供します。


ブール型


Swift には Bool と呼ばれる基本的なブール 型があります。ブール値はそれらが true または false にしかならないため、論理型 と呼ばれます。Swift は、truefalse の2つのブール定数値を提供します。


  1. let orangesAreOrange = true
  2. let turnipsAreDelicious = false


orangesAreOrangeturnipsAreDelicious の型は、それらがブール型のリテラル値で初期化されたという事実から Bool 値として推測されています。上記の IntDouble と同様に、それらを作成するやいなや true または false にそれらを設定した場合、Bool として定数または変数を宣言する必要はありません。型推論は、型が既に知られている他の値で、定数または変数を初期化するとき Swift のコードが、より簡潔で読みやすくするのに役立ちます。


if 文などのような条件文を使用するときにブール値は、特に有用です。


  1. if turnipsAreDelicious {
  2. print("Mmm, tasty turnips!")
  3. } else {
  4. print("Eww, turnips are horrible.")
  5. }
  6. // prints "Eww, turnips are horrible."


if 文などのような条件文は フロー制御 で詳しく説明されています。


Swift の型の安全性は、Bool の代わりに、非ブール値を用いることを防ぎます。以下の例は、コンパイル時にエラーを報告します。


  1. let i = 1
  2. if i {
  3. // this example will not compile, and will report an error
  4. }


しかし、以下に示した別の例は有効です。


  1. let i = 1
  2. if i == 1 {
  3. // this example will compile successfully
  4. }


i == 1 を比較した結果は、Bool 型のものであり、従って、この第二の例は、型チェックに合格します。i == 1 のような比較は、基本演算子 で説明されています。


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


タプル


tuples(タプル) は、複数の値を単一の複合値のグループにまとめます。タプル内の値は、任意の型とすることができ、互いに同じ型のものである必要はありません。


以下の例では、(404、"Not Found") は、HTTP ステータスコード を記述するタプルです。HTTP ステータスコードは、Web ページを要求するたびに、Web サーバから返される特別な値です。存在していない web ページを要求すると 404 Not Found のステータスコードが返されます。


  1. let http404Error = (404, "Not Found")
  2. // http404Error is of type (Int, String), and equals (404, "Not Found")


(404、"Not Found") を一緒にタプルのグループにして、HTTP ステータスコードに2つの別個の値を与える IntString にします:数字と人間が読める説明です。これは、"タプル型 (Int,String)" として記述できます。


型の任意の並べ替えからタプルを作成することができ、好きなだけ多くの異なる型を含めることができます。(INT、INT、INT) 型のタプル、または(String、Bool)、または実際にあなたが必要とする他の組み合わせを作ることからあなたを止めるものは何もありません。


別々の定数や変数にタプルの内容を 分解 し、通常どおりにアクセスできます。


  1. let (statusCode, statusMessage) = http404Error
  2. print("The status code is \(statusCode)")
  3. // prints "The status code is 404"
  4. print("The status message is \(statusMessage)")
  5. // prints "The status message is Not Found"


タプルの値の一部だけが必要な場合は、タプルを分解する時に、アンダースコア(_) でタプルの部分を無視します。


  1. let (justTheStatusCode, _) = http404Error
  2. print("The status code is \(justTheStatusCode)")
  3. // prints "The status code is 404"


代わりに、ゼロから始まるインデックス番号を使用してタプルの個別の要素値にアクセスできます。


  1. print("The status code is \(http404Error.0)")
  2. // prints "The status code is 404"
  3. print("The status message is \(http404Error.1)")
  4. // prints "The status message is Not Found"


タプルを定義する時、タプルの個別の要素に名前を付けることができます。


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


タプルの要素に名前を付けた場合には、それらの要素の値にアクセスするのに要素の名前を使用できます。


  1. print("The status code is \(http200Status.statusCode)")
  2. // prints "The status code is 200"
  3. print("The status message is \(http200Status.description)")
  4. // prints "The status message is OK"


タプルは、関数の戻り値として特に有用です。Web ページを検索しようとする関数は、ページ検索の成功または失敗を記述するために (Int,String) のタプル型を返すことがあります。二つの異なる値を持つタプルを戻すことにより、異なる型のそれぞれは、関数が単一の型の単一の値を返すだけよりその結果に関する有用な情報を提供します。詳細については、複数の戻り値を持つ関数 を参照してください。


注意: タプルは、関連する値の単純なグループのために有用です。それらは、複雑なデータ構造体の作成には適していません。データ構造がより複雑になる可能性がある場合は、タプルではなくクラスまたは構造体としてモデル化して下さい。詳細については、構造体とクラス を参照してください。


Optionals


値が存在しなくてもよい状況では optionals を使用して下さい。Optional は、2つの可能性を表現します。値が あり、その値にアクセスするため optional を開封できるか、値が全く ない かです。


注意: optionals の概念は、C や Objective-C には存在しません。Objective-C で最も近いものは、他の時はオブジェクトを返すメソッドから nil を返す機能で、nil は "有効なオブジェクトが存在しない" 事を意味します。しかし、これはオブジェクトでのみ動作し、構造体、基本的な C の型、または列挙値では動作しません。これらの型のために、Objective-C のメソッドは、値がないことを示すために、(例えば NSNotFound など) 特殊な値を通常返します。このアプローチは、メソッドの呼び出し元がそれをチェックするのを忘れず、テストするために特別な値があると知っていることを前提としています。Swift の optionals は、特別な定数を必要とせずに、まったくどの型の値も存在しない ことを示せます。


ここに、optionals が値の存在しない場合に対処するために使用できる方法の例を挙げます。Swift の Int 型には String 値を Int 値に変換しようとするイニシャライザがあります。しかし、必ずしもすべての文字列が整数に変換できるわけではありません。文字列 "123" は、数値 123 に変換することができますが、文字列 "hello, world" には変換すべき明白な数値がありません。


以下の例では、StringInt 型に変換しようとするイニシャライザを使用します。


  1. let possibleNumber = "123"
  2. let convertedNumber = Int(possibleNumber)
  3. // convertedNumber is inferred to be of type "Int?", or "optional Int"


イニシャライザは失敗する可能性があるので、それは Int ではなく optionalInt を返します。optional の IntInt ではなく Int? と書かれます。疑問符は、それが含む値は optional である事を示し、何らかの Int 値を含む場合があり、または まったく値を含んでいない かもしれないことを意味します。(これは、Bool 値または String 値のような、他のものを含めることはできません。それは、Int か、何もないかです。)



nil


特殊な値 nil を代入することによって、値のない状態に optional の変数を設定します。


  1. var serverResponseCode: Int? = 404
  2. // serverResponseCode contains an actual Int value of 404
  3. serverResponseCode = nil
  4. // serverResponseCode now contains no value


注意: nil は optional でない定数や変数では使用できません。コード内の定数または変数を、ある条件下で値が存在しない時に作業する必要がある場合は、必ず適切な型の optional の値としてそれを宣言して下さい。


デフォルト値を設けることなく、optional の変数を定義する場合は、変数は自動的に nil に設定されます:


  1. var surveyAnswer: String?
  2. // surveyAnswer is automatically set to nil


注意: Swift の nil は Objective-C の nil と同じではありません。Objective-C では、nil は、存在しないオブジェクトへのポインタです。Swift では、nil はポインタではなく、特定の型の値が存在しないことです。任意の 型の Optional が nil に設定されるのであって、オブジェクトの型では決してありません。


if 文と強制開封


if 文は、optional が nil と比較して、値を含むかどうかを調べるために使用できます。"等価" 演算子(==)または "非等価"演算子(!=)でこの比較を行って下さい。


Optional が値を持つ場合、それは nil と"等しくない(非等価)" と考えらます。


  1. if convertedNumber != nil {
  2. print("convertedNumber contains some integer value.")
  3. }
  4. // Prints "convertedNumber contains some integer value."


optional が値が含んで いる ことを確認したら、optional の名前の末尾に感嘆符(!)を追加して、その基礎となる値にアクセスできます。感嘆符は効果的に、"この optional は間違いなく値を持っています。どうぞ使って下さい" と告げます。これは、optional の値の 強制開封 として知られています:


  1. if convertedNumber != nil {
  2. print("convertedNumber has an integer value of \(convertedNumber!).")
  3. }
  4. // prints "convertedNumber has an integer value of 123."


if 文の詳細については、フロー制御 を参照してください。



注意: 存在しない optional の値にアクセスするのに ! を使用しようとすると、実行時エラーを引き起こします。! を使用してその値の強制開封をする前に optional が nil 以外の値を含んでいることを常に確認してください。



Optional の結合


Optional が値を含んでいるかどうかを調べるには optional の結合 を使用し、もし値を含んでいれば、一時的な定数または変数としてその値を利用できるようにします。Optional の結合は if および while 文を使って optional の中に値があるかをチェックするのに使われ、単一のアクションの一部として、その値を定数または変数に抽出します。if および while 文は、フロー制御 でより詳しく述べています。



if 文の Optional の結合は以下のように記述します。



if let = {


}



強制開封よりむしろ Optional の結合を使用するには、Optionals セクションから possibleNumber の例を書き直すことができます。


  1. if let actualNumber = Int(possibleNumber) {
  2. print("The String \"\(possibleNumber) \" has an integer value of \(actualNumber)")
  3. } else {
  4. print("The String \"\(possibleNumber)\" could not be converted to an integer")
  5. }
  6. // Prints "The String "123" has an integer value of 123"


このコードは次のように読めます。


"Int(possibleNumber) によって返された optional の Int が値を含む場合、actualNumber と呼ばれる新しい定数を optional に含まれる値に設定します。"


変換が成功した場合、actualNumber 定数は、if 文の最初の分岐内で使用可能になります。これは既に optional の中に 含まれる値で初期化されており、この値にアクセスするのに ! を末尾に付けて使用する必要はありません。この例では、actualNumber は単に変換の結果を印刷するために使用されています。


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


  1. let myNumber = Int(possibleNumber)
  2. // Here, myNumber is an optional integer
  3. if let myNumber = myNumber {
  4. // Here, myNumber is a non-optional integer
  5. print("My number is \(myNumber)")
  6. }
  7. // Prints "My number is 123"


このコードは、前の例のコードと同様に、myNumber に値が含まれているかどうかを確認することから始まります。myNumber に値がある場合、myNumber という名前の新しい定数の値がその値に設定されます。if 文の本体内に myNumber を記述すると、その新しい optional ではない定数が参照されます。if 文の開始前と終了後に myNumber を記述すると、optional の整数定数が参照されます。


この種のコードは非常に一般的であるため、optional の値を開封するために短いスペルを使用できます。開封する定数または変数の名前だけを記述します。新しい開封された定数または変数は、optional の値と同じ名前を暗黙的に使用します。


  1. if let myNumber {
  2. print("My number is \(myNumber)")
  3. }
  4. // Prints "My number is 123"


optional の結合では定数と変数を両方とも使用できます。if 文の最初の分岐内で myNumber の値を操作したい場合は、代わりに if var myNumber と記述できます。また、optional 内に含まれる値は、定数ではなく変数として使用できるようになります。if 文の本体内で myNumber に加えた変更は、そのローカル変数にのみ適用され、開封した元の optional の定数または変数には適用 されません


そうする必要があるならば、単一の if 文内でカンマで区切って、多くの optional の結合とブール条件を含めることができます。optional の結合内の値のいずれかが nil であるか、または任意のブール条件が false に評価された場合、if 文の全体の条件は false と考慮されます。以下の if 文は等価です:


  1. if let firstNumber = Int("4"), let secondNumber = Int("42"), firstNumber < secondNumber && secondNumber < 100 {
  2. print("\(firstNumber) < \(secondNumber) < 100")
  3. }
  4. // Prints "4 < 42 < 100"
  5. if let firstNumber = Int("4") {
  6. if let secondNumber = Int("42") {
  7. if firstNumber < secondNumber && secondNumber < 100 {
  8. print("\(firstNumber) < \(secondNumber) < 100")
  9. }
  10. }
  11. }
  12. // Prints "4 < 42 < 100"


注意: if 文内で optional の結合で作成された定数および変数は、if 文の本体内でのみ、利用可能です。これとは対照的に、guard 文で作成された定数と変数は、早期終了 で説明したように、guard 文の後に続くコードの行で利用できます。


暗黙に開封された Optionals


上述したように、optionals は定数または変数が "値を持たない" 事を許可されていることを示します。if 文で、optionals は値が存在するかどうかをチェックでき、値が存在する場合は、optional の値にアクセスするには、optional の結合で条件付きで開封することができます。


時にはそれは、その値が最初に設定された後に、optional は 常に、値を持つことになる事はプログラムの構造から明らかです。このような場合、常に値があると安全に見なすことができるため、optional の値は常にアクセスされるたびにチェックしたり開封する必要はありません。


optionals のこれらの種類は、暗黙に開封された optionals として定義されています。optional にしたい型の後に疑問符(String?)ではなく感嘆符(String!)を配置して暗黙に開封された Optional を記述して下さい。optional を使用するときに optional の名前の後に感嘆符を置くのではなく、宣言するときに optional の型の後に感嘆符を置きます。


暗黙に開封された optionals は、optional が最初に定義された直後に、間違いなくその後の全ての時点で optional の値が存在すると確信できた時に有用です。所有されていない参照と暗黙に開封された Optional のプロパティ で説明したように、Swift での暗黙に開封された optional の主な用途は、クラスの初期化中にあります。


暗黙に開封された optional は、舞台裏では、通常の optional ですが、また optional でない値のようにも使われ、それがアクセスされるたびにその optional の値を開封する必要はなく、使用できます。以下の例では、明示的に String として開封されていない値にアクセスするときに、optional の文字列と、暗黙に開封された optional の文字列との間の動作の違いを示しています。


  1. let possibleString: String? = "An optional string."
  2. let forcedString: String = possibleString! // requires an exclamation point
  3. let assumedString: String! = "An implicitly unwrapped optional string."
  4. let implicitString: String = assumedString // no need for an exclamation point


暗黙に開封された optional は、必要に応じて optional を強制的に開封する許可を与えると考えることができます。暗黙に開封された optional 値を使用する場合、Swift は最初にそれを通常の optional 値として使おうとします。optional として使用できない場合、Swift は値を強制的に開封します。上記のコードでは、implicitString には明示的で optional でない String の型があるため、optional 値 assumedString は、その値を implicitString に割り当てる前に強制的に開封されます。以下のコードでは、optionalString には明示的な型がないため、通常の optional です。


  1. let optionalString = assumedString
  2. // The type of optionalString is "String?" and assumedString isn't force-unwrapped.


暗黙的に開封された optional が nil であり、開封されていない値にアクセスしようとすると、実行時エラーがトリガーされます。結果は、値を含まない通常の optional の後に感嘆符を配置した場合とまったく同じです。


通常の optional をチェックするのと同じ方法で、暗黙に開封された optional が nil であるかどうかをチェックできます。


  1. if assumedString != nil {
  2. print(assumedString!)
  3. }
  4. // prints "An implicitly unwrapped optional string."


また、単一の文でその値をチェックして開封するために、optional の結合と共に、暗黙に開封された optional も使用できます。


  1. if let definiteString = assumedString {
  2. print(definiteString)
  3. }
  4. // prints "An implicitly unwrapped optional string."


注意: 後の時点で変数が nil になる可能性がある場合には、暗黙に開封された optional を使用しないでください。変数の寿命中に nil の値をチェックする必要がある場合には、必ず通常の optional の型を使用して下さい。


エラー処理


あなたのプログラムが実行中に発生する可能性のあるエラー状態に対処するために エラー処理 を使用して下さい。


関数の成功や失敗を通信するための値の有無を使用できる optionals とは対照的に、エラー処理を使用すると、失敗の基本的な原因を特定し、必要であれば、あなたのプログラムの別の部分にエラーを伝えることができます。


関数がエラー状態に遭遇すると、エラーを throws します。その関数の呼び出し元は、エラーを catch し、適切に対応できます。


  1. func canThrowAnError() throws {
  2. // this function may or may not throw an error
  3. }


関数は、その宣言の中で throws キーワードを含めることによって、エラーを throw できることを示します。エラーを throw できる関数を呼び出すときは、式に try キーワードを付加します。


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


  1. do {
  2. try canThrowAnError()
  3. // no error was thrown
  4. } catch {
  5. // an error was thrown
  6. }


do 文は、エラーが一つ以上の catch 節に伝播できるようにする、新しく含んだスコープを作成します。


以下に、エラー処理が異なるエラー条件に応答するためにどのように使用できるかの例を示します。


  1. func makeASandwich() throws {
  2. // ...
  3. }
  4. do {
  5. try makeASandwich()
  6. eatASandwich()
  7. } catch SandwichError.outOfCleanDishes {
  8. washDishes()
  9. } catch SandwichError.missingIngredients(let ingredients) {
  10. buyGroceries(ingredients)
  11. }


この例では、makeASandwich() 関数は、綺麗な皿が用意されていない場合、またはいずれかの原料が不足している場合、エラーを throw します。makeASandwich() 関数がエラーを throw できるので、関数呼び出しが try 式で包まれています。do 文で関数呼び出しを包むことによって、throw されたエラーは、提供された catch 節に伝達されます。


エラーが throw されない場合、eatASandwich() 関数が呼び出されます。エラーが throw され、それが SandwichError.outOfCleanDishes の case に一致する場合は、washDishes() 関数が呼び出されます。エラーが throw され、それが SandwichError.missingIngredients の case に一致する場合は、buyGroceries(_:) 関数が catch パターンによって捕捉された、関連する [String] の値で呼び出されます。


throw、catch、およびエラーの伝播は、エラー処理 で、より詳細に説明されています。


アサーション(断言)と前提条件


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


アサーションと前提条件を使用して、前提を表現したり、コーディング中に期待していることを表現したりできるので、あなたのコードの一部として組み込むことができます。アサーションは、開発中の間違いや正しくない前提を見つけるのに役立ち、また、前提条件は生産する時の問題の検出に役立ちます。


アサーションと前提条件はまた、実行時の前提を検証することに加えて、コード内のドキュメントの有用な形式になります。上記の エラー処理 で説明したエラー条件とは異なり、アサーションおよび前提条件は、リカバリ可能なまたは予期されるエラーには使用されません。アサーションまたは前提条件のエラーは無効なプログラム状態を示すので、失敗したアサーションを catch する方法はありません。


アサーションと前提条件を使用しても、無効な条件が発生しにくいようにあなたのコードを設計することに代わるものではありません。しかし、有効なデータと状態を強制するためにそれらを使用すると、無効な状態が発生した場合にあなたのアプリが、より予測可能なように終了し、問題をより簡単にデバッグしやすくします。無効な状態が検出されるとすぐに実行を停止することは、その無効な状態によって引き起こされる損傷を制限するのにも役立ちます。


アサーションと前提条件の違いはチェックされたときです。アサーションはビルドをデバッグする時のみチェックされますが、前提条件はビルドのデバッグと製品のビルドの両方でチェックされます。製品のビルドでは、アサーション内の条件は評価されません。つまり、製品のパフォーマンスに影響を与えることなく、開発プロセス中に必要なだけ多くのアサーションを使用できます。


アサーションを使用したデバッグ


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


  1. let age = -3
  2. assert(age >= 0, "A person's age cannot be less than zero")
  3. // this causes the assertion to trigger, because age is not >= 0


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


以下の例のように、散文のように条件を続ける場合には、アサーション·メッセージは、省略できます。


assert(age >= 0)


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


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


前提条件の実施


条件が false である可能性があるときは常に前提条件を使用しますが、コードが実行を継続するためには 必ず true でなければなりません。たとえば、前提条件を使用して、サブスクリプトが範囲外でないことをチェックしたり、関数が有効な値を渡されているかどうかをチェックします。


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


  1. // In the implementation of a subscript...
  2. precondition(index > 0, "Index must be greater than zero.")


また、preconditionFailure(_:file:line:) 関数を呼び出して、障害が発生したことを示すこともできます。たとえば、switch のデフォルトの case が取られたが、すべての有効な入力データが switch のその他のいずれか 1 つの場合で処理された場合。


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

プロトタイプ化や初期開発中に fatalError(_:file:line:) 関数を使用して、まだ実装されていない機能のスタブ(部分) として作成でき、 fatalError("Unimplemented") を記述してスタブの実装に使用できます。致命的なエラーは、アサーションや前提条件とは異なり、決して最適化されないため、スタブの実装に出会うと実行は必ず停止することになります。


前:Swift のツアー 次:基本演算子
















トップへ












トップへ












トップへ












トップへ
目次
Xcode の新機能

Swift について
Swift と Cocoa と Objective-C (obsolete)
Swift Blog より (obsolete)

SwiftLogo
  • Swift 5.8 全メニュー


  • Swift へようこそ

  • Swift 言語のガイド
  • Swift の基本
  • 基本演算子
  • 文字列と文字
  • コレクション型
  • フロー制御
  • 関数
  • クロージャ
  • 列挙型
  • 構造体とクラス
  • プロパティ
  • メソッド
  • サブスクリプト
  • 継承
  • 初期化
  • デイニシャライザ
  • Optional の連鎖
  • エラー処理
  • 同時実行
  • 型キャスト
  • ネストした型
  • 拡張機能
  • プロトコル
  • ジェネリック(汎用)
  • 不透明な型
  • 自動参照カウント
  • メモリの安全性
  • アクセス制御
  • 高度な演算子

  • 言語リファレンス

  • マニュアルの変更履歴













  • トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ