
こんにちは!クラウドナインアップスのショウです。
前回に引き続き、アプリ完成までの一部始終を解説していきたいと思います。
”「ファイナンス・経済ニュース」 アプリができるまで #1”では TableView について書きました。二回目となる今回は、RSSなどのXMLを読み込む(パースする)方法を解説していきたいと思います。
あと、リフレッシュコントロール(refreshControl)というメールやツイッターなどにある、下にスワイプすると更新される機能も付けたいと思います。

アプリ作成
手順② XMLParse
Xcodeでは[Event-driven API]という方法でXMLParseしています。
XMLの要素の読み込み毎に、以下のデリゲードメソッドが呼び出されます。
これらメソッドを用いて、XMLの中身を読み込んで行きます。
・parser:didStartElement:namespaceURI:qualifiedName:attributes:
エレメントの読み込み開始時のイベント
・parser:foundCharacters:
エレメントに挟まれた文字列要素を読み込んだ際のイベント
・parser:didEndElement:namespaceURI:qualifiedName:
エレメントの読み込み終了時のイベント
ViewController.h
前回(#1)、ViewController.hの@interfaceの末尾に
UITableViewDelegate,UITableViewDataSourceを書きました。
ここのうしろにNSXMLParserDelegateを追加で書きます。これを書かないとXMLParserは使えません。
また、XMLParserを使うための道具(nowTagStr,txtBuffer,urlTagStr)と
リフレッシュコントロール(_refreshControl)と
XMLParseで読み込んだニュースの情報を入れておくための文字列(titleString,urlString,dateString)
を追加で入れます。
@interface ViewController : UIViewController
<UITableViewDelegate,UITableViewDataSource,NSXMLParserDelegate>
{
NSString *nowTagStr;//解析中タグ
NSString *txtBuffer;//テキストバッファ
NSString *urlTagStr;//URLタグ
UIRefreshControl *_refreshControl;//リフレッシュコントロール
}
@property NSString *titleString;//ニュースタイトルの文字列
@property NSString *urlString;//ニュースURLの文字列
@property NSString *dateString;//日付の文字列
@end
ViewController.m
viewDidLoadにリフレッシュコントロールと
起動したらまず最初にstartReloadメソッドの所へ飛ぶことを設定します。
startReloadメソッドの中にXMLParserのデータ(URL)を用意し、インスタンスを生成します。
さらにリフレッシュした時に呼び出されるrefreshメソッドを加えます。
- (void)viewDidLoad {
[super viewDidLoad];
//起動したら最初にstartReloadの所へ飛ぶ
[self startReload];
//リフレッシュ設定
_refreshControl = [[UIRefreshControl alloc] init];
[_refreshControl addTarget:self action:@selector(refresh) forControlEvents:UIControlEventValueChanged];//詳細はrefreshで設定
[self.tableView1 addSubview:_refreshControl];
}
#pragma mark - リフレッシュコントロール
-(void)startReload
{
//URLを指定してXMLパーサーを作る
// 一旦配列の中を削除する
if (self.newsArr) {
[self.newsArr removeAllObjects];
}
//フラグを設定して一つ目の情報を無視
titleIgnoreFlag = YES;
urlIgnoreFlag = YES;
dateIgnoreFlag = YES;
NSURL *myURL = [NSURL URLWithString:@"http://newsbiz.yahoo.co.jp/industry/fince.rss"];
NSXMLParser *myParser = [[NSXMLParser alloc] initWithContentsOfURL:myURL];
myParser.delegate = self;
//解析を開始
[myParser parse];
}
-(void)refresh
{
NSLog(@"refresh!");
[self startReload];
}
XMLを読み込む (XMLPaeser)
NSXMLParserはXMLデータを読み込む際に、下記のメソッドを呼び出します。
・解析開始時(parserDidStartDocument:メソッド)
・開始タグを読み込んだ時(parser didStartElement:メソッド)
・閉じタグを読み込んだ時(parser didEndElement:メソッド)
・タグ以外のテキストを読み込んだ時(parser foundCharacters:メソッド)
・解析終了時(parserDidEndDocument:メソッド)
また、NSDictionaryという辞書を作成し、読み込んだデータのタイトル・URL・日付を
それぞれ文字列に入れて辞書に格納します。その時、文字列にはforKeyという鍵を付けます。
その辞書をnewsArrという配列に格納することでセルに表示することができます。
#pragma mark XMLパーサー
//XMLパース開始時のメソッド
-(void)parserDidStartDocument:(NSXMLParser *)parser {
//"nowTagStr"を初期化
nowTagStr = @"";
}
//開始タグを読み込んだ時のメソッド
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
if ([elementName isEqualToString:@"title"]) {
nowTagStr = elementName; //解析タグをelementNameに設定
txtBuffer = @""; //テキストバッファの初期化
} else if ([elementName isEqualToString:@"link"]) {
nowTagStr = elementName;
txtBuffer = @"";
} else if ([elementName isEqualToString:@"pubDate"]) {
nowTagStr = elementName;
txtBuffer = @"";
}
}
//タグ以外のテキストを読み込んだ時のメソッド
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if ([nowTagStr isEqualToString:@"title"]) {
txtBuffer = string;
} else if ([nowTagStr isEqualToString:@"link"]) {
txtBuffer = string;
} else if ([nowTagStr isEqualToString:@"pubDate"]) {
txtBuffer = string;
}
}
//閉じタグを読み込んだ時のメソッド
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if ([elementName isEqualToString:@"title"]){
if (!titleIgnoreFlag){ //もし"titleIgnoreFlag"がNOなら
//"txtBuffer"のデータを"titleString"に追加
self.titleString = txtBuffer;
}
titleIgnoreFlag = NO;
} else if ([elementName isEqualToString:@"link"]) {
if (!urlIgnoreFlag){
// urlを代入
self.urlString = txtBuffer;
}
urlIgnoreFlag = NO;
} else if ([elementName isEqualToString:@"pubDate"]) {
// 日付をちゃんと表示できるように変更する。
if (!dateIgnoreFlag) {
NSDateFormatter *inputDF = [[NSDateFormatter alloc] init]; // 1."inputDF"の作成(中継役)
[inputDF setDateFormat:@"EEE, dd MMM yyyy HH:mm:ss Z"]; // 2.フォーマットの設定("txtBuffer"の表示形式と同じ)
[inputDF setLocale:[[NSLocale alloc]initWithLocaleIdentifier:@"ENGLISH"]]; // 3.ロケール(地域指定)の設定(英語)
NSDate *inputDate = [inputDF dateFromString:txtBuffer]; // 4."txtBuffer"を"inputDF"を介して"inputDate"に変更(文字列->日付型)
[inputDF setDateFormat:@"yyyy/MM/dd/ HH:mm"]; // 5.日付を yyyy/MM/dd hh:mm:ss形式に変更
NSString *dString = [inputDF stringFromDate:inputDate]; // 6."inputDate"を"inputDF"を介して"dString"に格納(日付型->文字列)
self.dateString = dString; //7."dString"を"dateString"に代入
//辞書を作成し、タイトル・URL・日付を格納
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
[dic setObject:self.titleString forKey:@"title"];
[dic setObject:self.urlString forKey:@"url"];
[dic setObject:self.dateString forKey:@"date"];
[self.newsArr addObject:dic];
}
dateIgnoreFlag= NO;
}
}
//XMLパース終了時のメソッド
-(void)parserDidEndDocument:(NSXMLParser *)parser {
NSLog(@"self.newsArr %@",self.newsArr);
[self.tableView1 reloadData];
[_refreshControl endRefreshing];
}
ビルド(実行)
ここまで出来たら一回ビルド(実行)してみましょう。


こんな感じになりました。
ニュースを表示しているセルを下にスワイプするとニュースを更新することができます。
第2回まとめ
今回はここまでです。
これでRSSなどのXMLの読み込み、refreshControlができるようになりました。
このとおりやってもうまくいかない方は、アプリ開発スクール「クラウドナインアップス」へお気軽にご相談ください。
このとおりやってもうまくいかない方は、アプリ開発スクール「クラウドナインアップス」へお気軽にご相談ください。
次回はWebViewとGitHubについて説明します。お楽しみに!
〜#3へ続く〜







