Three20 JSON datasource implementation – revetkn.com
Three20とjson-frameworkを使って簡単にタイムライン画面を作ってみる。
それぞれセットアップは以下を参考に
【Three20】をプロジェクトで使えるようにする手順 | iphoneアプリで稼げるのか[iPhone] JSON Framework の使い方(準備編) | Sun Limited Mt.
※JSONFramework側の不具合で上記リンクの通り設定した場合でも、OS3.0で使うと実機転送時にcode signエラーが出た。そんな時は「他のリンカフラグ」等の設定はせずに、JSONディレクトリの中身のファイル達を直接プロジェクトに追加で回避できる。6月末に修正されたらしいので最新版を使えばだいじょぶかもしれない。
json-framework – Google Code
最低限のAPI仕様は
- http://twitter.com/statuses/friends_timeline.jsonへ
- ベーシック認証つきで
- GETメソッドでリクエストを投げる
例によってTwitter APIの詳細は公式wikiに譲る。
Twitter API Wiki / Twitter REST API Method: statuses friends_timeline
Three20の中でも今回は
- コントローラとしてTTTableViewController
- データソースとしてTTListDataSource
- テーブルフィールドとしてTTIconTableField
- HTTPアクセスはTTURLRequest
コードは以下。
コントローラ
FirstViewController.h#import
#import "Three20/Three20.h"
@interface FirstViewController : TTTableViewController {
}
@end |
FirstViewController.m
#import "FirstViewController.h"
#import "JSONDataSource.h"
@implementation FirstViewController
- (void)loadView {
self.view = [[[UIView alloc] initWithFrame:[UIScreen mainScreen].applicationFrame] autorelease];
self.view.backgroundColor = RGBCOLOR(240, 242, 245);
self.variableHeightRows = YES;
// STATUS_HEIGHTはTTGlobal.hで定義されてるステータスバーの高さを表す定数
self.tableView = [[[UITableView alloc] initWithFrame:CGRectMake(0, 0, 320, 480 - STATUS_HEIGHT)
style:UITableViewStylePlain] autorelease];
self.tableView.autoresizingMask =
UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.tableView.sectionIndexMinimumDisplayRowCount = 2;
[self.view addSubview:self.tableView];
}
// この辺はTTTableViewControllerのdelegateメソッド
// ここで返したデータソースを使ってTTTableViewControllerが描画もろもろやってくれる
- (id)createDataSource {
JSONDataSource *dataSource = [[[JSONDataSource alloc] init] autorelease];
[dataSource load:TTURLRequestCachePolicyNoCache nextPage:NO];
return dataSource;
}
- (UIImage*)imageForError:(NSError*)error {
return [UIImage imageNamed:@"Three20.bundle/images/error.png"];
}
@end |
データソース
JSONDataSource.h#import
#import "Three20/Three20.h"
@interface JSONDataSource : TTListDataSource {
@private
// 読み込み中フラグ
BOOL _isLoading;
// 読み込み完了フラグ
BOOL _isLoaded;
// ここいらのフラグを見て読み込み中Activityとか出し分けしてる様子
}
@end |
JSONDataSource.m
#import "JSONDataSource.h"
static NSString *username = @"username";
static NSString *password = @"password";
@implementation JSONDataSource
- (id)init {
if (self = [super init]) {
_isLoading = YES;
_isLoaded = NO;
}
return self;
}
#pragma mark TTTableViewDataSource
- (void)load:(TTURLRequestCachePolicy)cachePolicy nextPage:(BOOL)nextPage {
// この辺はTwitterポスト時とほぼ同じ
static NSString *jsonUrl = @"http://%@:%@@twitter.com/statuses/friends_timeline.json";
NSString *url = [NSString stringWithFormat:jsonUrl, username, password];
TTURLRequest *request =
[TTURLRequest requestWithURL:url delegate:self];
request.cachePolicy = cachePolicy;
request.response = [[[TTURLDataResponse alloc] init] autorelease];
request.httpMethod = @"GET";
BOOL cacheHit = [request send];
NSLog((cacheHit ? @"Cache hit for %@" : @"Cache miss for %@"), jsonUrl);
}
#pragma mark TTLoadable
- (BOOL)isLoading {
return _isLoading;
}
- (BOOL)isLoaded {
return _isLoaded;
}
#pragma mark TTURLRequestDelegate
- (void)requestDidStartLoad:(TTURLRequest*)request {
_isLoading = YES;
_isLoaded = NO;
[self dataSourceDidStartLoad];
}
- (void)requestDidFinishLoad:(TTURLRequest*)request {
// 通常通りレスポンスゲット
TTURLDataResponse *response = request.response;
NSString *responseBody = [[NSString alloc] initWithData:response.data encoding:NSUTF8StringEncoding];
// JSONFrameworkのメソッドでArrayとして受け取る。JSONの構造次第でNSDictionaryの可能性もあるのでAPI要確認
NSArray *json = [responseBody JSONValue];
for(NSDictionary *result in json) {
// JSON内のデータ構造はTwitter APIを参照
NSDictionary *user = [result valueForKey:@"user"];
// データソースの要素としてTTIconTableFieldをセット。これでアイコンとテキストがワンセットのテーブルになる。
[self.items addObject:[[[TTIconTableField alloc]
// JSONからテキスト取得
initWithText:[result objectForKey:@"text"]
url:nil
// JSONから画像取得
image:[user objectForKey:@"profile_image_url"]
// 画像読み込み前のデフォルト画像を指定。ここは自分で用意
defaultImage:[UIImage imageNamed:@"DefaultAlbum.png"]] autorelease]];
}
_isLoading = NO;
_isLoaded = YES;
[self dataSourceDidFinishLoad];
}
// この辺はNSURLRequestでおなじみな感じ
- (void)request:(TTURLRequest*)request didFailLoadWithError:(NSError*)error {
NSLog([error localizedDescription]);
NSLog(@"didFailLoadWithError");
_isLoading = NO;
_isLoaded = YES;
[self dataSourceDidFailLoadWithError:error];
}
- (void)requestDidCancelLoad:(TTURLRequest*)request {
NSLog(@"requestDidCancelLoad");
_isLoading = NO;
_isLoaded = YES;
[self dataSourceDidCancelLoad];
}
@end |
以上で、こんな画面の出来上がり。

これだけで、ネットワーク接続エラー時の対応やデータキャッシュや読み込み中表示などをこちらが意識せずとも勝手にやってくれる。
※表示項目をよりtwitterクライアントにしたい場合は別途カスタマイズが必要。
JSONに関してはアクセス先のURLと取り出し方法の2つが外部APIに依存する部分なので、その辺をdelegateに任せるなりすればこのソースをうまいこと活用できると思う。
タグ: API, doxygen, iphone, JSON, NSArray, NSString, objecti, objective-c, Three20, twitter, UITableView, アイコン, アプリ, 高さ

