Skip to content

JSONFrameworkを非同期で活用する

2011年7月7日

JSONFrameworkを活用するにあたって、別のクラス内で非同期パースして結果だけ得たいって事でつくってみた。

前提として、帰ってくるJSONはdatas:[]が頭についてます。

statusGetter.h

#import <Foundation/Foundation.h>
#import "SBJson.h"

@protocol statusGettrDelegate <NSObject>

- (void)DataDownloadFinished:(NSMutableArray *)data;
- (void)DataDownloadFailed:(id)data;

@end

@interface statusGetter : NSObject {

    id delegate;
    NSInteger statusCode;
    NSMutableArray *dataSource_;
    NSMutableData *data_;

}

@property(nonatomic,retain) id delegate;
@property(nonatomic,assign)NSInteger statusCode;
@property(nonatomic,retain)NSMutableArray *dataSource_;
@property(nonatomic,retain)NSMutableData *data_;

- (void)honyarararara:(NSString *)userid;

@end

statusGetter.m

#import "statusGetter.h"

@implementation statusGetter

@synthesize delegate;
@synthesize statusCode;
@synthesize dataSource_;
@synthesize data_;

- (void)dealloc
{
    NSLog(@"statusGetterdealloc");
    [dataSource_ release];
    [data_ release];
    [super dealloc];
}

//GETで帰ってきた値の先頭4文字を確認する
-(id) jsonHeadChecker:(NSString *)json_string{
    if ([json_string isEqualToString:@""]) {
        NSLog(@"返り値無し");
        return nil;
    }
    if ([[json_string substringToIndex:4] isEqualToString:@"<htm"]) {
        NSLog(@"先頭がHTML");
        return nil;
    }
    if ([[json_string substringToIndex:4] isEqualToString:@"<?xm"]) {
        NSLog(@"先頭がXML");
        return nil;
    }
    return json_string;
}

/// サーバからレスポンスが送られてきたときのデリゲート
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
    NSLog(@"didReceiveResponse");
    NSLog(@"ステータスコート判別----------");
	NSHTTPURLResponse *res = (NSHTTPURLResponse *)response;
	statusCode = [res statusCode];
}

/// サーバからデータが送られてきたときのデリゲート
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
    NSLog(@"didReceiveData");
    //分割されたデータを統合
    [data_ appendData:data];
}

/// データのロードか完了した時のデリゲート
- (void)connectionDidFinishLoading:(NSURLConnection *)connection{
    NSLog(@"connectionDidFinishLoading");
    if (statusCode == 200) {
        NSLog(@"Code200 : 通常処理");
        [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
        // 通常処理
    } else {
        NSLog(@"Code%d : エラー処理",statusCode);
        [connection cancel];
        [delegate DataDownloadFailed:nil];
        [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
        // エラー処理
    }

    //    NSLog(@"%@",response);
    NSString *json_string = [[[NSString alloc] initWithData:data_ encoding:NSUTF8StringEncoding] autorelease];
    NSLog(@"json_string : %@",json_string);
    NSString *checker = [self jsonHeadChecker:json_string];

    if (!checker) {
        NSLog(@"JSONが返ってきていません");
        [delegate DataDownloadFailed:nil];
        [connection cancel];
    }

    NSMutableDictionary *statuses = [json_string JSONValue];
    NSLog(@"didReceiveData : statuses:%@",statuses);

    //データがひとつの時は、配列ではなく辞書で返される
    if ([[statuses objectForKey:@"datas"] isKindOfClass:[NSDictionary class]]) {
        NSLog(@"Dictionaryです");
        //Datasの包みを外す
        [dataSource_ addObject:[statuses objectForKey:@"datas"]];
    }else{
        NSLog(@"Dictionaryじゃないです");
        //Datasの包みを外す
        [dataSource_ setArray:[statuses objectForKey:@"datas"]];
    }

    NSLog(@"dataSource:%@",dataSource_);
    [delegate DataDownloadFinished:dataSource_];
}

/// サーバからエラーが返されたときのデリゲート
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
    NSLog(@"didFailWithError");
    [delegate DataDownloadFailed:nil];
}

データ取得
- (void)honyarararara:(NSString *)userid{
    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
    dataSource_ = [[NSMutableArray alloc] init];
    data_ = [[NSMutableData alloc] init];
    NSString *urlStr = [[NSString alloc] initWithFormat:@"http://XXXXXXXXX/%@",userid];
    NSLog(@"URL:%@", urlStr);
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlStr]];
    [urlStr release];
    [NSURLConnection connectionWithRequest:request delegate:self];
}

あとは、使いたいクラスのヘッダーで statusGetterDelegateを入れて、viewDidLoadあたりで、statusGetter.delegate = self; をやって、以下のデリゲートメソッドを書く

-(void)DataDownloadFinished:(NSMutableArray *)data{
    NSLog(@"JSONDownloadFinish");
    NSLog(@"data%@",data);
    [dataSource_ setArray:data];

    [self.tableView reloadData];
}

-(void)DataDownloadFailed:(id)data{
    NSLog(@"faild : %@",data);
    if (!data) {
        UIAlertView *alert =[[UIAlertView alloc] initWithTitle:@"サーバーエラー" message:@"データが取得できませんでした" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
        [alert show];
        [alert release];
    }
}

デリゲートで値を返さないと、何故か[self.tableView reload]が動いてくれなかったので注意。あと、didReceiveDataでは、データが大きいとデータが分割されて送られてくるので注意。しかも個々の動きは、シミュレータと実機では違うので気をつけること。

広告

From → iPhone開発

コメントする

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中

%d人のブロガーが「いいね」をつけました。