SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

スマホアプリ開発の最新トレンド! ぜったい外せない位置情報活用術

YOLPでiPhoneアプリに挑戦~最寄コンビニ案内アプリ

スマホアプリ開発の最新トレンド! ぜったい外せない位置情報活用術(3)

  • X ポスト
  • このエントリーをはてなブックマークに追加

3. 現在位置周辺のコンビニを探し、地図上にピンを立てる

 現在地周辺の地点情報を調べるために、YOLPの「ローカルサーチAPI」を利用します。

 今回のアプリでは、「電話帳」カセットを指定して、「現在地周辺10km以内のコンビニ」を検索することにします。

補足

 それ以外にも、ローカルサーチでは「カセット」を指定することにより、さまざまなPOIを検索することができますので、過去の連載記事(「YOLP Hacks: ローカルサーチAPIの使い方 ~パラメーターを極める!」)なども参考にしていただき、パラメータを操作していろいろ試してみてください。

 また、カセットは、「YOLP カセットギャラリー」から探すことができます。

3-1. JSONパース用のライブラリを読み込む

 APIのレスポンスはJSON形式で受け取ることにして、JSONをパースするためのライブラリは「SBJson」を利用します。

 SBJsonとは、New BSD Licenseで公開されているフリーのライブラリで、著作権の表示と、無保証、免責の条件を守れば、誰でも利用することができます。

 現在の最新安定版SBJson3.0系をダウンロードし、zipファイルを解凍します。解凍したファイルのClassesフォルダ以下をプロジェクトに読み込ませます。

3-2. 「ローカルサーチAPI」アクセスクラス作成

 次に、「ローカルサーチAPI」にアクセスするためのクラスを新規に作成します。

 ファイルのタイプはObjective-C classで、親クラスはNSObjectを選択して、新規ファイルを作成してください。名前はYolpLocalSearchとします。

 データ通信を行うため、YolpLocalSearch.hにNSURLConnectionDataDelegateプロトコルを設定します。

 また、APIから取得したデータの処理をViewControllerで行わせるために、YolpLocalSearch.hでYolpLocalSearchDelegateプロトコルを宣言し、メソッドを追加します。

YolpLocalSearch.h
#import <Foundation/Foundation.h>

@protocol YolpLocalSearchDelegate; //プロトコルを宣言

@interface YolpLocalSearch : NSObject<NSURLConnectionDataDelegate>
{
    CGFloat _lat;
    CGFloat _lon; 
    
    NSURLConnection *_connection;
    NSMutableData *_data; 
    
    id _result;
    id<YolpLocalSearchDelegate> _delegate;
    NSError* _error;
}

@property (nonatomic,readonly) id result;
@property (nonatomic,assign) id<YolpLocalSearchDelegate> delegate;
@property (nonatomic,readonly) NSError *error;

- (id) initWithLat:(CGFloat)lat Lon:(CGFloat)lon;
- (BOOL) searchPointByLocation;
- (BOOL) validate;

@end

// プロトコルのメソッドを宣言
@protocol YolpLocalSearchDelegate <NSObject>

-(void)didFinishWithYolpLocalSearch:(YolpLocalSearch *)station;
-(void)didFailWithYolpLocalSearch:(YolpLocalSearch *)station;

@end

 YolpLocalSearch.mでは、先ほどプロジェクトに追加したSBJsonのヘッダーファイルをインポートします。

 ViewController.mから、緯度経度情報を付与した初期化メソッド- (id) initWithLat:(CGFloat)lat Lon:(CGFloat)lonを実行し、- (BOOL) searchPointByLocation;を呼ぶと、ローカルサーチAPIの検索が行われます。

 APIのレスポンスは非同期で受け取り、データの受信が完了したらエラーチェックの後、-(void)didFinishWithYolpLocalSearch:(YolpLocalSearch *)stationに渡されます。

 このメソッド内でJSONのパース処理が呼ばれ、APIのレスポンスはNSArrayとNSDictionary形式に変換されます。

YolpLocalSearch.m
#import "YolpLocalSearch.h"
#import "JSON/SBJson.h"  //SBJsonをインポート

#define API_YOLPSEARCH @"http://search.olp.yahooapis.jp/OpenLocalPlatform/V1/localSearch"
#define APPID_YOLPSEARCH @"<あなたのアプリケーションID>"
#define CID_YOLPSEARCH @"d8a23e9e64a4c817227ab09858bc1330" // 電話帳カセットのカセットID

@implementation YolpLocalSearch

@synthesize result   = _result;
@synthesize delegate = _delegate;
@synthesize error    = _error;

