前回更新からだいぶ日が経ってしまいましたが、めげずに更新を続けます。

今回は「テーブルビューコントロール(UITableViewController)」を追加し、ZIPファイルの一覧を表示します。テーブルビューというのは簡単にいえば「表」のことです。iPodのプレイリスト一覧などに使われているものですね。

iOSのテーブルビューの使い方は、他のプラットフォームのものと結構違います。他ではテーブル用のオブジェクトを作成し、そこにアイテムを追加していって、後のことはおまかせというものが多いと思うのですが、iOSのテーブルビューでは……

  • numberOfSectionsInTableViewメソッドが呼び出されたら、セクションの数を返す
  • numberOfRowsInSectionメソッドが呼び出されたら、現在のセクションの行数を返す
  • cellForRowAtIndexPathメソッドが呼び出されたら、セルに表示したい文字列を返す

といった具合に表示も自分でやってあげなければいけません。


■UITableViewControllerのサブクラスを作成する

UITableViewControllerクラスを継承したクラスを作成し、そこに独自のコードを入力します。このクラスはテンプレートを使って作成します。手入力で作ろうとするとオーバーライドしなければいけないメソッドが多くて大変です。

「ファイル」メニューから「新規ファイル」を選択します。「Cocoa Touch Class」「UIView Controller subclass」を選び、「UITableViewController subclass」「With XIB for user interface」をオンにして「次へ」をクリックします。

20100920-iphonesdk (14)

「With XIB~」をオンにしておくと、Interface Builder用のファイルも同時に作ってくれるわけです。

次にサブクラスのファイル名を入力します。ここでは「FileListTableViewController.m」とします。「同時に~.hも作成」をチェックしておき、「完了」をクリックします。

20100920-iphonesdk (13)

プロジェクトに3つのファイルが追加されました。

保存フォルダを指定していなかったので、ドラッグして「iPhone」フォルダに移動しています。

20100920-iphonesdk (12)

■テーブルビューコントローラをナビゲーションの最初のビューにする

Interface Builderを起動し、作成したFileListTableViewControllerを前回作成したナビゲーションコントローラの最初のビューに設定します。

XCodeで「FileListTableViewController.xib」をダブルクリックし、Interface Builderを起動します。すでにTableViewなどが配置済みになっています。これはこれ以上編集しません。

20100920-iphonesdk (10)

XCodeに戻り、前回作成した「MainWindow_iPhone.xib」をダブルクリックします。

20100920-iphonesdk (9)

開いたら、書類ウィンドウで「Navitation Controller」の下にある「View Controller」を選択します。

20100920-iphonesdk (8)

そのままInspectorウィンドウの「Identity」タブ(4つめのタブ)を選択し、「Class」から「FileListTableViewController」を選択します。

20100920-iphonesdk (7)

これでNavitation Contollerの最初のビューが「FileListTableViewController」になりました。

20100920-iphonesdk (6)

つまりアプリを起動すると、FileListTableViewControllerの画面が表示されるということです。

 

■テーブルビューにファイル名が表示されるようにする

続いて「FileListTableViewController.m」と「同.h」にコードを書き、アプリのドキュメントフォルダ内にあるファイルを一覧表示できるようにします。

XCodeでFileListTableViewController.hを開き、「HetimaUnZip.h」をインポートします。

そして、ファイル名を記憶しておくためのNSMutableArray型のdirectoryArrayプロパティを宣言します。NSMutableArrayはObjective-Cの「編集可能な配列」のクラスです。要素の型指定はないのでどんなデータでも記憶することができます。Objective-Cの配列はあまり好評ではないらしいです。

最後に独自に定義するupdateFileListメソッドの宣言を書いておきます。このメソッドはファイル一覧を更新し、directoryArrayに記憶させます。

★FileListTableViewController.h

//

//  FileListTableViewController.h

//  MangaNaviUniversal
//
//  Created by リブロワークス on 10/09/20.
//  Copyright 2010 __MyCompanyName__. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "HetimaUnZip.h"

@interface FileListTableViewController : UITableViewController {
	//ファイル一覧
	NSMutableArray* directoryArray;
}

@property (nonatomic, copy, readonly) NSArray *directoryArray;

- (void)updateFileList;

@end

FileListTableViewController.mを編集します。まず、directoryArrayプロパティのシンセサイズを書きます。

最初のviewDidLoadメソッドは、ビューのインスタンスが作られたときに呼び出されるメソッドです。ここでNSMutableArrayのインスタンスを作成し、directoryArrayプロパティにセットしておきます。

次のviewWillAppearメソッドはビューが表示される直前に呼び出されるメソッドです。ここでupdateFileListメソッドを呼び出し、ファイル一覧を更新します。

★FileListTableViewController.m

