koogawa blog

iOS、Android、foursquareに関する話題

近隣のべニューをリスト表示するiPhoneアプリを作ってみよう(前編)

今回は foursquare API

v2/venues/search

API を使い、 近隣のべニューをリスト表示するアプリを作ってみます。

対象スキル

本記事では、Objective-Cの基礎や、UIKitの使い方など、入門レベルの解説は省かせて頂きます。

今回使用した開発環境

なお、本ブログのポリシーに乗っ取り、今回もInterface builderは使用しません。

新規プロジェクトの作成

まずはプロジェクトを作成します。Xcodeを起動し、 メニューから[File] > [New] > [New Project]を選択します。



左のメニューから「Application」を選択します。その中の「Single View Application」を選択して「Next」ボタンを押します。



プロジェクト名などを入力します。
次のように入力し、「Next」ボタンを押します。

Product Name VenueList
Company Identifier com.yourcompany
Class Prefix そのまま
Device Family iPhone


保存先を聞かれるので、適当な場所を選んで保存します。このとき、「Create local git repository for this project」にはチェックを入れないでおきます。

テーブルビューを選択

今回は取得したデータをリスト表示するので、UIViewControllerではなく、 UITableViewContorollerを使います。

メニューから[File] > [New] > [New File]を選択します。



左のメニューから「Cocoa Touch」を選択し、その中の「UIViewController subclass」を選択して「Next」ボタンを押します。



次のように入力して「Next」を押します。

Class VenueListTableViewController
Subclass of UITableViewController


保存先を聞かれるので、適当な場所を選んで保存します(通常は変更する必要なし)。Groupに「VenueList」が選択され、Targetsの「VenueList」にチェックが入っていることを確認して「Create」ボタンを押します。

現在のソースコードは起動時にViewControllerを開くようになっているので、これをViewListTableViewControllerに変更します。

AppDelegate.hを開き、次のように書き換えます。

#import <UIKit/UIKit.h>

@class VenueListTableViewController;

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) VenueListTableViewController *viewController;

@end


次にAppDelegate.mを開き、11行目あたりにあるimport文を次のように書き換えます。

#import "VenueListTableViewController.h"

25行目あたりにある

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;

も書き換えましょう。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
    // Override point for customization after application launch.
    self.viewController = [[[VenueListTableViewController alloc] init] autorelease];
    self.window.rootViewController = self.viewController;
    [self.window makeKeyAndVisible];
    return YES;
}

これで、ViewListTableViewControllerを読みにいくようになりました。

この時点で一度アプリを実行してみましょう。
画面左上に「Run」と書かれた再生マークのようなボタンがあるのでクリックします。



まだ何も実装していないので空のリストが表示されるだけですが、とりあえずアプリのベースが出来上がりました。ここから各機能を実装していきます。

なお、自動的に作られたViewController.hViewController.mは使わないので削除して構いません。

まずは固定の配列で試してみる

foursquare APIからベニューリストを取得する前に、まずは固定のデータを表示してみます。

最初にべニューリストを格納するメンバ変数を用意し、初期化します。

VenueListTableViewController.h

@interface VenueListTableViewController : UITableViewController
{
    NSMutableArray *venues_;
}

VenueListTableViewController.m

- (id)initWithStyle:(UITableViewStyle)style
{
    self = [super initWithStyle:style];
    if (self) {
        // Custom initialization
        venues_ = [[NSMutableArray alloc] init];
    }
    return self;
}

次に、viewDidLoad(ビューが読み込まれたタイミングで呼ばれる)の中で固定の配列を作ります。

// APIから返ってくるデータと仮定
NSArray *response = [NSArray arrayWithObjects:@"近くの駅", @"ラーメン屋", @"コンビニ", nil];
venues_ = [response mutableCopy];

配列ができたら、リスト全体をリロードします。

[self.tableView reloadData];

リストのセクション数を指定するnumberOfSectionnumberOfSectionsInTableViewには1を、セクション中のリスト数を指定するnumberOfRowsInSectionには今作った配列の要素数を指定します。

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    // Return the number of sections.
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Return the number of rows in the section.
    return [venues_ count];
}

セルのタイトルをセットしてやります。

cell.textLabel.text = [venues_ objectAtIndex:indexPath.row];

ここで、一度アプリを実行してみましょう。



とりあえず、固定のデータが表示されるようになりました。

次はいよいよAPIにアクセスします。

アプリケーションの登録

APIにアクセスする前に、アプリケーションの登録を行います。
ここで発行されるconsumer keyがないとデータを取得できません。

https://ja.foursquare.com/oauth/

