他のサービスやアプリとつながるiOSアプリをSwiftで作成しながら、「アプリの考え方」を習得する本連載。前回は、ネットワーク上のデータをアプリに読み込んで扱う方法について解説しました。今回は実務でも利用することの多いオープンデータをアプリで扱う方法を解説します。
※本連載では、2015年10月時点で最新のXcode 7、Swift 2で解説します。
誰でも自由に利用可能なオープンデータ
オープンデータとは、誰でも自由に入手でき、再利用や再配布のできるデータのことです。公共機関や科学データ、天気データなどがあり、形式はXMLやCSVやJSONなどがあります。
オープンデータの中から今回は、「HeartRails Express」の無料APIをつかって、指定した路線の駅情報を取得して表示しましょう。
HeartRails Expressは、路線/駅名データ等の地理情報を、XML、JSON 形式で無料提供しているサービスです。
「HeartRails Express」
http://express.heartrails.com/api.html
※無料利用には、アプリケーション内に 「HeartRails Express」 のクレジットが必要です。
「駅情報取得API」は「http://express.heartrails.com/api/json?method=getStations」で、駅の情報一覧が取得できます。
ブラウザーに直接
http://express.heartrails.com/api/json?method=getStations&line=JR山手線
と入力するとJSON形式で山手線の駅名データが返ってきます。
データの構造は、「駅情報取得API」の「レスポンスフィールド」で確認できます。
返ってきたJSONデータから階層構造がわかります。
Swiftで試してみよう
APIの階層構造がわかったところで実際にアプリを作ってみましょう。
前回、JSONデータのデメリットは「本当にそのデータがあるかどうかをチェックする」のが大変だと解説しました。今回はJSONデータを解析する「SwiftyJSON」ライブラリーを利用します。
1)SwiftyJSONライブラリーをダウンロードします。
SwiftyJSON-masterをGitHubからダウンロードします。右下にある「Download ZIP」ボタンからダウンロードできます。
ダウンロードしたファイル(SwiftyJSON-master.zip)を解凍すると、「SwiftyJSON-master」フォルダが作成されます。
2)Xcodeのメニュー「File」→「New」→「Project」から「Single View Application」を選択して、新規プロジェクトを作成しましょう。
3)「作成したプロジェクトのフォルダ」を開き、そこに、SwiftyJSON-masterフォルダをドラッグ&ドロップしてコピーします。
4)作成したプロジェクトを開き、コピーしたSwiftyJSON-masterフォルダを開いて、中にある「SwiftyJSON.xcodeproj」ファイルを、ナビゲータエリアのプロジェクトファイルの下にドラッグ&ドロップします。
5)「プロジェクト」→「TARGETS」→「Build Phases」→「Target Dependencies」の「+」ボタンを押して、「SwiftyJSON iOS」を選択して、「Add」ボタンを選択します。
これで、このプロジェクトでSwiftyJSONを使えるようになりました。
6)Info.plistに例外処理をし、HTTP通信を可能にします。
iOS 9から、ATS(App Transport Security)というセキュリティ機能が付きました。ATSが有効のときは、HTTP通信ができません。Info.plistに例外としてドメインを設定し、そのドメインとHTTP通信できるようにします。
- [Info.plist]を選択して、[Add Raw]メニューで1行追加し、Keyに[NSAppTransportSecurity]を入力、Typeを[Dictionary]にします。
- 三角アイコンを下向きにして、[Add Raw]メニューで1行追加し、Keyに[NSExceptionDomains]を入力、Typeを[Dictionary]にします。
- 三角アイコンを下向きにして、[Add Raw]メニューで1行追加し、Keyに[express.heartrails.com]を入力、Typeを[Dictionary]にします。
- 三角アイコンを下向きにして、[Add Raw]メニューで1行追加し、Keyに[NSTemporaryExceptionAllowsInsecureHTTPLoads]を入力、Typeを[Boolean]、Valueを[Yes]にします。
これで、「express.heartrails.com」とHTTP通信できるようになりました。あとは、いつものようにアプリを作っていきます。
7)画面に[Button]と[textView]と[Label]を配置して、アプリ画面を作ります。
「Main.storyboard」を選択し、右下のライブラリーから[Button]と[textView]と[Label]をドラッグ&ドロップして配置します。Labelには「情報:HeartRails Inc.」と書きます。右下の「|△|」ボタンを押して、「Reset to Suggested Constraints(自動レイアウト設定)」を選択します。
Main.storyboardの仮画面の中央にボタンを配置しただけでは、縦長のiPhone画面で見るとボタンが端に表示されてしまいます。自動レイアウト設定をすることで、縦長の画面でも中央に表示されます。
8)[textView]に名前をつけてコントロールします。
メニューで「View」→「Assitant Editor」→「Show Assistant Editor」を選択して、「アシスタントエディター」を表示し、キーボードのcontrolを押しながら、textViewをViewController.swiftへドラッグして、名前を「myTextView」とします。
ViewControll.swiftにコード、
@IBOutlet weak var myTextView: UITextView!
が追加されます。
9)ボタンが押されたときに実行される関数を作ります。
ボタンが押されたときの命令を記述するための関数を作ります。
キーボードのcontrolを押しながら「Button」をViewController.swiftへドラッグし、「Connection」を「Action」に切り換えてボタンを押したとき実行する関数を作ります。関数名は「tapBtn」にします。
10)ViewController.swiftに、プログラムを記述します。
ボタンが押されたときに、heartrailsからJSONデータをダウンロードして解析し、アプリに表示プログラムを記述します。
取得するAPIのURLを用意して、「sendAsynchronousRequest」で非同期ダウンロードを実行します。
例えば、JR山手線の駅名を取得するには「http://express.heartrails.com/api/json?method=getStations&line=JR山手線」となります。路線名は「東京メトロ銀座線」「JR大阪環状線」など指定できますが、URLに日本語が含まれるのでUTF8にURL エンコードします。(18行目)
データの読み込み完了の合図が来たら、JSONに変換します。
データの階層構造を参考にして解析します。
路線名は、json["response"]["station"][0]["line"]
その路線に含まれる駅名は、json["response"]["station"][id]["name"]
で取り出すことができます。
取り出したデータを「myTextView」に表示します。
記述したプログラムは以下の通りです。
// SwiftyJSONを使うのでimport
import SwiftyJSON
class ViewController: UIViewController {
@IBOutlet weak var myTextView: UITextView!
@IBAction func tapBtn(sender: AnyObject) {
let URLstr = "http://express.heartrails.com/api/json?method=getStations&line=JR山手線"
// 日本語入りのURLなので、UTF8形式に変換する
let encodeURL:String = URLstr.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!
if let url = NSURL(string: encodeURL) {
let request = NSURLRequest(URL: url)
// データの読み込みが終わったら dispStationsを実行
NSURLConnection.sendAsynchronousRequest(
request,
queue: .mainQueue(),
completionHandler: dispStations)
}
}
// 表示するメッセージを入れる変数
var msg:String = ""
// 返ってきたJSONデータを解析して駅名表示
func dispStations(res: NSURLResponse?, data: NSData?, error: NSError?){
if error == nil {
// JSONデータに変換する
let json = JSON(data:data!)
// 路線名を取得
let linename = json["response"]["station"][0]["line"]
msg += "路線名=\(linename)\n"
// 路線内の各駅名を取得
let linedata = json["response"]["station"]
for id in 0..<linedata.count {
let name = linedata[id]["name"]
msg += "駅[\(id)]=\(name)\n"
}
// 駅名リストを表示
myTextView.text = msg }
}
//(中略)
ボタンを押すと、JR山手線の駅名が「textView」に表示されます。
◆
今回は外部 APIを取得し、ライブラリーを使って解析する方法を紹介しました。
プログラムは、自分だけでもすべてを作れますが、他の人が作ったデータやライブラリーを利用して作ると、手間がだいぶ省けます。保守され続けているライブラリーは、自分で作るよりも機能が豊富で、安全な場合もあります。
「いつかは自分もライブラリーを作る側になれたら」を目標に利用したいですね。