Sections(1)~セクションとインデックス

2010. 11. 12
前回まではセクションが一つしかないセル要素のみのテーブルビューでしたが、今回はセクション(区切りとなる項目)を含んだテーブルビューを作成し、ついでにグループスタイルでの表示や右端に表示させるインデックスにも触れていきます。

928


●プロジェクトの作成

View-based Applicationテンプレートで、プロジェクト名を『Sections』とします。

923


●ビューコントローラのnibファイルの編集

nibファイルの編集は『Cells(1)~サブビューによるカスタマイズ』の時と同じです。

画面全体にテーブルビューを貼り付けます。

SectionsViewController.xibをダブルクリックしてInterface Builderで開き、LibraryウィンドウからViewウィンドウへTable Viewをドラッグ&ドロップします。

878

UITableViewオブジェクトはデータソースとデリゲートを持つ必要があります。

今回はデータソースもデリゲートもビューコントローラ(CellsViewController)で行うので、InspectorウィンドウのConnectionsタブを開き、『Outlets』の『dataSource』と『delegate』をDocumentウィンドウのFile's Ownerに接続します。

879

接続が完了したら保存してXcodeに戻ります。


●データのインポート

テーブルで表示するデータですが、今回は本書にある通りApress社のサイト内のサンプルコードからプロパティリストをコピーして使用します。

プロパティリストの作成方法については、『Pickers(6)~DependentComponentPicker(1)』や『スライドショーの画像配列をXML化』を参照してください。

ダウンロードしたサンプルコードの『Beginning iPhone Development Projects Oct 12 2009/08 Sections 1』下にある『sortednames.plist』ファイルを自身のプロジェクトにコピーし、XcodeのResourcesに追加します。

924

sortednames.plistは、アルファベット26文字をキーとする辞書で、各アルファベットには人名の配列が含まれています。


●ヘッダファイルの編集

SectionsViewController.hを開き、デリゲート(UITableViewDelegate)とデータソース(UITableViewDataSource)プロトコルを導入し、データソースとなる辞書namesと、配列要素を取り出すためのkeysを宣言します。
(太字が追加した部分)

#import <UIKit/UIKit.h>

@interface SectionsViewController : UIViewController <UITableViewDataSource, UITableViewDelegate> {
    NSDictionary *names;
    NSArray *keys;

}

@property (nonatomic, retain) NSDictionary *names;
@property (nonatomic, retain) NSArray *keys;


@end


●ソースファイルの編集

SectionsViewController.mを開き、辞書namesと配列keys、データソースメソッドの実装を行います。
(太字が追加・変更した部分)

#import "SectionsViewController.h"

@implementation SectionsViewController

@synthesize names;
@synthesize keys;

#pragma mark -
#pragma mark UIViewController Methods


/*
// The designated initializer. Override to perform setup that is required before the view is loaded.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
        // Custom initialization
    }
    return self;
}
*/

/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
}
*/

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.

- (void)viewDidLoad {
    [super viewDidLoad];
    NSString *path = [[NSBundle mainBundle] pathForResource:@"sortednames" ofType:@"plist"];
    NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
    self.names = dict;
    [dict release];
    NSArray *array = [[names allKeys] sortedArrayUsingSelector:@selector(compare:)];
    self.keys = array;

}

// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}


- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.
}

- (void)viewDidUnload {
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;

    self.names = nil;
    self.keys = nil;
    [super viewDidUnload];

}

- (void)dealloc {
    [names release];
    [keys release];

    [super dealloc];
}

#pragma mark -
#pragma mark Table View Data Source Methods

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return [keys count];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    NSString *key = [keys objectAtIndex:section];
    NSArray *nameSection = [names objectForKey:key];
    return [nameSection count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSUInteger section = [indexPath section];
    NSUInteger row = [indexPath row];
    NSString *key = [keys objectAtIndex:section];
    NSArray *nameSection = [names objectForKey:key];
    static NSString *SectionsTableIdentifier = @"SectionsTableIdentifier";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SectionsTableIdentifier];

    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:SectionsTableIdentifier] autorelease];
    }
    cell.textLabel.text = [nameSection objectAtIndex:row];
    return cell;
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    NSString *key = [keys objectAtIndex:section];
    return key;
}


@end

927_

shouldAutorotateToInterfaceOrientation:メソッド(アプリケーションで有効なデバイスの向きを指定)はコメントアウトを解除しています。
(特に追記はしていません)

・viewDidLoad

最初にsortednames.plistファイルの読み込みを行います。

プロパティリストの読み込みは、mainBundleメソッドでアプリケーションバンドルの位置を取得し、pathForResource:ofType:メソッドでファイル名と拡張子を指定し、その位置をpathとしています。

そのパスを元にinitWithContentsOfFile:メソッドでプロパティリスト内のキーと値で、新規に辞書dictを生成します。

生成したdictの内容は辞書namesに移します。

次に辞書namesの全てのキーを取り出して配列arrayを作ります。