// 初期化
- (id)initWithLat:(CGFloat)lat Lon:(CGFloat)lon
{
    self = [super init];
    if (self) {
        _lat = lat;
        _lon = lon;
        _connection = nil;
        _data       = nil;
    }
    return self;
}

- (void) dealloc
{
    // インスタンス変数を開放する
    [_connection release];
    [_data       release];
    [_error      release];
    _delegate = nil;
    [super dealloc];
}

// 検索のトリガーとなるメソッド。このメソッドをViewControllerから実行する
- (BOOL) searchPointByLocation 
{
    if(_connection){
        return FALSE;
    }
    
    NSString *query = [NSString stringWithString:@"コンビニ"];
    query = [query stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    
    NSString* sYolpUrl = [NSString stringWithFormat:@"%@?output=json&appid=%@&cid=%@&detail=full&group=gid&distinct=true&start=1&results=10&dist=10&sort=dist&lat=%f&lon=%f&query=%@", API_YOLPSEARCH, APPID_YOLPSEARCH, CID_YOLPSEARCH, _lat, _lon, query];
// ローカルサーチAPIのリクエストURLを作成

    // NSURLオブジェクトからNSURLREquestオブジェクトを作成
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:sYolpUrl] cachePolicy:0 timeoutInterval:10];
    _connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
    
    return YES;
}

//レスポンスのバリデーション
-(BOOL)validate{
    if(_result == nil){
        if (_error == nil) {
            _error = [[NSError alloc] initWithDomain:@"YolpLocalSearchError" code:0 userInfo:nil];
        }
        return  FALSE;
    }
    return TRUE;
}

// サーバからレスポンスが送られてきたことを通知
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
    //[super connection:connection didReceiveResponse:response];
    
    // レスポンスのステータスをチェック
    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
    if(httpResponse.statusCode < 400){
        // 正常レスポンスであれば、変数をクリアする
        if (_data) {
            [_data release];
        }
        _data = [[NSMutableData alloc] init];
    }else{
        // エラーであれば、接続を中断する
        [_connection cancel];
        [_connection release];
        _connection = nil;
    }
    
    if(httpResponse.statusCode >= 400){
        _error = [[NSError alloc] initWithDomain:@"YolpLocalSearchError" code:httpResponse.statusCode userInfo:nil];
        if ([_delegate respondsToSelector:@selector(didFailWithYolpLocalSearch:)]) {
            [_delegate performSelector:@selector(didFailWithYolpLocalSearch:) withObject:self];
        }
    }
}

// サーバからダウンロードしたデータ(data)を通知
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    if(_data){
        [_data appendData:data];
    }
}

// ダウンロードが完了したことを通知
- (void)connectionDidFinishLoading:(NSURLConnection *)connection 
{
    [_connection release];
    _connection = nil;
    
    NSString *tmpString = [[NSString alloc] initWithData:_data encoding:NSUTF8StringEncoding];
    _result = [[tmpString JSONValue] retain];  // JSONをパースする
    [tmpString release];
    if([self validate]){
        if ([_delegate respondsToSelector:@selector(didFinishWithYolpLocalSearch:)]) {
            [_delegate performSelector:@selector(didFinishWithYolpLocalSearch:) withObject:self];
        }
    }else{
        if ([_delegate respondsToSelector:@selector(didFailWithYolpLocalSearch:)]) {
            [_delegate performSelector:@selector(didFailWithYolpLocalSearch:) withObject:self];
        }
    }
    [_result release];
}

//通信がエラーになったことを通知
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 
{
    if(_data){
        [_data release];
        _data = nil;    
    }
    [_connection release];
    _connection = nil;
    
    _error = [error retain];
    if ([_delegate respondsToSelector:@selector(didFailWithYolpLocalSearch:)]) {
        [_delegate performSelector:@selector(didFailWithYolpLocalSearch:) withObject:self];
    }
}
@end

次のページ

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
スマホアプリ開発の最新トレンド! ぜったい外せない位置情報活用術連載記事一覧

もっと読む

この記事の著者

市川 晶子(ヤフー株式会社)(イチカワ アキコ(ヤフーカブシキガイシャ))

2007年にYahoo! JAPAN入社。主に「Yahoo!ロコ 路線」の開発を担当。PC版・モバイル版の路線サービスリニューアル、YOLPカセットギャラリーの立ち上げなどを担当したあと、iPhoneアプリ「乗換案内 Yahoo!ロコ」の開発を担当。趣味はスキューバダイビングで、MTES Assis...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/6544 2012/04/20 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング