StatusXMLParserクラスをRootViewControllerクラスから呼び出して使ってみましょう。「RootViewController.h」を以下のように編集します。
#import <UIKit/UIKit.h> @interface RootViewController : UITableViewController { NSArray *statuses; } @property(retain, nonatomic) NSArray *statuses; @end
RootViewController.hには解析済みのデータを保存するstatusesプロパティを追加します。
実装ファイルのRootViewController.mにStatusXMLParser.hをインポートします。
#import "StatusXMLParser.h"
また、プロパティの実装も宣言します。
@synthesize statuses
次に、loadTimeLineDidEndメソッドを次のように書き換えます。
- (void) loadTimeLineDidEnd: (NSNotification *)notification { URLLoader *loder = (URLLoader *)[notification object]; NSData *xmlData = loder.data; StatusXMLParser *parser = [[[StatusXMLParser alloc] init] autorelease]; self.statuses = [parser parseStatuses:xmlData]; [self.tableView reloadData]; }
ログ出力処理の代わりにStatusXMLParserを呼び出し、解析した結果をstatusesに設定しています。その後Viewの更新処理を読び出します。
さらに、下記2つのメソッドを以下のように編集してください。
// (14) - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [self.statuses count]; } //(15) - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:CellIdentifier] autorelease]; } int row = [indexPath row]; NSString *name = [[statuses objectAtIndex:row] objectForKey:@"name"]; NSString *text = [[statuses objectAtIndex:row] objectForKey:@"text"]; // ユーザー名 cell.textLabel.font = [UIFont systemFontOfSize:16]; cell.textLabel.textColor = [UIColor lightGrayColor]; cell.textLabel.text = name; // テキスト cell.detailTextLabel.numberOfLines = 0; cell.detailTextLabel.font = [UIFont systemFontOfSize:14]; cell.detailTextLabel.text = text; return cell; }
「Navigation-based Application」テンプレートから作られたRootViewControllerクラスはUITableViewControllerというクラスを継承して作られており、この親クラスがもつデリゲートメソッドを上書きしてUITableViewの表示をコントロールできます。
表示行数を設定するためメソッドです。今回は、statusesプロパティの持つデータの数を返しています。
UITableViewの1つ1つのセルをどのように表示するかの設定を行うメソッドです。statusesプロパティから「ユーザー名」「つぶやき」を取得し、それぞれラベルに設定しています。
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:CellIdentifier] autorelease];
上記部分でinitWithStyle の引数を初期値のUITableViewCellStyleDefaultから UITableViewCellStyleValue2に変更するのを忘れないようにしてください。
ここまでの編集が完了したらシミュレータで実行してみましょう。
情報は表示できているようですが、行の高さが低いため、つぶやきの内容が隠れて見えなくなってしまっています。行の高さを調節するには、RootViewController.mに以下のメソッドを追加します。
- (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath { UITableViewCell *cell = [self tableView:self.tableView cellForRowAtIndexPath:indexPath]; CGSize bounds = CGSizeMake(self.tableView.frame.size.width - 150, self.tableView.frame.size.height); CGSize size = [cell.detailTextLabel.text sizeWithFont: cell.detailTextLabel.font constrainedToSize: bounds lineBreakMode: UILineBreakModeCharacterWrap]; return size.height; }
ここでは固定の高さではなく、表示領域の横幅と文字の長さに応じた高さを取得して返すようにしています。
CGSizeMake(self.tableView.frame.size.width - 150, self.tableView.frame.size.height);
上記の個所でつぶやき表示領域のサイズを取得しています。横幅に関しては、「テーブルの横幅 - ユーザー名のテキストラベルの横幅」とするのが望ましいのでしょうが、この時点ではユーザー名のテキストラベルの横幅も未設定なため大方の値として150と指定しています。
そうして算出したサイズを引数に、cell.detailTextLabel.textの「sizeWithFont: constrainedToSize: lineBreakMode」メソッドを呼び出し、文字の長さに応じた表示サイズを取得して返しています。
高さの設定が完了したので、もう一度シミュレータを起動してみましょう。セルの高さが内容に応じて調節されるようになっています。
ここまで来れば、あと一息で完成です。次に画面上につぶやきの更新ボタンを配置してみましょう。今回はInterface Builderは使わずに、ソースコードからボタンを設定します。
最初にRootVIewController.mに更新用のメソッド、reloadを追加します。
- (void) reload: (id)sender { [self loadTimeLineByUserName:@"itmedia"]; }
次に、viewDidLoadメソッドを編集し、更新ボタンの追加し、その更新ボタンが押されたら、reloadメソッドが呼ばれるようにします。ついでに、ナビゲーションバーの色もTwitterのイメージカラーに変更してみました。
- (void)viewDidLoad { [super viewDidLoad]; // ナビゲーションバーの色を青っぽく変更 self.navigationController.navigationBar.tintColor = [UIColor colorWithRed:0.3 green:0.6 blue:0.7 alpha:1.0]; // 更新ボタンの追加 self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:@selector(reload:)]; [self loadTimeLineByUserName:@"itmedia"]; }
最後に、通信中であることを表すnetworkActivityIndicatorを追加します。networkActivityIndicatorは以下のように、ステータスバーに回転する画像を表示する機能です。ソースコード中のフラグの切り替えだけで簡単に表示・非表示を設定できます
RootVIewController.m のloadTimeLineByUserName: userNameメソッド内の通信開始直前でnetworkActivityIndicatorVisibleプロパティを「YES」にすると、回転画像が表示されます。
- (void) loadTimeLineByUserName: (NSString *) userName ……【省略】…… [UIApplication sharedApplication].networkActivityIndicatorVisible = YES; [loder loadFromUrl:url method: @"GET"]; }
通信完了後は、loadTimeLineDidEndの先頭でnetworkActivityIndicatorVisibleを「NO」にすることで回転画像が非表示となります。
- (void) loadTimeLineDidEnd: (NSNotification *)notification { [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; ……【省略】…… }
以上で、Twitterアプリの完成です。
今回紹介した非同期通信によるデータの取得・XML解析は、TwitterだけでなくさまざまなWebサービスをiPhone/iPadから利用する際にも基本となる技術です。これらを用いることで作成できるiPhone/iPadアプリの幅がぐっと広がるのではないでしょうか。
次回も、さまざまな技術を紹介しますので、どうぞお楽しみに。
竹内 彰吾(たけうち しょうご)
どこにでもいる職業プログラマであり、好きな言語はJavaとObjective-C。現在は、業務システムの開発に従事し、顧客の要望に日々全力で応えている。
一方、ほかの案件や趣味ではiPhone/Androidアプリ開発にも積極的に取り組んでいる
Copyright © ITmedia, Inc. All Rights Reserved.