変数と定数
データの入れ物を定義します。
目的 | 構文 | 説明 | 例 |
---|---|---|---|
変数宣言 | var 名前: 型 = 初期値 |
後から値を変更できる変数を宣言します。型推論が可能な場合は型を省略できます。 |
|
定数宣言 | let 名前: 型 = 初期値 |
一度値を設定すると変更できない定数を宣言します。型推論が可能な場合は型を省略できます。可能な限り let を使うことが推奨されます。✨ |
|
型指定 | var/let 名前: 型 |
明示的に変数や定数の型を指定します。初期値を後で設定する場合などに必要です。 |
|
タプル | (値1, 値2, ...) (名前1: 値1, 名前2: 値2, ...) |
複数の値をまとめて一時的に扱うための複合型です。要素に名前をつけることも可能です。 |
|
オプショナル型 (?)
値が存在しない可能性 (nil
) を表現するための型です。安全な値の取り扱いに不可欠です。🛡️
目的 | 構文 | 説明 | 例 |
---|---|---|---|
宣言 | var/let 名前: 型? var/let 名前: 型! |
? をつけるとオプショナル型になります。初期値は nil です。! は暗黙的アンラップオプショナルで、アクセス時に自動でアンラップされますが、nil だとクラッシュするため注意が必要です。 |
|
Optional Binding (if let / guard let) | if let 定数名 = オプショナル変数 { ... } guard let 定数名 = オプショナル変数 else { ... } |
オプショナル変数が nil でない場合に、アンラップされた値を定数に束縛して安全に利用します。guard は nil の場合に早期リターンするのに便利です。 |
|
Nil-Coalescing Operator (??) | オプショナル変数 ?? デフォルト値 |
オプショナル変数が nil の場合に、?? の右辺のデフォルト値を使用します。 |
|
Optional Chaining (?) | オプショナル変数?.プロパティ オプショナル変数?.メソッド() |
オプショナル変数が nil でない場合にのみ、プロパティアクセスやメソッド呼び出しを実行します。結果もオプショナル型になります。 |
|
強制アンラップ (!) | オプショナル変数! |
オプショナル変数の値を強制的に取り出します。注意: もし変数が nil の場合、実行時エラーでクラッシュします。💥 使用は確実に nil でないと分かっている場合に限定すべきです。 |
|
コレクション型 📚
複数の値をまとめて管理するための型です。
配列 (Array)
順序付けられた値のコレクションです。
目的 | 構文 | 説明 | 例 |
---|---|---|---|
宣言・初期化 | var/let 名前: [型] = [値1, 値2, ...] var/let 名前 = [値1, 値2, ...] var/let 名前: [型] = [] var/let 名前 = [型]() |
特定の型の要素を格納する配列を宣言・初期化します。 |
|
要素へのアクセス | 配列[インデックス] |
指定したインデックス(0から始まる)の要素にアクセスします。範囲外アクセスはエラーになります。 |
|
要素の追加 | 配列.append(要素) 配列 += [要素1, 要素2] |
配列の末尾に要素を追加します。var で宣言された配列のみ変更可能です。 |
|
要素の挿入 | 配列.insert(要素, at: インデックス) |
指定したインデックスに要素を挿入します。 |
|
要素の削除 | 配列.remove(at: インデックス) 配列.removeLast() 配列.removeAll() |
指定したインデックスの要素、最後の要素、または全ての要素を削除します。 |
|
要素数 | 配列.count |
配列に含まれる要素の数を取得します。 |
|
空かどうか | 配列.isEmpty |
配列が空かどうかをBool値で返します。count == 0 より効率的です。 |
|
繰り返し処理 (for-in) | for 要素 in 配列 { ... } |
配列の各要素に対して処理を繰り返します。 |
|
高階関数 (map) | 配列.map { クロージャ } |
各要素に指定した変換処理を適用し、新しい配列を生成します。 |
|
高階関数 (filter) | 配列.filter { クロージャ } |
クロージャが `true` を返す要素だけを含む新しい配列を生成します。 |
|
高階関数 (reduce) | 配列.reduce(初期値) { 結果, 要素 in ... } |
要素を畳み込み、単一の値を生成します(合計、連結など)。 |
|
辞書 (Dictionary)
キーと値のペアを格納する、順序のないコレクションです。🔑
目的 | 構文 | 説明 | 例 |
---|---|---|---|
宣言・初期化 | var/let 名前: [キー型: 値型] = [キー1: 値1, ...] var/let 名前 = [キー1: 値1, ...] var/let 名前: [キー型: 値型] = [:] var/let 名前 = [キー型: 値型]() |
キーと値のペアを格納する辞書を宣言・初期化します。キーはHashableプロトコルに準拠している必要があります (String, Intなど)。 |
|
値へのアクセス | 辞書[キー] |
指定したキーに対応する値にアクセスします。キーが存在しない場合 nil が返るため、結果はオプショナル型になります。 |
|
値の追加・更新 | 辞書[キー] = 値 |
指定したキーに値を設定します。キーが既に存在すれば値が更新され、存在しなければ新しいキーと値のペアが追加されます。var で宣言された辞書のみ変更可能です。 |
|
値の削除 | 辞書[キー] = nil 辞書.removeValue(forKey: キー) |
指定したキーとその値を削除します。removeValue(forKey:) は削除された値をオプショナル型で返します。 |
|
要素数 | 辞書.count |
辞書に含まれるキーと値のペアの数を取得します。 |
|
空かどうか | 辞書.isEmpty |
辞書が空かどうかをBool値で返します。 |
|
繰り返し処理 (for-in) | for (キー, 値) in 辞書 { ... } |
辞書の各キーと値のペアに対して処理を繰り返します。処理される順序は保証されません。 |
|
キーのみ/値のみ取得 | Array(辞書.keys) Array(辞書.values) |
辞書のキーのみ、または値のみを配列として取得します。 |
|
セット (Set)
順序がなく、重複する値を持たないコレクションです。集合演算に便利です。🔢
目的 | 構文 | 説明 | 例 |
---|---|---|---|
宣言・初期化 | var/let 名前: Set<型> = [値1, 値2, ...] var/let 名前: Set = [値1, 値2, ...] var/let 名前 = Set<型>() |
特定の型の要素を格納するセットを宣言・初期化します。要素の型はHashableプロトコルに準拠している必要があります。配列リテラルから初期化できますが、型を明示する必要があります。 |
|
要素の追加 | セット.insert(要素) |
セットに要素を追加します。既に要素が存在する場合は何も起こりません。var で宣言されたセットのみ変更可能です。 |
|
要素の削除 | セット.remove(要素) セット.removeAll() |
指定した要素、または全ての要素を削除します。remove() は削除された要素をオプショナル型で返します(存在しなければ nil )。 |
|
要素の存在確認 | セット.contains(要素) |
セットに指定した要素が含まれているかどうかをBool値で返します。配列よりも高速です。 |
|
要素数 | セット.count |
セットに含まれる要素の数を取得します。 |
|
空かどうか | セット.isEmpty |
セットが空かどうかをBool値で返します。 |
|
繰り返し処理 (for-in) | for 要素 in セット { ... } |
セットの各要素に対して処理を繰り返します。処理される順序は保証されません。 |
|
集合演算 (和集合) | セット1.union(セット2) |
両方のセットに含まれる全ての要素からなる新しいセットを生成します。 |
|
集合演算 (積集合) | セット1.intersection(セット2) |
両方のセットに共通して含まれる要素からなる新しいセットを生成します。 |
|
集合演算 (差集合) | セット1.subtracting(セット2) |
セット1に含まれ、かつセット2に含まれない要素からなる新しいセットを生成します。 |
|
集合演算 (対称差集合) | セット1.symmetricDifference(セット2) |
どちらか一方のセットにのみ含まれる要素からなる新しいセットを生成します。 |
|
集合の比較 (isSubset) | セット1.isSubset(of: セット2) |
セット1がセット2の部分集合であるか(セット1の全要素がセット2に含まれるか)を返します。 |
|
集合の比較 (isSuperset) | セット1.isSuperset(of: セット2) |
セット1がセット2のスーパーセットであるか(セット1がセット2の全要素を含むか)を返します。 |
|
集合の比較 (isDisjoint) | セット1.isDisjoint(with: セット2) |
セット1とセット2が互いに素であるか(共通の要素を持たないか)を返します。 |
|
制御構文 🚦
プログラムの実行フローを制御します。
種別 | 構文 | 説明 | 例 |
---|---|---|---|
if文 | if 条件 { ... } else if 条件 { ... } else { ... } |
条件が真 (true) の場合に特定のコードブロックを実行します。複数の条件分岐や、いずれの条件にも合致しない場合の処理も記述できます。 |
|
guard文 | guard 条件 else { 早期リターン処理; return/throw/break/continue } 後続の処理 (条件が真の場合) |
条件が偽 (false) の場合に、特定のコードブロック(通常は関数の早期リターン)を実行します。条件が真の場合は、guard文以降の処理が続行されます。オプショナルバインディングと組み合わせて使うことが多いです。 |
|
switch文 | switch 評価する値 { case パターン1: ... case パターン2 where 条件: ... default: ... } |
評価する値が特定のパターンに一致する場合に、対応するコードブロックを実行します。Swiftのswitch文は強力で、タプル、範囲、値束縛、where句など多様なパターンマッチングが可能です。網羅的である必要があり、default ケースが不要な場合もあります(enumなど)。 |
|
for-in ループ | for item in コレクション { ... } for i in 範囲 { ... } |
コレクション(配列、辞書、セット、範囲など)の各要素に対して処理を繰り返します。 |
|
while ループ | while 条件 { ... } |
条件が真である間、コードブロックを繰り返し実行します。ループに入る前に条件が評価されます。 |
|
repeat-while ループ | repeat { ... } while 条件 |
コードブロックを最低1回実行し、その後、条件が真である間、繰り返し実行します。ループの最後に条件が評価されます。 |
|
break | break |
現在のループ(for, while, repeat-while)またはswitch文から即座に抜け出します。 |
|
continue | continue |
現在のループの反復処理を中断し、次の反復処理を開始します。 |
|
fallthrough | fallthrough |
switch文のcaseブロック内で使用し、そのcaseの実行が完了した後、次のcaseブロック(通常は実行されない)へ制御を移します。C言語スタイルの動作が必要な稀なケースで使用されます。 |
|
関数とクロージャ ⚙️
特定のタスクを実行するコードのまとまりです。
関数 (Function)
目的 | 構文 | 説明 | 例 |
---|---|---|---|
基本定義 | func 関数名(引数ラベル パラメータ名: 型, ...) -> 戻り値の型 { ... return 戻り値 } |
名前、引数、戻り値を持つ関数を定義します。引数ラベルは関数呼び出し時に使用し、パラメータ名は関数内部で使用します。戻り値がない場合は -> Void または省略可能です。 |
|
引数ラベル省略 | func 関数名(_ パラメータ名: 型) { ... } |
引数ラベルを _ にすると、関数呼び出し時にラベルを省略できます。 |
|
デフォルト引数値 | func 関数名(パラメータ名: 型 = デフォルト値) { ... } |
引数にデフォルト値を設定できます。呼び出し時にその引数を省略するとデフォルト値が使用されます。 |
|
可変長引数 | func 関数名(パラメータ名: 型...) { ... } |
... をつけると、同じ型の引数を0個以上受け取れます。関数内では配列として扱われます。 |
|
inoutパラメータ | func 関数名(引数ラベル パラメータ名: inout 型) { ... } 関数呼び出し: 関数名(引数ラベル: &変数) |
関数の内部で引数として渡された変数の値を直接変更できるようにします。呼び出し時には変数名の前に & をつけます。値型(構造体、enumなど)の変数を関数内で変更したい場合に使用します。 |
|
関数型 | (引数の型) -> 戻り値の型 |
関数の型自体を変数や定数に代入したり、別の関数の引数や戻り値として使用できます。 |
|
クロージャ (Closure)
自己完結型のコードブロックで、変数や定数に代入したり、関数の引数として渡したりできます。関数は名前付きクロージャの一種です。
目的 | 構文 | 説明 | 例 |
---|---|---|---|
基本構文 | { (パラメータ) -> 戻り値の型 in 実行コード } |
中括弧 {} で囲まれたコードブロックです。パラメータ、戻り値の型、in キーワードで本体と区切られます。型推論が可能な場合は、多くを省略できます。 |
|
後置クロージャ (Trailing Closure) | 関数名() { クロージャ本体 } 関数名(引数) { クロージャ本体 } |
関数の最後の引数がクロージャである場合、関数呼び出しの括弧 () の外にクロージャを記述できます。可読性が向上します。最後の引数以外にもクロージャがある場合でも、最後の引数であれば使えます。 |
|
値のキャプチャ | (特別な構文なし) | クロージャは、それが定義されたコンテキスト(周囲のスコープ)にある定数や変数をキャプチャして保持できます。元のスコープが消滅した後でも、それらの値にアクセスしたり変更したりできます。 |
|
エスケープクロージャ (@escaping) | func 関数名(completion: @escaping (引数) -> 戻り値型) |
関数の引数として渡されたクロージャが、関数の実行が終了した後(例: 非同期処理の完了ハンドラなど)に呼び出される可能性があることを示します。明示的に @escaping をつける必要があります。 |
|
オートクロージャ (@autoclosure) | func 関数名(predicate: @autoclosure () -> Bool) |
引数として渡された式を自動的にクロージャでラップします。これにより、呼び出し側では通常の式のように記述できますが、実際にはクロージャとして渡されます。遅延評価などに使われます。assert 関数などで利用されています。 |
|
構造体とクラス 🏛️
独自のデータ型を定義するための構成要素です。
機能 | 構造体 (struct) | クラス (class) | 説明 |
---|---|---|---|
定義 | struct 名前 { ... } |
class 名前 { ... } |
プロパティやメソッドを持つ新しい型を定義します。 |
インスタンス化 | let instance = 名前(引数...) |
let instance = 名前(引数...) |
定義した型から具体的なオブジェクト(インスタンス)を生成します。イニシャライザ (init ) が呼び出されます。 |
プロパティ | Stored / Computed | Stored / Computed | インスタンスに関連付けられた値 (Stored) や、計算によって値を返すプロパティ (Computed) を定義できます。 |
メソッド | Instance / Type | Instance / Type | インスタンスや型自体に関連付けられた関数(操作)を定義できます。 |
イニシャライザ | init(引数...) { ... } (デフォルトあり) |
init(引数...) { ... } (デフォルトなし、必須) |
インスタンス生成時に初期設定を行うためのメソッドです。クラスは全てのStoredプロパティを初期化するイニシャライザが必須です(デフォルトイニシャライザは条件付きで生成)。構造体はメンバワイズイニシャライザが自動生成されることがあります。 |
デイニシャライザ | なし | deinit { ... } |
クラスのインスタンスがメモリから解放される直前に呼び出される処理です。リソースのクリーンアップなどに使用します。 |
型 | 値型 (Value Type) | 参照型 (Reference Type) | 最重要の違い! 構造体のインスタンスは代入や関数渡し時にコピーされます。クラスのインスタンスは代入や関数渡し時に参照(メモリ上のアドレス)がコピーされ、同じインスタンスを指します。🔗 |
継承 | 不可 ❌ | 可能 ✅ (class SubClass: SuperClass ) |
クラスは他のクラスの特性(プロパティ、メソッド)を引き継ぐことができます。構造体は継承できません。 |
利用推奨場面 | データのカプセル化、状態が少ない、同等性を値で比較、コピーが望ましい場合(スレッドセーフなど) | アイデンティティ(同一性)が重要、状態が多い、Objective-Cとの連携、継承が必要な場合 | 一般的に、シンプルなデータ構造には構造体を、より複雑なオブジェクトや状態管理にはクラスを使用します。Swiftでは構造体が推奨される場面が多いです。 |
コード例
// --- 構造体 (値型) ---
struct Point {
var x: Double
var y: Double
// メソッド
func distance(to other: Point) -> Double {
let dx = other.x - self.x
let dy = other.y - self.y
return sqrt(dx * dx + dy * dy)
}
// mutatingメソッド (自身のプロパティを変更)
mutating func moveBy(x deltaX: Double, y deltaY: Double) {
x += deltaX
y += deltaY
}
}
var p1 = Point(x: 1.0, y: 2.0) // メンバワイズイニシャライザが自動生成
var p2 = p1 // 値がコピーされる
p2.x = 3.0
print(p1.x) // 1.0 (p1は影響を受けない)
print(p2.x) // 3.0
p1.moveBy(x: 0.5, y: 0.5)
print(p1) // Point(x: 1.5, y: 2.5)
// --- クラス (参照型) ---
class Person {
var name: String
var age: Int
weak var bestFriend: Person? // 循環参照を避けるための弱参照 (後述)
// イニシャライザ (必須)
init(name: String, age: Int) {
self.name = name
self.age = age
print("\(name) が生成されました")
}
// メソッド
func celebrateBirthday() {
age += 1
print("Happy Birthday \(name)! You are now \(age).")
}
// デイニシャライザ (クラスのみ)
deinit {
print("\(name) が解放されます")
}
}
var personA: Person? = Person(name: "Alice", age: 30)
var personB = personA // 参照がコピーされる (同じインスタンスを指す)
personB?.name = "Alicia"
print(personA?.name ?? "nil") // Alicia (personAも変更される)
personA?.celebrateBirthday() // Happy Birthday Alicia! You are now 31.
print(personB?.age ?? 0) // 31
personA = nil // personAの参照を解放
personB = nil // personBの参照も解放 (ここで参照カウントが0になり deinit が呼ばれる)
// 出力: Alicia が解放されます
プロトコルとエクステンション 🧩
型の機能や振る舞いを定義し、拡張するための仕組みです。
プロトコル (Protocol)
特定の機能や適合条件を定義するブループリント(設計図)です。クラス、構造体、enum はプロトコルに準拠することで、その機能を持つことを保証します。
目的 | 構文 | 説明 | 例 |
---|---|---|---|
定義 | protocol プロトコル名 { プロパティ要件; メソッド要件; イニシャライザ要件; ... } |
準拠する型が実装すべきプロパティ、メソッド、イニシャライザなどを定義します。具体的な実装は含みません。 |
|
準拠 | struct/class/enum 型名: プロトコル1, プロトコル2 { ... } |
クラス、構造体、またはenumがプロトコルを採用し、定義された要件を全て実装します。クラスがスーパークラスを持つ場合は、スーパークラス名の後にプロトコル名を記述します。 |
|
プロトコル型としての利用 | var/let 変数名: プロトコル名 |
プロトコル名を型として使用できます。そのプロトコルに準拠する任意の型のインスタンスを代入できます。これにより、具体的な型に依存しない柔軟なコードが書けます(ポリモーフィズム)。 |
|
委譲 (Delegate) パターン | プロトコルを使って実装 | あるオブジェクト(委譲元)が、自身の処理の一部を別のオブジェクト(デリゲート)に委任するデザインパターンです。プロトコルで委任するメソッドを定義し、デリゲートオブジェクトがそのプロトコルに準拠して実装します。iOS/macOS開発で多用されます。 |
|
オプショナル要件 (@objc) | @objc protocol プロトコル名 { @objc optional func メソッド要件(...) } |
Objective-Cとの互換性のために、プロトコルのメソッドやプロパティをオプショナル(実装が任意)にできます。プロトコルと要件の両方に @objc が必要です。Swiftのみで使用する場合は、プロトコルを分割するなどの代替案が推奨されます。 |
|
エクステンション (Extension)
既存のクラス、構造体、enum、またはプロトコルに新しい機能(メソッド、コンピューテッドプロパティ、イニシャライザなど)を追加します。元のソースコードを変更できない型に対しても機能拡張が可能です。
目的 | 構文 | 説明 | 例 |
---|---|---|---|
機能追加 | extension 型名 { 新しいメソッド/プロパティ/イニシャライザなど } |
既存の型に、新しいインスタンスメソッド、タイプメソッド、コンピューテッドプロパティ、イニシャライザを追加します。Storedプロパティや既存の機能の上書きはできません。 |
|
プロトコル準拠の追加 | extension 型名: プロトコル名 { プロトコルの要件を実装 } |
既存の型を、後からプロトコルに準拠させることができます。これにより、コードの整理や、外部ライブラリの型への適合などが可能になります。 |
|
プロトコルへのデフォルト実装 | extension プロトコル名 { デフォルトのメソッド/プロパティ実装 } |
プロトコル自体を拡張して、メソッドやコンピューテッドプロパティのデフォルト実装を提供できます。プロトコルに準拠する型は、必要に応じてこのデフォルト実装をそのまま使うか、独自にオーバーライドできます。 |
|
ジェネリクス (Generics)
特定の型に依存しない、柔軟で再利用可能なコードを書くための機能です。型をパラメータとして扱います。
目的 | 構文 | 説明 | 例 |
---|---|---|---|
ジェネリック関数 | func 関数名<T>(引数: T, ...) -> T { ... } |
任意の型 T (型パラメータ) を受け入れる関数を定義します。T はプレースホルダーであり、関数呼び出し時に具体的な型が決定されます。複数の型パラメータ (<T, U> など) も可能です。 |
|
ジェネリック型 | struct/class/enum 型名<T> { ... プロパティやメソッドでTを使用 ... } |
任意の型 T を要素として保持したり、操作したりできる構造体、クラス、またはenumを定義します。Swift標準ライブラリの Array<Element> , Dictionary<Key, Value> , Optional<Wrapped> などが代表例です。 |
|
型制約 (Type Constraint) | func 関数名<T: プロトコル名>(...) struct 型名<T: クラス名> { ... } func 関数名<T>(...) where T: プロトコル1, T: プロトコル2, T == U.AssociatedType { ... } |
ジェネリック型パラメータ T が、特定のクラスを継承していることや、特定のプロトコルに準拠していることを要求します。これにより、T が持つべきメソッドやプロパティを保証し、ジェネリックコード内で安全に利用できます。where 句を使うと、より複雑な制約(複数のプロトコル、関連型との比較など)を指定できます。 |
|
プロトコルの関連型 (Associated Type) | protocol プロトコル名 { associatedtype 型名 } |
プロトコルの定義内で、具体的な型を後で(プロトコルに準拠する型によって)決定するためのプレースホルダー名を指定します。ジェネリック型における型パラメータに似ていますが、プロトコル定義内で使用されます。 |
|
エラーハンドリング ⚠️
プログラム実行中に発生する可能性のあるエラーに対処するための仕組みです。Swiftでは Error
プロトコルと do-catch
, try
, throw
を使ってエラーを表現し、伝播させ、処理します。
目的 | 構文 | 説明 | 例 |
---|---|---|---|
エラー型の定義 | enum エラー名: Error { case エラーケース1; case エラーケース2(associatedValue: 型) } |
エラーの種類を表現するためのカスタム型を定義します。通常、Error プロトコルに準拠した enum を使用します。関連値 (Associated Values) を使って、エラーに関する追加情報を持たせることができます。 |
|
エラーのスロー | throw エラーインスタンス func 関数名(...) throws -> 戻り値型 |
関数やメソッドがエラーを引き起こす可能性があることを示すには、関数の宣言に throws キーワードを追加します。関数内でエラーが発生した場合、throw を使ってエラーを呼び出し元に伝播させます。 |
|
エラーのキャッチ (do-catch) | do { 処理1: let result = try スローする可能性のある関数() ... } catch パターン1 { エラー処理1 } catch パターン2 where 条件 { エラー処理2 } catch { 未知のエラー処理 } |
throws キーワードを持つ関数を呼び出すには、try キーワードを前置し、その呼び出しを do ブロックで囲みます。catch ブロックで、発生したエラーの型やパターンに応じて処理を分岐します。 |
|
エラー変換 (try?) | let result = try? スローする可能性のある関数() |
throws 関数を呼び出し、エラーが発生した場合は結果を nil に、成功した場合は結果をオプショナル型でラップして返します。エラーの詳細情報は失われますが、エラー処理を簡潔に書きたい場合に便利です。 |
|
エラー強制解決 (try!) | let result = try! スローする可能性のある関数() |
throws 関数を呼び出し、エラーが発生しないことが確実であると想定する場合に使用します。もし実行時にエラーが発生した場合、プログラムはクラッシュします💥。try! の使用は、エラーが決して起こりえないことが証明できる場合に限定すべきです。 |
|
defer文 | defer { 実行したい処理 } |
defer ブロック内のコードは、現在のスコープ(関数、doブロックなど)から退出する直前に必ず実行されます。エラーが発生して途中で退出する場合でも、正常に完了して退出する場合でも実行されます。リソースのクリーンアップ(ファイルハンドルを閉じる、ロックを解除するなど)に非常に便利です。 |
|
非同期処理 (Concurrency) ⏳
時間のかかる処理(ネットワーク通信、ファイルI/Oなど)を、メインスレッドをブロックせずに実行するための仕組みです。Swift 5.5以降、async/await
, Task
, actor
といった構造化された並行処理機能が導入されました。
機能 | 構文 / キーワード | 説明 | 例 |
---|---|---|---|
非同期関数 (async) | func 関数名(...) async -> 戻り値型 func 関数名(...) async throws -> 戻り値型 |
関数が非同期に実行され、処理の途中で中断・再開する可能性があることを示します。throws と同様に、関数のシグネチャに async キーワードを追加します。エラーをスローする可能性のある非同期関数は async throws と記述します。 |
|
非同期関数の呼び出し (await) | let result = await 非同期関数(...) let result = try await スローする非同期関数(...) |
async 関数を呼び出す際に、その関数の完了を待つ必要がある場所で await キーワードを使用します。await は中断ポイントとなり、システムは他のタスクを実行できます。非同期関数が throws する場合は try await を使用します。await は別の async 関数や Task の中など、非同期コンテキスト内でのみ使用できます。 |
|
タスク (Task) | Task { await 非同期処理 } Task(priority: .background) { ... } let task = Task { ... }; task.cancel() |
非同期処理を実行するための単位です。Task { ... } の形式で、同期的なコードから非同期処理を開始できます。タスクは優先度を指定したり、外部からキャンセルしたりできます。 |
|
構造化された並行性 (Structured Concurrency) | async let TaskGroup |
複数の非同期タスクを並行に実行し、それら全ての結果を待つための仕組みです。async let は少数の固定されたタスクを並行実行するのに便利です。TaskGroup は動的な数のタスクを管理するのに適しています。タスクの親子関係が明確になり、エラーハンドリングやキャンセルが容易になります。 |
|
アクター (Actor) | actor アクター名 { ...状態 (プロパティ)... メソッド... } await アクターインスタンス.メソッド() nonisolated func メソッド() { ... } |
アクターは、内部の状態(プロパティ)へのアクセスを保護し、データ競合を防ぐための参照型です。アクターの外部からそのプロパティやメソッド(nonisolated でないもの)にアクセスするには、常に await が必要です。これにより、一度に一つのタスクだけがアクターの状態を変更できることが保証され、スレッドセーフな状態管理が容易になります。 |
|
メインアクター (@MainActor) | @MainActor class/struct/func/var ... |
UI更新など、メインスレッドで実行する必要があるコードを指定するためのグローバルアクターです。クラス、構造体、関数、プロパティ全体に @MainActor を付与すると、そのコードは常にメインスレッドで実行されることが保証されます。個別の処理をメインスレッドで実行したい場合は await MainActor.run { ... } を使用します。 |
|
メモリ管理 (ARC) 🧠
SwiftはARC (Automatic Reference Counting) を使用して、クラスインスタンスのメモリを自動的に管理します。インスタンスへの参照がいくつ存在するかを追跡し、参照カウントが0になったときにインスタンスが使用していたメモリを解放します。
通常は意識する必要はありませんが、循環参照 (Retain Cycle) を引き起こさないように注意が必要です。これは、2つ以上のクラスインスタンスが互いを強く参照し合い、参照カウントが0にならずメモリリークが発生する状況です。
参照の種類 | キーワード | 説明 | 使用例 / 状況 |
---|---|---|---|
強参照 (Strong Reference) | (デフォルト、キーワードなし) | インスタンスへの通常の参照です。参照が存在する限り、インスタンスはメモリ上に保持され、参照カウントを増やします。 |
|
弱参照 (Weak Reference) | weak var 変数名: 型? |
インスタンスへの参照を持ちますが、参照カウントを増やしません。参照先のインスタンスが解放されると、自動的に nil になります。そのため、弱参照は常にオプショナル型 (? ) の変数 (var ) として宣言する必要があります。循環参照を解決する一般的な方法です。 |
状況: 一方のインスタンスがもう一方を所有するが、所有される側も所有者を参照する必要がある場合(例: Delegateパターン、親子関係)。ライフサイクルが独立している可能性がある場合。
|
非所有参照 (Unowned Reference) | unowned var/let 変数名: 型 |
弱参照と同様に参照カウントを増やしませんが、参照先のインスタンスが解放された後も nil になりません。解放されたインスタンスにアクセスしようとするとクラッシュします💥。参照先のインスタンスが、非所有参照を持つインスタンスよりも常に長く生存することが保証されている場合に使用します。そのため、通常はオプショナル型ではなく、定数 (let ) で宣言されることも多いです。 |
状況: 2つのインスタンスが常に同時に破棄される、または一方が他方なしには存在しえず、他方が常に先に破棄されないことが確実な場合。ライフサイクルが密接に関連している場合。
|
クロージャ内のキャプチャリスト | { [weak self, unowned other] (引数) -> 戻り値型 in ... } |
クロージャがクラスインスタンスのメソッドやプロパティを参照する場合、暗黙的にそのインスタンスへの強参照をキャプチャし、循環参照を引き起こす可能性があります(特にクロージャがインスタンスのプロパティとして保持される場合)。キャプチャリスト [weak self] や [unowned self] を使用して、self (または他のインスタンス) への参照を弱参照または非所有参照としてキャプチャすることで、循環参照を防ぎます。weak self の場合、クロージャ内で self はオプショナル型になるため、guard let self = self else { return } などでアンラップして使用します。 |
|
その他 🛠️
その他の重要なSwiftの機能です。
機能 | キーワード / 構文 | 説明 | 例 |
---|---|---|---|
アクセスコントロール | open public internal fileprivate private |
コード(クラス、構造体、プロパティ、メソッドなど)へのアクセスレベルを制限します。
|
|
型キャスト | is (型チェック)as? (ダウンキャスト – オプショナル)as! (ダウンキャスト – 強制)as (アップキャスト / ブリッジング) |
インスタンスの型を確認したり、スーパークラスやプロトコルの型から、より具体的なサブクラスや準拠型へ変換(ダウンキャスト)したりします。
|
|
パターンマッチング | (switch , if case , guard case , for case ) |
値が特定のパターンに一致するかどうかを調べ、一致した場合に関連する値を抽出(バインド)する強力な機能です。switch 文だけでなく、if , guard , for ループでも限定的なパターンマッチングが可能です。 |
|
Any, AnyObject | Any AnyObject |
特定の型が不明な場合や、様々な型の値を扱いたい場合に使用できる特殊な型です。
as? , as! ) が必要になることが多く、型安全性が低下するため、可能な限り具体的な型を使用することが推奨されます。 |
|
コメント