Swift開発手法をポケモンで理解してみよう⑦

ポケモンニワカなのでポケモンに関する情報は正確ではない可能性があります、ご容赦ください。

Swift開発手法をポケモンに例えて覚えてみようとする試み。

Part7です。

Part7

Void

無の使い手、ミミッキュ

解説
  • タイプ: ゴースト/フェアリー (何もないことを表すゴーストタイプ、そして謎めいた存在感を放つフェアリータイプ)
  • 特性: ばけのかわ (実態がないように見せかけ、攻撃を防ぐ)
  • 得意技:
    • シャドーボール: 何も返さないことを表現
    • のろい: 何も返さないことで、次に繋がる効果を生み出す
    • トリックルーム: 処理の順番を操作し、Voidの役割を強調
  • 性格: まじめ (決められたルールに従い、必ず何も返さない)

ミミッキュのように、Voidは:

  • 何もないことを表す型です。
  • 関数が値を返さない場合に利用されます。
  • () (空のタプル) と同じ意味を持ちます。
func greetPikachu() -> Void {
    print("ピカチュウ!") // 値を返さない
}

greetPikachu() // 出力: ピカチュウ!
  1. greetPikachu() 関数は、戻り値の型として Void を指定しています。
  2. 関数内で print("ピカチュウ!") を実行しますが、値は返しません。
  3. 関数を呼び出すと、”ピカチュウ!”と出力されますが、戻り値はありません。

Any

変幻自在のメタモン

解説
  • タイプ: ノーマル (どんな型にも変身できる)
  • 特性: かわりもの (他のポケモンに変身するように、どんな型でも保持できる)
  • 得意技:
    • へんしん: 他の型に変身
    • ものまね: 他の型のメソッドやプロパティを模倣
    • バトンタッチ: 保持している値を他の変数に安全に渡す
  • 性格: まんぷく (どんな型でも受け入れる心の広さ)

メタモンのように、Anyは:

  • どんな型の値でも保持できる特別な型です。
  • 異なる型の値をまとめて扱う必要がある場合に便利です。
  • しかし、型安全性が失われるため、注意が必要です。
  • コレクション(配列や辞書)などで異なる型の値をまとめて扱う場合に利用されます。
  • 型情報を保持しないため、値を取り出す際には型変換(ダウンキャスト)が必要です。
let pokedex: [Any] = ["ピカチュウ", 10, true] // 異なる型の値を格納

for item in pokedex {
    switch item {
    case let pokemon as String:
        print("ポケモン: \(pokemon)")
    case let level as Int:
        print("レベル: \(level)")
    case let isShiny as Bool:
        print("色違い: \(isShiny)")
    default:
        print("不明なデータ")
    }
}
  1. pokedex という配列に、文字列、整数、真偽値という異なる型の値を格納します。
  2. for ループで配列の要素を順番に取り出し、switch 文で型に応じて処理を分岐します。
  3. as を使って型変換(ダウンキャスト)を行い、それぞれの型の値を取り出します。

escaping

時を超えるセレビィ

解説
  • タイプ: エスパー/くさ (時間と空間を超越する能力を表現)
  • 特性: しぜんかいふく (関数のスコープ外でも生き続ける)
  • 得意技:
    • みらいよち: 関数が終了した後でも未来のイベントを予知
    • リーフストーム: 関数のスコープ外で強力な処理を実行
    • タイムマシン: 過去に遡り、関数のスコープ内の変数を変更
  • 性格: おっとり (マイペースに、関数のライフサイクルにとらわれず行動)

セレビィのように、escapingクロージャーは:

  • 関数が終了した後でも実行されるクロージャーです。
  • 関数のスコープ外で保持され、後から呼び出される可能性があります。
  • 非同期処理やイベントハンドラなどでよく利用されます。
func catchPokemonLater(completion: @escaping (String) -> Void) {
    DispatchQueue.main.asyncAfter(deadline: .now() + 2) { // 2秒後に実行
        let pokemon = "ピカチュウ"
        completion(pokemon) // クロージャーを実行
    }
    print("モンスターボールを投げた!")
}

