A.N.Variation

Affected Next Variation

Objective-CでRSS機能を使った『まとめサイトアプリ』の作り方④


こんにちは、iPhoneアプリ開発者の中川です。
前回までは、PHPでXMLファイルを出力して、XcodeでのMainStoryboardの設定まで解説しました。

Objective-CでRSS機能を使った『まとめサイトアプリ』の作り方①
Objective-CでRSS機能を使った『まとめサイトアプリ』の作り方②
Objective-CでRSS機能を使った『まとめサイトアプリ』の作り方③

いよいよ、プログラムの実装です。まとめブログの新着順を解析するプログラムです。
TableViewControllerはsintyakuTableViewControllerクラス、
ViewControllerはDetailsintyakuViewControllerクラスとしています。

sintyakuTableViewController.h
—————————————————————
@interface sintyakuTableViewController : UITableViewController<NSXMLParserDelegate,UITableViewDelegate>
– (IBAction)refrechTitle:(id)sender;

// XMLを解析して、必要な情報の配列を返すメソッド
-(NSMutableArray *) loadXML: (NSString *) urlstring;

@end
—————————————————————

sintyakuTableViewController.m
—————————————————————
#import “sintyakuTableViewController.h”
#import “DetailSintyakuViewController.h”
#import “SmartCell.h”

@interface sintyakuTableViewController (){
NSMutableArray* _xmlInfo;
NSString* urlRSS;
NSArray* bookmarkInfo;
}

@end

@implementation sintyakuTableViewController{
// タグ内の要素を格納する配列
NSMutableArray* titleArray;
NSMutableArray* blog_titleArray;
NSMutableArray* dateArray;
NSMutableArray* linkArray;
// XMLのタグ要素チェック
BOOL itemElementCheck;
BOOL titleElementCheck;
BOOL blog_titleElementCheck;
BOOL dateElementCheck;
BOOL linkElementCheck;

// 要素を出力するテキスト
NSString* titleText;
NSString* blog_titleText;
NSString* dateText;
NSString* linkText;

// ブックマークに使う配列
NSMutableArray *bookmarkInfo_b;
BOOL tyoufuku;
}

– (void)viewDidLoad
{
[super viewDidLoad];

self.tableView.separatorColor = [UIColor yellowColor];
self.navigationController.navigationBar.tintColor = [UIColor colorWithRed:0 green:0.89 blue:0.7 alpha:1];
self.navigationController.navigationBar.titleTextAttributes = @{NSForegroundColorAttributeName: [UIColor grayColor]};
self.tableView.rowHeight = 60;

urlRSS = @”PHPで出力したファイルのURL”;

_xmlInfo = [NSMutableArray array];
[_xmlInfo setArray:[self loadXML:urlRSS]];

self.title = @”新着”;

// カスタムセル設定
[self.tableView registerNib:[UINib nibWithNibName:@”SmartCell” bundle:nil] forCellReuseIdentifier:@”Cell”];
}

// XMLを読込み解析するメソッド
– (NSMutableArray *)loadXML:(NSString *)urlstring{
// 変数の初期化
// 格納する配列
titleArray = [NSMutableArray array];
blog_titleArray = [NSMutableArray array];
dateArray = [NSMutableArray array];
linkArray = [NSMutableArray array];
// 要素チェック
itemElementCheck = NO;
titleElementCheck = NO;
blog_titleElementCheck = NO;
dateElementCheck = NO;
linkElementCheck = NO;
// 要素
titleText = @””;
blog_titleText = @””;
dateText = @””;
linkText = @””;

// URLを作成
NSURL* url = [NSURL URLWithString:urlstring];
// urlからパーサーを作成。
NSXMLParser* parser = [[NSXMLParser alloc]initWithContentsOfURL:url];

// デリゲートをセット
[parser setDelegate:self];

// XMLを解析
[parser parse];

// 配列の一部のタイトル配列を返す
return titleArray;
}

#pragma mark – Table view data source

– (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}

– (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return _xmlInfo.count;
}