names辞書からallKeysメソッドで全てのキーを取得し、sortedArrayUsingSelector:メソッドで昇順で並べ替えます。
(セレクタにはcompare:メソッドを使用しています)

生成したarrayの内容は配列keysに移します。

sortedArrayUsingSelector:メソッドで並べ替えを行うのは、allKeyメソッドで取得した要素の順序は定義されていないためです。

また、辞書dictはすぐ解放しているのに配列arrayを解放していないのは、sortedArrayUsingSelector:メソッドで作られた配列はコピーされたオブジェクトではなくレシーバのnamesを参照しているためで、arrayを解放するとkeysは元データを辿る事ができず、アプリケーションは強制終了してしまうので注意してください。

・viewDidUnload

辞書namesと配列keysの所有権の放棄を追加しています

・dealloc

辞書namesと配列keysの解放を追加しています

・numberOfSectionsInTableView:

これまでと異なり、今回はアルファベット単位でセクションを分けたテーブルなので、numberOfSectionsInTableView:メソッドでセクション数を決定します。

セクション数はプロパティリストsortednames.plistのキーを抽出した配列keysの要素数をcountメソッドで返しています。

・tableView:numberOfRowsInSection:

各セクション毎の行数を返すので、まず配列keysに対しobjectAtIndex:メソッドで引数sectionに対応するキーを文字列で取得します。

取得した文字列keyを使い、辞書namesからobjectForKey:メソッドで該当するキーの配列(つまりアルファベットに対応する名前の入った配列)を取得し、その配列の要素数をcountメソッドで返しています。

・tableView:cellForRowAtIndexPath:

最初に引数indexPathからsectionとrowというプロパティを使って、セクションと行の位置を特定しています。

両プロパティはUITableView.hで定義されています。

// This category provides convenience methods to make it easier to use an NSIndexPath to represent a section and row
@interface NSIndexPath (UITableView)

+ (NSIndexPath *)indexPathForRow:(NSUInteger)row inSection:(NSUInteger)section;

@property(nonatomic,readonly) NSUInteger section;
@property(nonatomic,readonly) NSUInteger row;

@end

(このカテゴリは、セクションと行を表すNSIndexPathを簡単に使用できるように作られた便利なメソッドです)

sectionプロパティは、配列keysからobjectAtIndex:メソッドでセクション名を取得するのに使用し、辞書namesからobjectForKey:メソッドでそのセクション用の配列nameSectionを取得しています。

rowプロパティは、セクションの配列nameSectionからobjectAtIndex:メソッドでセルに表示する要素の取得に使用しています。

セル再利用時の識別子SectionsTableIdentifierを定義し、dequeueReusableCellWithIdentifier:メソッドで再利用可能なセルがあれば返す部分は前回と同じです。

if文内に記述されるセルの初回生成時の内容はテキストを表示するだけなのでシンプルで、initWithStyle:reuseIdentifier:で初期化しています。

本書中ではinitWithFrame:reuseIdentifier:メソッドを使用していますがiOS 3.0以降用に書き換えました。

その後のセル内容のテキストのプロパティも、同様にtextLabelプロパティに書き換えています。
(詳細は『Simple Table(1)~テキストの表示』の『●改良点』の項を参照してください)

・tableView:titleForHeaderInSection:

tableView:titleForHeaderInSection:メソッドは、セクションに表示するタイトルを文字列で指定するもので、ここではアルファベットとなる配列keysからobjectAtIndex:メソッドでセクションを指定して取得し、返しています。


●プレーンとグループ化

実行するとセクション付きのプレーンテーブルが表示されます。

928

これは、InspectorウィンドウのAtrributesタブで、『Table View』の『Style』を『Plain』に設定している場合です。

925

Interface BuilderでSectionsViewController.xibを開き、InspectorウィンドウのAtrributesタブで、『Table View』の『Style』を『Plain』から『Grouped』に変更するとグループ化されたテーブルになります。

929


●インデックスの追加

画面右端にインデックスを追加するには、データソースメソッドのsectionIndexTitlesForTableView:メソッドを使用します。

@endの前に以下のメソッドを追加します。

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
    return keys;
}

932

今回は単純にセクションのタイトルの配列keyを返しています。

930

本書でも触れていますが、『iOSヒューマンインターフェイスガイドライン』のp.149にある『Table View』で『(グループ化のスタイルにおいて)このTable Viewのスタイルは、インデックスを提供しません。』とありますが、グループスタイルでもインデックスを表示する事は可能です。

931

ただ実装自体は可能であっても、グループスタイルでインデックスを使用したアプリケーションを提出したら審査は弾かれると思われます。


sectionIndexTitlesForTableView:

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView

データソースにテーブルビューのセクションのタイトルを返すように尋ねます。

戻り値は、テーブルビュー内のセクションのタイトルとして提供される文字列で、テーブルビューの右側にインデックスのリストとして表示されます。

テーブルビューはプレーンスタイル(UITableViewStylePlain)である必要があります。

