iOSアプリ開発でのHTTP通信をラクにする「Alamofire」の使い方

2017/03/03

Aleksander Koko

66

Articles in this issue reproduced from SitePoint
Copyright © 2017, All rights reserved. SitePoint Pty Ltd. www.sitepoint.com. Translation copyright © 2017, KADOKAWA ASCII Research Laboratories, Inc. Japanese syndication rights arranged with SitePoint Pty Ltd, Collingwood, Victoria,Australia through Tuttle-Mori Agency, Inc., Tokyo

iOSアプリでHTTP通信をする方法はいろいろありますが、オープンソースのライブラリー「Alamofire」を使うのが簡単で便利です。Wikipediaからデータを取得するアプリを例に、基本的な使い方を学びましょう。

※本記事は2016年6月30日に掲載した記事を再編集したものです。執筆時点の情報をベースにしており、最新ではない可能性があります。

ほとんどのアプリは、外部サービスやデータソースに接続するときにネットワークを使います。「ネットワーク」とは、もっとも利用されているプロトコルの1つである「HTTP(ハイパーテキスト・トランスファー・プロトコル)」を使って情報を交換することを意味しています。ブラウザーを開き、データを取得・送信するたびに、プロトコルとしてHTTPを使用しています。この記事では、以下の項目を確認しながら、iOSにおけるネットワークの使い方を学習します。

  • HTTP
  • REST API
  • NSURLSession:サードパーティーのライブラリーを使わないネットワーク処理
  • Alamofire:ネットワーク処理のプロセスを単純化するサードパーティー製のライブラリー
  • そのほかのネットワーク処理ライブラリーの一覧

すでにHTTPやREST APIを熟知している人は、 NSURLSessionから始めてください。

本記事はiOSに関するシリーズの一環で、今後オープンソースとして公開する予定の開発中のアプリをもとに執筆しています。アプリはWikimedia Commonsのデータを使用し、サイトのREST APIでこのデータにアクセスしています。

HTTPってそもそもなんだっけ?

HTTPはもっとも一般的なプロトコルの1つです。この記事もHTTPによってHTMLページをSitePointのサーバーから取得しています。クライアント(ブラウザー)がサーバーにリクエストを送信し、サーバーはリクエストされたリソースについて情報を返します。モバイルアプリはデータリストをリクエストし、サーバーはリクエストされたデータを返します。これらはGETリクエストと呼ばれます。

ときどきアプリからサーバーへ、更新されたデータを投稿することもあります。これらはPOSTリクエストと呼ばれます。

他のリクエストタイプ(またはHTTPの動詞)には次のようなものがあります。

  • GET
  • POST
  • HEAD
  • PUT
  • PATCH

HTTPプロトコルについて詳しく知りたい人には、Wikipediaの記事をおすすめします。

REST APIを使おう

REST APIはシンプルで標準的なデータ交換の方法です。サーバーにデータがいくつかあり、アプリで取得したいとしましょう。API(アプリケーション・プログラミング・インターフェース)の大部分はデータベースのラッパーなので、最初にAPIの構造を理解する必要があります。

例として、書籍リストのデータベースがあり、アプリから書籍の詳細を検索する必要があったとします。

はじめに、このデータを取得する場所が必要です。このケースではドメインはhttps://books.com/で、APIは/apiにあります。

APIではデータをどのように表せばよいでしょうか?

APIでアクセスできるデータはコレクションとエンティティーで構成する必要があります。この場合、コレクションは書籍グループを指し、下のように表します。

https://example.com/api/books