#import "FileListTableViewController.h"

@implementation FileListTableViewController
@synthesize directoryArray;

#pragma mark -
#pragma mark View lifecycle

- (void)viewDidLoad {
	[super viewDidLoad];
	// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
	// self.navigationItem.rightBarButtonItem = self.editButtonItem;
	//ファイル一覧を記録するための配列を作成
	directoryArray = [[NSMutableArray alloc] init];
}

- (void)viewWillAppear:(BOOL)animated {
    	[super viewWillAppear:animated];
    	//ファイル一覧を更新
     	[self updateFileList];
}

少し下にスクロールして、テーブルにデータを表示する処理を書きます。

テーブルには「セクション」というグループが作れるのですが、まずその数をnumberOfSectionsInTableViewメソッドから問い合わせられるのでそれを応えます。今回は1を返します。

次にnumberOfRowsInSectionメソッドによってセクション内のセル数が問い合わせられます。引数sectionによってセクションのIDが渡されるので、その数を返します。今回はセクションは1つしかないのですが、念のためsectionが0(最初のセクション)のときだけ、directoryArrayのcountプロパティを使って配列の要素数を調べ、それを返します。

最後にcellForRowAtIndexPathメソッドによって、indexPathに指定したセルの内容を問い合わせられるので、それを返します。

#pragma mark -
#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.
	if(section == 0) return directoryArray.count;
	return0;
}

// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
	staticNSString *CellIdentifier = @"Cell";
	UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

	if (cell == nil) {
		cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
	}

	// Configure the cell...
	//ファイル名を表示
	if(indexPath.section == 0){
		NSString *name = [directoryArray objectAtIndex:indexPath.row];
		cell.textLabel.text = name;
	}
	return cell;
}

NSIndexPath型引数indexPathのsectionにセクションID、rowにセルIDが登録されているので、それに該当するファイル名をobjectAtIndexメソッドで調べます。

それを返値用に確保されているUITableViewCell型変数cellのtextLabel.textプロパティにセットします。

最後にファイル一覧を更新するupdateFileListメソッドの定義です。

//ドキュメントフォルダ内のZIPファイルの一覧を表示する
- (void)updateFileList{
	//ドキュメントフォルダの場所を取得
	NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
	NSString *docpath = [paths objectAtIndex:0];
	NSLog(@"%@", docpath);

	//ファイル一覧の取得
	NSFileManager *fileman = [NSFileManager defaultManager];
	NSError *error;

	[directoryArray removeAllObjects];
	NSArray *arr = [fileman contentsOfDirectoryAtPath:docpath error:&error];
	NSLog(@"arr = %@", arr);

	//ZIPファイルのみを登録
	for(NSString *item in arr){
		if([[[item pathExtension] lowercaseString] isEqualToString:@"zip"] == NO) continue;
		[directoryArray addObject:item];
		NSLog(@"addstring%@", item);
	}
}

まず、アプリのドキュメントフォルダの位置をNSSearchPathForDirectoriesInDomains関数で調べます。

次にファイル操作を行うNSFileManagerのインスタンスを取得します。

directoryArrayの要素をremoveAllObjectsメソッドで全削除し、NSFileManagerを使ってドキュメントフォルダ内の全ファイル名の一覧を取得して変数arrに記憶します。

その後はforループを使い、arrの要素で拡張子がzipであればdirectoryArrayに追加します。

これをビルドすると次のようにファイル一覧が表示されます。

20100920-iphonesdk (5)

ファイルを増やしたいときは、「ユーザー」→「ライブラリ」→「Application Support」→「iPhone Simulator」→「バージョン番号」→「Applications」→「アプリのGUID」→「Doucuments」フォルダの中に、jpegファイルを圧縮したzipファイルを入れてください。実際のアプリではiTunesのファイル共有を使ってコピーすることになります。

20100920-iphonesdk (4)

今回のソースコードは以下からダウンロードできます。なお、「samplebook.zip」は市販マンガをスキャンしたものなので除いています。前の記事のリソースファイルに関する話を参考に、自分で追加してください。

ソースコードのダウンロード


今回も余談です。前回から時間が経ちすぎてしまい、iOS SDKのバージョンが変わってしまいました。

おかげでビルド時にこんなエラーが……。

20100920-iphonesdk (2)

error:There is no SDK with the name or path ‘iphoneos4.0’

SDKを4.1用に更新したらパスが変わってしまったようですね。

「プロジェクト」メニューから「プロジェクト設定を編集」を選択し、プロジェクト設定の画面を表示します。

「ベースSDK」が「iOSデバイス4.0(見つかりません)」になっているので……

20100920-iphonesdk (17)

「iOSデバイス4.1」に変更します。

20100920-iphonesdk (16)