LoginSignup
0
1

【Swift】ポケモンのAPI通信のサンプルコードから、API通信処理を学習する - Decoder・URLSessionなど -

Last updated at Posted at 2023-05-03

今回は、ポケモンのAPI通信の実装済みであるサンプルコードを用いて、初学者として勉強になったところをまとめてみる。

↑のGitHubは、ポケモンのAPIを使ったサンプルコード

↑がポケモンのAPIについて記載されている。ドキュメントあり。

JSON→構造体に変換に関するリファクタリングに有効

 public static var decoder: JSONDecoder = {
          let decoder = JSONDecoder()
          decoder.keyDecodingStrategy = .convertFromSnakeCase
          return decoder
      }()

このコードは、JSONDecoder オブジェクトを作成して、その keyDecodingStrategy プロパティを .convertFromSnakeCase に設定しています。
keyDecodingStrategy プロパティは、JSON キー名が Swift の命名規則に準拠していない場合に、JSON キーを Swift の命名規則に変換するために使用されます。例えば、JSON キー名が snake_case (アンダースコア区切り) の場合、keyDecodingStrategy.convertFromSnakeCase に設定することで、Swift の命名規則である camelCase (大文字で始まる) に変換することができます。
この設定を行うことで、JSON データを Swift の構造体やクラスにデコードする際に、より自然な命名規則を使うことができます。例えば、以下のような JSON データがあった場合、keyDecodingStrategy.convertFromSnakeCase に設定することで、first_name キーが firstName としてデコードされます。
命名規則に従って、JSONが実装されている場合は、コード量を減らすことが可能である。

わざわざ 変換前のコードを書いることが多かったので、これは便利!っと感じました。

APIのパスパラメータの種類が多いときの実装例

PokemonAPI.swift
public class PokemonAPI {
     public let session: URLSession
     
     public init(session: URLSession = URLSession.shared) {
         self.session = session
     }
     
     public lazy private(set) var berryService = BerryService(session: session)
     public lazy private(set) var contestService = ContestService(session: session)
     public lazy private(set) var encounterService = EncounterService(session: session)
     public lazy private(set) var evolutionService = EvolutionService(session: session)
     public lazy private(set) var gameService = GameService(session: session)
     public lazy private(set) var itemService = ItemService(session: session)
     public lazy private(set) var locationService = LocationService(session: session)
     public lazy private(set) var machineService = MachineService(session: session)
     public lazy private(set) var moveService = MoveService(session: session)
     public lazy private(set) var pokemonService = PokemonService(session: session)
     public lazy private(set) var resourceService = ResourceService(session: session)
     public lazy private(set) var utilityService = UtilityService(session: session)
 }

PokemonAPIの中に、様々なパスパラメータがある。それらを管理するために、PokemonAPIクラスの中に、プロパティとして、保持しておく。参考になった。

API通信に必要なURLを管理する実装例

Pokemon.swift
public struct PokemonService: PKMPokemonService {
     public enum API: APICall {
         case fetchAbilityList
         case fetchAbilityByID(Int)
         case fetchAbilityByName(String)
          // 省略
         case fetchTypeByName(String)
         
         var path: String {
             switch self {
             case .fetchAbilityList:
                 return "/ability"
             case .fetchAbilityByID(let id):
                 return "/ability/\(id)"
             case .fetchAbilityByName(let name):
                 return "/ability/\(name)"
             // 省略
             case .fetchTypeByName(let name):
                 return "/type/\(name)"
             }
         }
     }
     
     public var session: URLSession
     
     public var baseURL: String = "https://pokeapi.co/api/v2"
     // 省略
     }

PokemonService構造体の中で、APIというenumが定義されており、その中にpathがあり、各caseに対応するAPIエンドポイントのパスを返します。例えば、.fetchAbilityListの場合は"/ability"を、.fetchAbilityByIDの場合は"/ability/(id)"を返します。また、各caseはそれぞれ必要な場合は、StringIntなどの型を保持している。
また、baseURLは、 "https://pokeapi.co/api/v2" という各パスパラメータの元となる部分であり、各APIのURLを完成させるために使用されます。API列挙型のcasepathプロパティをbaseURLに追加することで完成します。

このように管理すればよいのか! と大変勉強になった。

列挙型のAPIに対して、プロトコルの作成して、共通化 

APICall.swift
 protocol APICall {
     var path: String { get }
 }
 
 extension APICall {
     func createUrl(baseURL: String) -> URL? {
         return URL(string: baseURL + path)
     }
     
     // 省略   
  }

先程のAPI実装例と話は関連しています。
上記のように、APICallに、pathを設定することにより、各API実装において、pathの設定を忘れることはなくなり、APICallの拡張での、func createUrl(baseURL: String) -> URL?関数の中で、pathを用いることができ、各APIにおいて共通化してこのメソッドを使用することが可能となる。
上記によって、毎回createURLメソッドを作成する必要がなくなる。
プロトコルによる抽象化の恩恵はこうゆうところで受けるんだなーと感じた。

次回は、エラーハンドリング周りのコードで、学習していく。
以上です。

他にも良い方法があれば、コメントいただけると大変うれしいです。
良かったと思ったら、いいねやTwitterのフォローよろしくお願いいたします!

https://sites.google.com/view/muranakar
個人でアプリを作成しているので、良かったら覗いてみてください!

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1