このURLは書籍コレクションを返します。またページレイアウトや検索を実装できます(https://example.com/api/v2/books?page=2https://example.com/api/v2/books?query='Jump Start PHP Environment')。

エンティティはコレクションの特定の書籍です。 IDが「1」の書籍なら、https://example.com/api/v2/books/1と表します。

GETPOSTPUTなどのHTTP動詞を使用すると、エンティティやコレクションを操作できます。GETを使うと、IDで書籍を検索できます。たとえば、https://example.com/api/v2/books/7です。POSTを使うと、書籍コレクションに新しい書籍を追加できます。あわせて、他のパラメーターと必須フィールドを指定する必要があります。

APIの構造が分かったので、次はデータを表示する方法を決めます。私は、開発言語に関係なく使えるフォーマットであるJSONが気に入っています。

JSONメッセージは下記のようになります。

{
  "id": 7,
  "userId": 20,
  "title": "Jump Start PHP Environment",
  "description": "Many entry level PHP developers want a quick path to glory, a shortcut to “knowing PHP.” Too many books and tutorials go straight into a pre-made, awful environment that just wants you to code, with no regard for security, version control, or other absolutely essential practices. This book is aimed at the absolute beginner who wants to start learning PHP, but aims to set you up with a thorough understanding of what makes for a good, modern, adaptable PHP environment before you start diving into PHP itself."
}

APIの構築に興味がある人は、SitePointの『Building a Simple REST API for Mobile Applications』をおすすめします。WordPressを使っていてAPIに変換したい人は、『The WordPress JSON REST API』がおすすめです。

NSURLSessionによる通信

iOS7以降では、NSURLSessionでネットワーク通信ができるようになりました。

NSURLSessionはSwiftのリモートデータセットと連動する「ネイティブ」な方法です。Alamofireはこの技術を使って構築されています。次のコードは、Wikimedia Commons APIからログイントークンを取得する方法の例です。

class WCLoginApi {

  static func nsurlAction(){

      // Create a session configuration
      let session = NSURLSession.sharedSession()

      var stringUrl: String = "https://en.wikipedia.org/w/api.php"
      stringUrl = stringUrl.stringByAppendingString("?action=query")
      stringUrl = stringUrl.stringByAppendingString("&format=json")
      stringUrl = stringUrl.stringByAppendingString("&meta=tokens")
      stringUrl = stringUrl.stringByAppendingString("&type=login")

      let url: NSURL = NSURL(string: stringUrl)!

      let request = NSMutableURLRequest(URL: url)
      request.HTTPMethod = "GET"
      request.cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringCacheData

      let task = session.dataTaskWithRequest(request) {
          (
          let data, let response, let error) in

          guard let _:NSData = data, let _:NSURLResponse = response  where error == nil else {
              print("error")
              return
          }

          let dataString = NSString(data: data!, encoding: NSUTF8StringEncoding)
          print(dataString)
      }

      task.resume()

  }
}

WCLoginApi.nsurlAction()

最初にセッションの設定が必要で、この例では、共有セッションの設定を取得します。アプリの一般的な接続設定を繰り返し使用する場合には便利なメソッドですが、異なるリクエストをする場合はそうではありません。

設定を取得したあと、URLとパラメーターを作成します。この場合、ベースURLはhttps://en.wikipedia.org/w/api.phpで、パラメーターはactionformatmetatypeです。サーバーからトークンを取得する際、GETがHTTP動詞として使用されます。

taskを作成して実行するのはさらに複雑です。定義したあと、resumeメソッドは非同期的にtaskを実行します。taskを定義するとき、コールバックは引数として渡され、print(dataString)はサーバーから取得したデータを出力します。

Alamofireならシンプルに

Alamofireライブラリーの目的ははっきりとしていて、iOSのネットワーク通信処理をシンプルにすることです。カスタムネットワークを使うつもりなら(たとえば違うプロトコルを使うなどですが)、このライブラリーは適しません。しかし昔ながらのREST APIやシンプルなネットワーク通信を使用する場合、Alamofireを試すことをおすすめします。

Alamofireをインストールするには、CocoaPods、Carthage、手動インストールがあるので、インストールガイドを読んで自分にぴったりの方法を見つけてください。

以下はAlamofireを使って書き換えた最初の例です。

import Alamofire

class WCLoginApi {
    static func alamofireExample() -> Void
    {
        Alamofire.request(
            .GET,
            "https://en.wikipedia.org/w/api.php",
            parameters: [
                "action": "query",
                "format": "json",
                "meta": "tokens",
                "type": "login"
            ]).responseJSON { response in

                if let JSON = response.result.value {

                    if let loginTokenKey = JSON.objectForKey("query")?.objectForKey("tokens")?.objectForKey("logintoken") {
                        print(loginTokenKey)
                    }else{
                        print("Error to parse JSON")
                    }

                }else{
                    print("Error with response")
                }
        }
    }
}

WCLoginApi.alamofireExample()

requestは、HTTP動詞を2番目の引数(Alamofireでは定数で、この場合.GET)としてメソッドを呼び出します。3番目の引数は、引数を含まないString型のベースURLです。

次は、パラメーターリスト(NSURLSessionと同様)です。この例では、NSURLSessionの例のようにはエンコードせず、Alamofireが自動的にビルドします。URLとパラメーター文字列を自分で作りたいかもしれませんが、こちらの方がよいアプローチです。

REST APIを操作していると、異なるフォーマットに遭遇します。Wikimedia Commons APIは異なるフォーマットをサポートしていますが、JSONであることがわかっていればresponseJSONメソッドを使用できます。他のコールバックメソッドは異なるフォーマットに対応しています。

iOSのネイティブの方法に比べ、シンプルで構造化されています。ネイティブの方法でもよりよい方法はありますが、Alamofireなら簡単です。Alamofireはデータの取得だけでなく、データの投稿やダウンロードもできます。

Alamofireがあるとキャッシュの設定変更やヘッダー、チェーンレスポンス(たとえば、他のレスポンスタイプでresponseJSONメソッドのチェック)、レスポンスからのデータの検証、ユーザー認証などができます。

ほかには?

ネットワークは一般的なタスクなので、プロセスをシンプルにする方法がAlamofireだけではありません。以下は、検討に値するその他のライブラリーです。

  • SwiftHTTP: A simple Swift wrapper around NSURLSession.
  • Moya: A Swift alternative to Alamofire.
  • FSNetworking: Foursquare’s Objective-C networking implementation.
  • Reach: A simple Swift library to check if you have network.
  • iOS-netdiag: An Objective-C network diagnosis library.

(原文:A Crash Course on Networking in iOS

[翻訳:中野汐里/編集:Livit

Copyright © 2017, Aleksander Koko All Rights Reserved.

Aleksander Koko

Aleksander Koko

開発者で、最新のWebテクノロジーを使うのが大好きです。空いた時間で、PHP、Firefox OS、新しい言語の実験について学習しています。最近のマイブームはPHPデザインパターン、Laravel、Dart、クラウドです。

Loading...