例えばアルファベットのリストを表示したい場合、AからZの文字列を含む配列を返します。

tableView:この情報を要求するテーブルビューオブジェクトを指定します。



参考文献

UITableViewDataSource Protocol Reference

はじめてのiPhone3プログラミングはじめてのiPhone3プログラミング
(2009/12/17)
Dave Mark、Jeff LaMarche 他

商品詳細を見る






コンパニオン20
0 Comments
Leave a comment
管理者にだけ表示を許可する
Top
0 Trackbacks
Top
Calendar
03 | 2017/04 | 05
Sun Mon Tue Wed Thu Fri Sat
- - - - - - 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 - - - - - -
Recent Articles
iTunes


Swift
Categories
Tips
Profile

水月杏香

Author:水月杏香
永遠の初心者プログラマ。

Wish List
WACOM


ARC
Technical Q&A
情報プロパティリストキー
Start Developing iOS Apps Today
BOSE

コンパニオン20
Reference
NSApplicationDelegateプロトコル
NSArrayクラス
NSAutoreleasePoolクラス
NSBundleクラス
NSBundle UIKit追加分
NSCalendarクラス
NSCoderクラス
NSCodingプロトコル
NSCopyingプロトコル
NSDataクラス
NSDateクラス
NSDateFormatterクラス
NSDictionaryクラス
NSEntityDescriptionクラス
NSEnumeratorクラス
NSErrorクラス
NSExceptionクラス
NSFetchRequestクラス
NSFileHandleクラス
NSFileManagerクラス
NSIndexPathクラス
NSIndexPath UIKit追加分
NSKeyedArchiverクラス
NSKeyedUnarchiverクラス
NSKeyValueCodingプロトコル
NSLocaleクラス
NSManagedObjectクラス
NSManagedObjectContextクラス
NSManagedObjectModelクラス
NSMutableArrayクラス
NSMutableCopyingプロトコル
NSMutableDictionaryクラス
NSMutableSetクラス
NSNotificationクラス
NSNotificationCenterクラス
NSNullクラス
NSNumberクラス
NSObjectクラス
NSObject UIKit追加分
NSObjectプロトコル
NSPersistentStoreクラス
NSPersistentStoreCoordinatorクラス
NSPredicateクラス
NSPropertyListSerializationクラス
NSRunLoopクラス
NSSetクラス
NSStringクラス
NSString UIKit追加分
NSTimerクラス
NSTimeZoneクラス
NSURLクラス
NSURLProtectionSpaceクラス
NSURLRequestクラス
NSUserDefaultsクラス
NSValueクラス

UIActionSheetクラス
UIActionSheetDelegateプロトコル
UIActivityIndicatorViewクラス
UIAlertViewクラス
UIAlertViewDelegateプロトコル
UIApplicationクラス
UIApplicationDelegateプロトコル
UIBarButtonItemクラス
UIBarItemクラス
UIButtonクラス
UIColorクラス
UIControlクラス
UIDatePickerクラス
UIDeviceクラス
UIEventクラス
UIFontクラス
UIGestureRecognizerクラス
UIImageクラス
UIImageViewクラス
UIKit Function
UILabelクラス
UINavigationControllerクラス
UINavigationItemクラス
UIPickerViewクラス
UIPickerViewDataSourceプロトコル
UIPickerViewDelegateプロトコル
UIPinchGestureRecognizerクラス
UIResponderクラス
UIScreenクラス
UIScrollViewクラス
UISearchBarクラス
UISearchBarDelegateプロトコル
UISegmentedControlクラス
UISliderクラス
UISwipeGestureRecognizerクラス
UISwitchクラス
UITableViewクラス
UITableViewCellクラス
UITableViewControllerクラス
UITableViewDataSourceプロトコル
UITableViewDelegateプロトコル
UITapGestureRecognizerクラス
UITextFieldクラス
UITextFieldDelegateプロトコル
UITextInputTraitsプロトコル
UITextViewクラス
UITextViewDelegateプロトコル
UIToolbarクラス
UITouchクラス
UIViewクラス
UIViewControllerクラス
UIWebViewクラス
UIWebViewDelegateプロトコル
UIWindowクラス

AVAudioPlayerクラス
AVAudioPlayerDelegateプロトコル

CADisplayLinkクラス
CAEAGLLayerクラス
CALayerクラス

CGAffineTransform
CGBitmapContext
CGColor
CGColorSpace
CGContext
CGGeometry
CGImage
CGPath

EAGLContextクラス
EAGLDrawableプロトコル

Foundation Constants
Foundation Data Types
Foundation Functions

MPMediaItemクラス
MPMediaItemArtworkクラス
MPMediaPlaylistクラス
MPMediaPropertyPredicateクラス
MPMediaQueryクラス
MPMusicPlayerControllerクラス

Randomization Services

System Sound Services
Amazon


OpenGL ES
SQLite
Monthly Archives
Recent Comments
Recent TrackBacks
RSS Link
Visitors
QR Code
QR