– (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString* cellIdentifier = @”Cell”;
SmartCell* cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell = [[SmartCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}

NSData* data = _xmlInfo[indexPath.row];
cell.titleLabel.text = [data description];
cell.titleLabel.font = [UIFont boldSystemFontOfSize:15];
cell.titleLabel.textColor = [UIColor brownColor];

cell.dateLabel.text = dateArray[indexPath.row];
cell.dateLabel.font = [UIFont systemFontOfSize:8];
cell.dateLabel.textColor = [UIColor greenColor];

cell.blog_titleLabel.text = blog_titleArray[indexPath.row];
cell.blog_titleLabel.font = [UIFont systemFontOfSize:8];
cell.blog_titleLabel.textColor = [UIColor redColor];

// セルにブックマークボタンをつける。
UIImage* buttonImage = [UIImage imageNamed:@”bookmarkButton.png”];
[cell.button addTarget:self action:@selector(tapButton:) forControlEvents:UIControlEventTouchUpInside];
[cell.button setTag:indexPath.row];
[cell.button setTitle:@”” forState:UIControlStateNormal];
[cell.button setBackgroundImage:buttonImage forState:UIControlStateNormal];
[cell.button.titleLabel setFont:[UIFont systemFontOfSize:10]];

return cell;
}

// ブックマークボタンがタップされたときのアクション

-(void)tapButton:(id)sender{
UIButton *button = (UIButton *)sender;
int row = button.tag;
NSLog(@”%d”,row);
bookmarkInfo = [NSArray array];
bookmarkInfo = @[titleArray[row],blog_titleArray[row],dateArray[row],linkArray[row]];
NSLog(@”%@”,bookmarkInfo[0]);

// ブックマークに格納するための配列を準備
bookmarkInfo_b = [NSMutableArray array];
// NSUserDefaultsのインスタンスを生成。
NSUserDefaults* defaultsB2 = [NSUserDefaults standardUserDefaults];

// ブックマーク登録されたブログデータを取得
NSData* d = [defaultsB2 dataForKey:@”keyBookMark”];
if (d) {
NSMutableArray *Array = [NSKeyedUnarchiver unarchiveObjectWithData:d];
bookmarkInfo_b = [NSMutableArray arrayWithArray:Array];

// タイトルの重複チェック

for (int i = 0; i < bookmarkInfo_b.count; i++)
{
if ([bookmarkInfo_b[i] isEqualToString:titleArray[row]])
{
tyoufuku = YES;
NSLog(@”タイトルが重複しています。”);
}
}
if (!tyoufuku)
{
NSLog(@”タイトルの重複ないよ!”);
[bookmarkInfo_b addObjectsFromArray:bookmarkInfo];
}
NSLog(@”titleArray2[0]=%@”,bookmarkInfo_b[0]);
// アラートで知らせる。

// 生成と同時に各種設定も完了させる例
UIAlertView *alert =
[[UIAlertView alloc]
initWithTitle:nil
message:@”お気に入りに登録しました。”
delegate:nil
cancelButtonTitle:nil
otherButtonTitles:@”OK”, nil
];
[alert show];
}

// ブックマークに書き込む
NSUserDefaults* defaultsB = [NSUserDefaults standardUserDefaults];

NSData* dataB = [NSKeyedArchiver archivedDataWithRootObject:bookmarkInfo_b];

[defaultsB setObject:dataB forKey:@”keyBookMark”];

BOOL successful = [defaultsB synchronize];
if (successful) {
NSLog(@”データの保存成功!”);
}

// ブックマークを読み込んでプログラム内部で確認。この作業をすることで、保存が確定する。
NSUserDefaults* defaultsB3 = [NSUserDefaults standardUserDefaults];

// ブックマーク登録されたブログデータを取得
NSData* d3 = [defaultsB3 dataForKey:@”keyBookMark”];
if (d3) {
NSMutableArray *Array = [NSKeyedUnarchiver unarchiveObjectWithData:d];
bookmarkInfo_b = [NSMutableArray arrayWithArray:Array];
}

// ブックマークに登録したらボタンを消す。
button.alpha = 0;
}

// cellがタップされた時のアクションを表すメソッド ランキングに反映。
– (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
for (int i = 0; i < titleArray.count; i++) {
if (indexPath.row == i) {
// URL指定
NSURL *url = [NSURL URLWithString:@”ランキングに反映するためのPHPファイルのURL(このPHPファイルは解説していません。)“];
NSMutableURLRequest *req = [[NSMutableURLRequest alloc] initWithURL:url];
// POST指定
req.HTTPMethod = @”POST”;
// BODYに登録、設定
NSString *body = [NSString stringWithFormat:@”a=%@&b=%@”, titleArray[i], linkArray[i]];
req.HTTPBody = [body dataUsingEncoding:NSUTF8StringEncoding];

CGRect rc = [[UIScreen mainScreen] applicationFrame];
UIWebView *web = [[UIWebView alloc] initWithFrame:CGRectMake( 0, 0, rc.size.width, rc.size.height )];
// リクエスト送信
[web loadRequest:req];
// 画面に表示
[self.view addSubview:web];
web.alpha = 0;

NSLog(@”%@”, titleArray[i]);
}
}
// カスタムセルを利用した場合セグエ設定はここでする。
[self performSegueWithIdentifier:@”showDetail” sender:self.tableView];
}

– (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}

– (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
[_xmlInfo removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
} else if (editingStyle == UITableViewCellEditingStyleInsert) {

}
}

// セグエ遷移する前の準備
– (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([[segue identifier] isEqualToString:@”showDetail”]) {
// rowの中身を選択されたrowに設定
NSIndexPath* indexPath = [self.tableView indexPathForSelectedRow];

// 選択されたリンク先を変数rowの中身にセット
NSString* link = linkArray[indexPath.row];
[[segue destinationViewController] setDetailItem:link];
}
}

#pragma mark – Table view delegate

– (IBAction)refrechTitle:(id)sender {
// テーブルを再読み込み
[self.tableView reloadData];
}

// 開始タグの処理
– (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
// item要素のチェック
if ([elementName isEqualToString:@”item”]) {
itemElementCheck = YES;
}

// title要素のチェック
if (itemElementCheck && [elementName isEqualToString:@”title”]) {
titleElementCheck = YES;
} else {
titleElementCheck = NO;
}

// blog_title要素チェック
if (itemElementCheck && [elementName isEqualToString:@”blog_title”]) {
blog_titleElementCheck = YES;
} else {
blog_titleElementCheck = NO;
}

// date要素のチェック
if (itemElementCheck && [elementName isEqualToString:@”date”]) {
dateElementCheck = YES;
} else {
dateElementCheck = NO;
}

// link要素のチェック
if (itemElementCheck && [elementName isEqualToString:@”link”]) {
linkElementCheck = YES;
} else {
linkElementCheck = NO;
}
}

// 終了タグの処理
– (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
// item要素のチェック
if ([elementName isEqualToString:@”item”]) {
itemElementCheck = NO;
}

// title要素のチェック
if ([elementName isEqualToString:@”title”]) {
if (titleElementCheck) {
// 配列titleArrayに追加。
[titleArray addObject:titleText];
}
titleElementCheck = NO;
titleText = @””;
}

// blog_title要素のチェック
if ([elementName isEqualToString:@”blog_title”]) {
if (blog_titleElementCheck) {
// 配列blog_titleArrayに追加。
[blog_titleArray addObject:blog_titleText];
}
blog_titleElementCheck = NO;
blog_titleText = @””;
}

// date要素のチェック
if ([elementName isEqualToString:@”date”]) {
if (dateElementCheck) {
// 配列dateArrayに追加。
[dateArray addObject:dateText];
}
dateElementCheck = NO;
dateText = @””;
}

// link要素のチェック
if ([elementName isEqualToString:@”link”]) {
if (linkElementCheck) {
// 配列linkArrayに追加
[linkArray addObject:linkText];
}
// linkElementCheckをNO、linkTextを空にセット
linkElementCheck = NO;
linkText = @””;
}
}

// 要素の取り出し
– (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
// titleテキストの取り出し
if (titleElementCheck) {
titleText = [titleText stringByAppendingString:string];
}

// blog_titleテキストの取り出し
if (blog_titleElementCheck) {
blog_titleText = [blog_titleText stringByAppendingString:string];
}

// dateテキストの取り出し
if (dateElementCheck) {
dateText = [dateText stringByAppendingString:string];
}

// linkテキストの取り出し
if (linkElementCheck) {
linkText = [linkText stringByAppendingString:string];
}
}
@end
—————————————————————

DetailSintyakuViewController.h
—————————————————————

@interface DetailSintyakuViewController : UIViewController
@property (strong, nonatomic) id detailItem;
@property (weak, nonatomic) IBOutlet UIWebView *rssWeb;

@end
—————————————————————

DetailSintyakuViewController.m
—————————————————————
#import “DetailSintyakuViewController.h”

@interface DetailSintyakuViewController ()
– (void) updateInterface;

@end

@implementation DetailSintyakuViewController

– (void)setDetailItem:(id)newDetailItem
{
if (_detailItem != newDetailItem) {
_detailItem = newDetailItem;

// viewのアップデート
[self updateInterface];
}
}

– (void) updateInterface{
// 文字列からURLを作成
NSURL* url = [NSURL URLWithString:self.detailItem];
// リクエスト作成
NSURLRequest* request = [NSURLRequest requestWithURL:url];
// webページを表示
[_rssWeb loadRequest:request];
}

– (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}

– (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[self updateInterface];
}

– (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

@end
—————————————————————

以上でプログラム部分は終わりです。
もっとメソッドを駆使してすっきり書くことができると思いますので、あくまでこのプログラムは参考程度にしてください。

これでまとめブログの新着順を表すことができるようになると思います。
完全にプログラムを掲載したわけではありませんが、ここまで理解していただければあとはお好みのまとめブログを作ることができると思います。
また、ランキングや、ブックマーク、記事検索などの概念には触れていませんが、このブログではここまでで解説を終わりとします。もし希望が多数寄せられれば書こうとは思います。

ここまで長い記事を読んでいただきありがとうございます。
みなさまのRSSを駆使したまとめアプリの助けになれば幸いです。