catchPokemonLater { pokemon in
    print("\(pokemon)をゲット!") // クロージャーが実行される
}
  1. catchPokemonLater 関数は、completion というescapingクロージャーを引数に取ります。
  2. @escaping は、このクロージャーが関数のスコープ外で保持される可能性があることを示します。
  3. 関数内で、2秒後に実行されるように DispatchQueue.main.asyncAfter を使用してクロージャーを登録します。
  4. 関数はすぐに終了し、”モンスターボールを投げた!”と出力されます。
  5. 2秒後、クロージャーが実行され、”ピカチュウをゲット!”と出力されます。

CaseIterable

全種類コンプリートを目指す図鑑、ロトム図鑑

解説
  • タイプ: でんき/ゴースト (デジタルな図鑑と、全てのケースを把握する不思議な力を表現)
  • 特性: ふゆう (特定の型に依存せず、様々なenumに対応)
  • 得意技:
    • 10まんボルト: 全てのケースを一気に列挙
    • おにび: 不正なケースの使用を防ぐ警告
    • トリック: ケースの順番を入れ替え、新たな発見を促す
  • 性格: れいせい (冷静に全てのケースを分析し、整理)

ロトム図鑑のように、CaseIterableは:

  • enumの全てのケースを列挙するためのプロトコルです。
  • allCases というプロパティを通じて、enumの全てのケースを配列として取得できます。
  • enumのケースを網羅的に処理したい場合に便利です。
enum PokemonType: CaseIterable {
    case ほのお, みず, くさ, でんき, ノーマル, かくとう, どく, じめん, ひこう, エスパー, むし, いわ, ゴースト, ドラゴン, こおり, はがね, フェアリー
}

for type in PokemonType.allCases {
    print(type)
}
  1. PokemonType というenumを定義し、CaseIterable プロトコルに準拠させます。
  2. PokemonType.allCases で全てのケースを取得し、配列として扱えます。
  3. for ループで全てのケースを順番に処理します。

URLSession

ネットを駆ける高速デリバード、アーマーガア

解説
  • タイプ: はがね/ひこう (インターネットを高速で飛び回り、データを届ける)
  • 特性: ミラーアーマー (外部からの攻撃を防ぎ、安全に通信)
  • 得意技:
    • ブレイブバード: 高速でリクエストをサーバーに送信
    • アイアンヘッド: 受け取ったデータを堅牢に処理
    • ボディプレス: 圧縮されたデータを効率的に扱う
  • 性格: ゆうかん (どんなサーバーにも臆せず立ち向かう)

アーマーガアのように、URLSessionは:

  • ネットワークリクエストを行い、データを送受信します。
  • RxSwiftでは、URLSession の拡張機能を使って、リアクティブにネットワーク通信を扱えます。
  • Observable としてデータを受信し、エラー処理やデータ変換などを柔軟に行えます。
let url = URL(string: "https://pokeapi.co/api/v2/pokemon/pikachu")!
let request = URLRequest(url: url)

URLSession.shared.rx.data(request: request) // リクエストを送信し、レスポンスデータのObservableを取得
    .map { try JSONDecoder().decode(Pokemon.self, from: $0) } // JSONデータをPokemonオブジェクトに変換
    .subscribe(onNext: { pokemon in
        print(pokemon.name) // ポケモンの名前を表示
    }, onError: { error in
        print("エラー: \(error)") // エラー処理
    })
    .disposed(by: disposeBag)
  1. リクエスト先のURLと URLRequest を作成します。
  2. URLSession.shared.rx.data(request: request) でリクエストを送信し、レスポンスデータの Observable を取得します。
  3. map 演算子で JSONDecoder を使って、レスポンスデータを Pokemon オブジェクトに変換します。
  4. subscribe(onNext:onError:)Observable を購読し、成功時にはポケモンの名前を表示、エラー時にはエラーメッセージを表示します。
  5. disposed(by: disposeBag) で購読を破棄します。