はじめての Swift ソースコード読解チートシート(完全分解つき)

「型?プロパティ?メソッド?クロージャ?」を“見た瞬間に”見分けられるように。 すべての項目に、コードと“完全分解”表を付けました。


  1. 0. まずは地図:情報か?動作か?
  2. 1. 型(Type)とは:設計図そのもの
    1. サンプル
    2. 完全分解
  3. 2. プロパティ(Property):情報を持つ箱
    1. サンプル
    2. 完全分解(static let species = "human" 例)
  4. 3. メソッド(Method):型に属する「動作」
    1. サンプル
    2. 完全分解(pochi.bark())
  5. 4. イニシャライザ(Initializer):実体を作る特別なメソッド
    1. サンプル
    2. 完全分解(init(name: String) { self.name = name })
  6. 5. クロージャ(Closure):その場で書ける“小さな関数”
    1. サンプル
    2. 完全分解(let square: (Int) -> Int = { x in x * x })
    3. 完全分解(即時実行 { ... }())
    4. クロージャの応用:SwiftUI の「中かっこ記法」はクロージャ引数
      1. 普段の省略版
      2. 等価な明示版
      3. VStack の場合
      4. モディファイアでも同じ仕組み
    5. まとめ
  7. 6. オプショナル(Optional):値が“ないかも”を型で表す
    1. サンプル
    2. 完全分解(if let value = name { ... })
  8. 7. 拡張(Extension):既存の型に“後から”機能追加
    1. サンプル
  9. 📝 完全分解(extension String { var dogBark: String { ... } })
  10. 8. FileManager の“超”完全分解(再掲)
  11. 9. プロトコル(Protocol):できることの“約束”
    1. サンプル
    2. 完全分解
  12. 10. ジェネリクス(Generics):型に依存しない汎用コード
    1. サンプル
    2. 完全分解
  13. 11. エラー処理:throws / try / do-catch
    1. サンプル
    2. 完全分解(do { let s = try loadData() } catch { ... })
  14. 12. おまけ:配列の高階関数(手触りで“関数=動作”に慣れる)
    1. 完全分解(arr.map {

0. まずは地図:情報か?動作か?

  • 情報を持つもの → プロパティ(変数・定数のように値をしまう箱)
  • 動作をするもの → メソッド(型の中の関数)
  • 設計図 → 型(struct / class / enum など)
  • 設計図から作る実体 → インスタンス

見分けの合言葉:「これは“箱”か、“動作”か?」


1. 型(Type)とは:設計図そのもの

サンプル

struct Dog {      // Dog という「型」(設計図)
    var name: String
}

let pochi = Dog(name: "ポチ") // 設計図から作った実体=インスタンス

完全分解

断片種別役割
structキーワード構造体(値型)の定義を始める合図
Dog型名新しい型の名前(設計図の名前)
{ ... }ブロック型に属するプロパティやメソッドを書く場所
var name: Stringプロパティ宣言この型の各インスタンスが持つ「名前」という情報
Dog(name: "ポチ")イニシャライズ設計図から実体(インスタンス)を作る

2. プロパティ(Property):情報を持つ箱

サンプル

struct User {
    // 格納プロパティ(値をそのまま保持)
    var name: String

    // 計算プロパティ(計算して返す)
    var greeting: String { "こんにちは、\(name)" }

    // 遅延プロパティ(初アクセス時に初期化)
    lazy var cache = HeavyLoader.load()

    // 型プロパティ(インスタンス不要、型に属する)
    static let species = "human"
}

完全分解(static let species = "human" 例)

断片種別役割
static修飾子型に属するメンバ(インスタンス不要)
letキーワード変更不可の定数プロパティ
species識別子プロパティ名
= "human"代入初期値

見分け方var/let で始まったらプロパティ。“箱”。static が付けば型プロパティ


3. メソッド(Method):型に属する「動作」

サンプル

struct Dog {
    var name: String

    // インスタンスメソッド(インスタンスが必要)
    func bark() { print("\(name)がワン!") }

    // 型メソッド(インスタンス不要、型に属する)
    static func info() { print("犬は哺乳類です") }
}

let pochi = Dog(name: "ポチ")
pochi.bark()   // 実体に対して“動作”する
Dog.info()     // 型そのものに対して“動作”する // 型メソッド(設計図そのものに命令)

完全分解(pochi.bark())

断片種別役割
pochi変数(インスタンス)Dog 型の実体
.演算子所属するメンバへアクセス
barkインスタンスメソッド名実体の動作
()呼び出しメソッドを実行する合図

見分け方func で始まったらメソッド。“動作”。static/class func なら型メソッド


4. イニシャライザ(Initializer):実体を作る特別なメソッド

サンプル

struct Dog {
    var name: String
    init(name: String) { self.name = name }
}

let pochi = Dog(name: "ポチ")

完全分解(init(name: String) { self.name = name })

断片種別役割
initキーワードイニシャライザの宣言開始
(name: String)パラメータ作成時に必要な情報
{ self.name = name }本体渡された値をプロパティへ格納
self参照いま初期化している自分自身のインスタンス

5. クロージャ(Closure):その場で書ける“小さな関数”

サンプル

let square: (Int) -> Int = { x in x * x }
print(square(4)) // 16

// 即時実行クロージャ:作ってすぐ呼ぶ
let greeting: String = {
    let name = "太郎"
    return "こんにちは、\(name)さん"
}()

完全分解(let square: (Int) -> Int = { x in x * x })

断片種別役割
let square定数宣言クロージャをしまう“箱”の名前
: (Int) -> Int型注釈「Int を受け取って Int を返す」関数型
=代入右側のクロージャを代入
{ x in x * x }クロージャ式x を受け取り x*x を返す動作

完全分解(即時実行 { ... }())

断片種別役割
{ ... }クロージャ小さな関数の本体
()呼び出しいま作ったクロージャをその場で実行

なるほど!
すでに「Swift基礎まとめ記事(型・プロパティ・メソッド・クロージャ・オプショナル…など完全分解つき)」があって、そこに 「SwiftUI の中かっこの正体=クロージャ引数」 の解説を追加したいわけですね。

既存記事の流れ(5. クロージャ → 6. オプショナル…)に自然に溶け込むよう、「クロージャの実例(関数型) → SwiftUIでの応用(引数にクロージャを渡す省略記法)」 の流れで追記できる形にしました

クロージャの応用:SwiftUI の「中かっこ記法」はクロージャ引数

クロージャは「その場で書ける小さな関数」です。
SwiftUI の VStack { ... }NavigationStack { ... } で登場する 中かっこ { ... } も、実は クロージャを引数に渡しているだけです。

普段の省略版

NavigationStack {
    Text("Hello")
}

等価な明示版

NavigationStack(content: {
    Text("Hello")
})
  • NavigationStack 自体は View(構造体)
  • { ... }content 引数に渡されるクロージャ

👉 SwiftUI では「TypeName { … }」は「TypeName(content: { … })」に展開できると思えばOK。


VStack の場合

VStack(alignment: .leading, spacing: 16) {
    Text("左寄せ1")
    Text("左寄せ2")
}

= 展開すると

VStack(
    alignment: .leading,
    spacing: 16,
    content: {
        Text("左寄せ1")
        Text("左寄せ2")
    }
)
  • alignment … 配置(leading = 左寄せ)
  • spacing … 子ビュー間の余白
  • content: { … } … 実際に並べるビューを返すクロージャ

モディファイアでも同じ仕組み

.sheet(isPresented: $show) {
    DetailView()
}
// = .sheet(isPresented: $show, content: { DetailView() })
.alert("エラー", isPresented: $showErr) {
    Button("OK", role: .cancel) {}
}
// = .alert("エラー", isPresented: $showErr, actions: { Button("OK", role: .cancel) {} })

まとめ

  • 中かっこ { ... } は「引数に渡すクロージャ」
  • Type 自体がクロージャではない
  • 見慣れた VStack { ... }NavigationStack { ... } も、省略を外せば VStack(content: { ... }) と同じ

つまり「SwiftUIの中かっこ = クロージャ応用の実例」として理解すれば、Swift文法とUIコードがつながります。


6. オプショナル(Optional):値が“ないかも”を型で表す

サンプル

var name: String? = nil        // ない かもしれない
name = "花子"

// 安全な取り出し(アンラップ)
if let value = name { print(value) }

// 強制取り出し(危険)
print(name!)  // nil ならクラッシュ

完全分解(if let value = name { ... })

断片種別役割
if let構文オプショナルを安全に取り出す(nil なら中へ入らない)
value変数取り出した実体(非オプショナル)
= name代入元のオプショナルからコピー

合言葉? は「無いかも」、! は「絶対ある!(無かったら落ちる)」


7. 拡張(Extension):既存の型に“後から”機能追加

サンプル

// String 型を拡張して「犬の鳴き声」を追加
extension String {
    var dogBark: String {
        return self + "がワン!"
    }
}

let name = "ポチ"
print(name.dogBark) // → 「ポチがワン!」

📝 完全分解(extension String { var dogBark: String { ... } })

断片種別役割
extension String宣言既存の String 型に機能を追加します
var dogBark: StringインスタンスプロパティString の各インスタンスが持てる「情報」を追加
: String型注釈このプロパティの返り値は String 型
{ return self + "がワン!" }本体self(この文字列自身)に「がワン!」を足して返す

8. FileManager の“超”完全分解(再掲)

FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
断片種別役割
FileManager型(class)ファイル/フォルダ操作の窓口
.default型プロパティ共有の FileManager インスタンス
.urls(for:in:)インスタンスメソッド指定ディレクトリの URL 配列を取得
.documentDirectoryネスト enum 値「ドキュメントフォルダ」を指す選択肢
.userDomainMaskネスト OptionSet 値「ユーザー領域」を指す選択肢
.firstプロパティ配列の先頭要素(Optional)
!演算子強制アンラップ:URL?URL(nil ならクラッシュ)

流れ:型 → 共有インスタンス → メソッド実行 → 配列 → 先頭要素 → 強制取り出し。


9. プロトコル(Protocol):できることの“約束”

サンプル

protocol Greeter { func greet() -> String }
struct Person: Greeter { func greet() -> String { "Hi" } }

完全分解

断片種別役割
protocol Greeter宣言「挨拶できること」を約束する仕様
{ func greet() -> String }要件実装すべきメソッド
struct Person: Greeter準拠Person は Greeter の約束を守る
func greet() -> String { ... }実装実際の動作を提供

10. ジェネリクス(Generics):型に依存しない汎用コード

サンプル

func maxOf<T: Comparable>(_ a: T, _ b: T) -> T { a < b ? b : a }
maxOf(3, 5)        // 5
maxOf("a", "b")  // "b"

完全分解

断片種別役割
<T: Comparable>型パラメータどんな型でもOK。ただし比較できる(Comparable)こと
(_ a: T, _ b: T)引数同じ型 T の2つの値
-> T返り値T 型を返す
a < b ? b : a本体大きい方を選んで返す

11. エラー処理:throws / try / do-catch

サンプル

func loadData() throws -> String { "OK" } // 失敗するかも、と宣言

do {
    let s = try loadData()  // 失敗可能なので try が必要
    print(s)
} catch {
    print("エラー:", error)
}

let maybe = try? loadData()  // 失敗したら nil
let must  = try! loadData()  // 失敗しないと信じる(失敗でクラッシュ)

完全分解(do { let s = try loadData() } catch { ... })

断片種別役割
do { ... }構文ここでエラーが出るかもしれない処理を包む
tryキーワード失敗可能な関数を呼ぶときの印
catch { ... }構文失敗したときの処理

12. おまけ:配列の高階関数(手触りで“関数=動作”に慣れる)

let arr = [1,2,3]
let doubled = arr.map { $0 * 2 }     // [2,4,6]
let even    = arr.filter { $0 % 2 == 0 } // [2]
let sum     = arr.reduce(0, +)        // 6

完全分解(arr.map {

完全分解(arr.map { $0 * 2 }

* 2 })

断片種別役割
arr変数元の配列
.mapメソッド各要素に処理を適用して新しい配列を作る“動作”
{ $0 * 2 }クロージャ受け取った要素($0)を2倍にする処理

最後に:見分けのルール(暗記カード)

  1. var/letプロパティ(情報=箱)
  2. funcメソッド(動作)
  3. static/class型に属する(インスタンス不要)
  4. init実体を作る特別メソッド
  5. { ... }クロージャ{ ... }()即時実行
  6. ? / !オプショナル(無いかも / 強制取り出し)
  7. . の左側は 「いま誰に話しかけているか」:型?インスタンス?

迷ったら「これは?それとも動作?」「型に話しかけてる?インスタンスに話しかけてる?」の2つを確認!

コメント

タイトルとURLをコピーしました