にアクセスし、ページ右上の「REGISTER A NEW CONSUMER」ボタンをクリックします。

「APPLICATION NAME」には文字通りアプリケーション名を入力します。ここは好きな名前で問題ないのですが、ここでは「Venue List」と入力しました。「APPLICATION WEB SITE」「CALLBACK URL」にはアプリの紹介サイトなどを入力するのですが、今回はWebアプリではないため、仮にhttp://www.example.com/を入力しておきました。

「ENTER TEXT BELOW」に画像の文字を入力し、「REGISTER APPLICATION」ボタンを押すと「CLIENT ID」「CLIENT SECRET」が発行されます。

APIからベニューリストを取得する

foursquare APIにアクセスする準備は整ったので、実際にソースコードを書き換えていきます。

NSArray *response = [NSArray arrayWithObjects:@"近くの駅", @"ラーメン屋", @"コンビニ", nil];
venues_ = [response mutableCopy];

前回は、上記のように固定のデータを作成していましたが、この部分をいったん削除します。

次に、APIのURLを格納する文字列を作成します。

NSString *urlString = [NSString stringWithFormat:@"https://api.foursquare.com/v2/venues/search?ll=35.702065,139.775308&limit=20&client_id=(あなたのCLIENT_ID)&client_secret=(あなたのCLIENT_SECRET)&v=20111111"];

"ll"パラメータにはGPSで取得した現在地の緯度経度等を指定しますが、今回は六本木駅付近(35.702065,139.775308)を指定します。

最大取得数"limit"にはとりあえず20を指定しておきます。

"client_id""client_secret"には、先ほど取得した「CLIENT ID」「CLIENT SECRET」を指定してください。

"v"に指定する日付には「この日付時点での仕様に基づいたレスポンスを返してね」といった意味があります。この値を指定しておけば、APIの仕様が変更になった場合も返ってくるレスポンス仕様は変わらないので安心、というわけです。今回はこの記事を書いている20111111(2011年11月11日)を指定しておきます。

次に、この文字列をNSURL型に変換し、リクエストを送信します。

NSURL *url = [NSURL URLWithString:urlString];
NSString *response = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];

変数responseには、APIからのレスポンスデータがJSON形式で格納されます。

JSON結果

{
    "meta": {
        "code": 200
    },
    "response": {
        "venues": [
            {
                "id": "4b586bbdf964a520f45628e3",
                "name": "MOGRA 秋葉原",
                "categories": [
                    {
                        "icon": {
                            "name": ".png",
                            "prefix": "https://foursquare.com/img/categories/arts_entertainment/musicvenue_",
                            "sizes": [
                                32,
                                44,
                                64,
                                88,
                                256
                            ]
                        },
                        "id": "4bf58dd8d48988d1e5931735",
                        "name": "Music Venue",
                        "pluralName": "Music Venues",
                        "primary": true,
                        "shortName": "Music Venue"
                    }
                ],
                "contact": {
                    "formattedPhone": "03-6206-8338",
                    "phone": "0362068338"
                },
                "hereNow": {
                    "count": 0
                },
                "location": {
                    "address": "秋葉原3-11-B1",
                    "city": "台東区",
                    "country": "日本",
                    "distance": 23,
                    "lat": 35.702122269999997,
                    "lng": 139.7750532,
                    "postalCode": "110-0006",
                    "state": "東京都"
                },
                "stats": {
                    "checkinsCount": 1773,
                    "tipCount": 2,
                    "usersCount": 747
                },
                "url": "http://club-mogra.jp",
                "verified": false
            },
            …
            {
            }
        ]
    }
}

これをNSJSONSerialization(iOS5から使用可)を使ってNSDictionary形式に変換してやります。
JSONObjectWithDataメソッドに通すために、いちどNSData型に変換しています。
※エラー処理は省略しています。

NSData *jsonData = [response dataUsingEncoding:NSUTF32BigEndianStringEncoding];
NSDictionary *jsonDic = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:nil];

ここからresponse->venuesを取り出し、NSMutableArray型のvenues_に格納してやります。

NSArray *venues = [[jsonDic objectForKey:@"response"] objectForKey:@"venues"];
venues_ = [venues mutableCopy];

これで実装はすべて完了です!早速実行してみましょう。

APIから取得したベニューのリストが表示されたと思います。

まとめ

今回はfoursquare APIを用いてベニューリストを取得し、リスト表示するアプリを作成しました。
ただ、このままだと毎回同じ場所のベニューリストが表示されるだけなので、次回はGPSを使い、現在地周辺のを取得してみる予定です。

なお、今回作成したアプリのソースはこちらにアップしております。

https://github.com/koogawa/VenueList