Nav(5)~Disclosure Buttons(2)

2011. 01. 04
●サブビューDisclosure ButtonsのヘッダファイルDisclosureButtonController.hの編集

6つあるサブビューは全てSecondLevelViewControllerクラスを継承するテーブルビューコントローラになります。
(太字が追加・修正した部分)

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

@class DisclosureDetailController;


@interface DisclosureButtonController : SecondLevelViewController <UITableViewDelegate, UITableViewDataSource> {
    NSArray *list;
    DisclosureDetailController *childController;

}

@property (nonatomic, retain) NSArray *list;

@end

1022

SecondLevelViewControllerを継承するため、ヘッダファイルSecondLevelViewController.hのインポートとクラス宣言でスーパークラスをUITableViewControllerからSecondLevelViewControllerへの変更を行います。

それとApress社のサイト内のサンプルコードでは省略されていますが、テーブルを扱うので旧版の本書にあるようにUITableViewDelegateとUITableViewDataSourceプロトコルを採用します。

@classはコンパイラ指示子で、後に続く文字列がクラスであることを宣言します。

詳細ビューのDisclosureDetailControllerクラスを宣言しているのは、同クラスのインスタンス変数childControllerを宣言するためです。

ヘッダファイルDisclosureDetailController.hのインポートではなくクラス宣言にしているのは、(詳解 Objective-C 2.0によると)メソッドを利用せずインスタンス変数の宣言だけ行うので、ヘッダファイル全体をインポートする必要が無く、コンパイルを高速化できるからということです。

DisclosureDetailControllerクラスのメソッド(アクセサメソッドであるプロパティmessageとimageName)を利用するソースファイルDisclosureButtonController.mでは、クラス宣言ではなくヘッダファイルDisclosureDetailController.hのインポートを行っています。

配列のプロパティlistは、サブビューDisclosure Buttonsのテーブルに表示するリストを格納します。

DisclosureDetailControllerのインスタンスchildControllerは、サブビューから詳細ビューへのデータの受け渡しと、ナビゲーションコントローラへの詳細ビューのプッシュで利用します。


●サブビューDisclosure ButtonsのソースファイルDisclosureButtonController.mの編集

ソースファイルでは、表示するテーブルの作成と、行またはアクセサリをタップした際の処理を行います。
(太字が追加・修正した部分)

#import "DisclosureButtonController.h"
#import "DisclosureDetailController.h"

@implementation DisclosureButtonController

@synthesize list;

#pragma mark -
#pragma mark Initialization

- (id)initWithStyle:(UITableViewStyle)style {
    // Override initWithStyle: if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
    self = [super initWithStyle:style];
    if (self) {

        // Custom initialization.
    }
    return self;
}


#pragma mark -
#pragma mark View lifecycle

- (void)viewDidLoad {
    [super viewDidLoad];
    NSArray *array = [[NSArray alloc] initWithObjects:@"Yoshika Miyafuji", @"Mio Sakamoto",
    @"Minna-Dietlinde Wilcke", @"Lynette Bishop", @"Perrine-H.Clostermann",
    @"Erica Hartmann", @"Gertrud Barkhorn", @"Francesca Lucchini", @"Charlotte E Yeager",
    @"Eila Ilmatar Juutilainen", @"Sanya V.Litvyak", nil];
    self.list = array;
    [array release];

}

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


#pragma mark -
#pragma mark Table view data source

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    // Return the number of rows in the section.
    return [list count];
}

// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *DisclosureButtonCellIdentifier = @"DisclosureButtonCellIdentifier";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:DisclosureButtonCellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:DisclosureButtonCellIdentifier] autorelease];
    }

    // Configure the cell...
    NSUInteger row = [indexPath row];
    NSString *rowString = [list objectAtIndex:row];
    cell.textLabel.text = rowString;
    cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
    [rowString release];

    return cell;
}

#pragma mark -
#pragma mark Table view delegate

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Hey, do you see the disclosure button?"
    message:@"If you're trying to drill down, touch that instead" delegate:nil
    cancelButtonTitle:@"Won't happen again" otherButtonTitles:nil];
    [alert show];
    [alert release];

}

- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath {
    if (childController == nil)
        childController = [[DisclosureDetailController alloc] initWithNibName:@"DisclosureDetail" bundle:nil];

    NSUInteger row = [indexPath row];
    NSString *selectedWitch = [list objectAtIndex:row];
    NSString *detailMessage = [[NSString alloc] initWithFormat:@"You pressed the disclosure button for %@.", selectedWitch];
    NSString *name = [[NSString alloc] initWithFormat:@"%@.png", selectedWitch];
    childController.message = detailMessage;
    childController.imageName = name;
    childController.title = selectedWitch;
    [detailMessage release];
    [name release];
    [self.navigationController pushViewController:childController animated:YES];
}


#pragma mark -
#pragma mark Memory management

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

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

- (void)viewDidUnload {
    // Relinquish ownership of anything that can be recreated in viewDidLoad or on demand.
    // For example: self.myOutlet = nil;

    self.list = nil;
    childController = nil;

}

- (void)dealloc {
    [list release];
    [childController release];

    [super dealloc];
}

@end

1023

1)DisclosureDetailController.hのインポート

先述の通り詳細ビューのプロパティを使用するため、ヘッダファイルDisclosureDetailController.hのインポートを行います。

また旧版の本書にあるNavAppDelegate.hのインポートは、navigationControllerプロパティを使用するため不要になります。

2)プロパティlistの実装

サブビューDisclosure Buttonsでテーブルに表示する内容を設定する配列プロパティlistを実装します。

3)initWithStyle:の実装

旧版の本書では太字で示されていなく、サンプルコードでは省略されていますが、initWithStyle:メソッドのコメントアウトを解除してデフォルトのまま実装しています。

4)viewDidLoadの実装

viewDidLoadはコメントアウトを解除し、配列listを設定します。

一時配列arrayをinitWithObjects:で初期化し配列listに代入していますが、中身の文字列についは本書やサンプルコードとは異なります。
(注:詳細ビューで使用する画像ファイルと同じ名前を設定しています)

本書やサンプルコードではスーパークラスでの初期化を最後に行っていますが、ここでは最初に行っています。

5)不要なView lifecycleのメソッド

viewWillAppear:、viewDidAppear:、viewWillDisappear:、viewDidDisappear:の4つは今回使用しないので削除します。

6)shouldAutorotateToInterfaceOrientation:の実装

本書やサンプルコードでは触れられていませんが、shouldAutorotateToInterfaceOrientation:のコメントアウトを解除してデフォルトの状態(ポートレートのみ有効)で実装しています。

7)numberOfSectionsInTableView:の削除

セクションが一つしか無いので、numberOfSectionsInTableView:は不要のため削除します。

8)tableView:numberOfRowsInSection:の実装

セクションの行数として、tableView:numberOfRowsInSection:ではサブビューの配列listの要素数をcountメソッドで返します。

9)tableView:cellForRowAtIndexPath:の実装

tableView:cellForRowAtIndexPath:では、サブビューDisclosure Buttonsのテーブルセルの内容を設定します。

旧版の本書ではこの後にtableView:accessoryTypeForRowWithIndexPath:メソッドでアクセサリの設定を行っていますが、同メソッドはiOS 3.0以降で非推奨になっているため、サンプルコードと同様にtableView:cellForRowAtIndexPath:メソッド内でaccessoryTypeプロパティを使用して設定します。

再利用識別子は『DisclosureButtonCellIdentifier』と設定しています。

if文内のinitWithFrame:reuseIdentifier:メソッドはiOS 3.0以降非推奨なので、自動生成されるinitWithStyle:reuseIdentifier:で初期化しています。

セルの構成は、最初にインデックスパスからrowプロパティで行番号を取得します。

次に配列listから当該行の文字列をobjectAtIndex:メソッドで取得します。

旧版の本書ではテキストの取得にtextプロパティを使用していますが、iOS 3.0以降は非推奨なので、代わりにtextLabeltextプロパティを使用しています。

アクセサリは前述のaccessoryTypeプロパティで、詳細なコンテンツを表すUITableViewCellAccessoryDetailDisclosureButton(青い丸内に白い『>』)を設定します。

10)不要なTable view data sourceメソッド

Table view data sourceのtableView:canEditRowAtIndexPath:tableView:commitEditingStyle:forRowAtIndexPath:tableView:moveRowAtIndexPath:toIndexPath:tableView:canMoveRowAtIndexPath:の4つは今回使用しないので削除します。

11)tableView:didSelectRowAtIndexPath:の実装

tableView:didSelectRowAtIndexPath:では、サブビューDisclosure Buttonsでのテーブルの行をタップした際にアラートを表示します。

アラートの設定はinitWithTitle:message:delegate:cancelButtonTitle:otherButtonTitles:メソッドを用いており、固定文なのでどの行を選択しても同じ文面となります。

12)tableView:accessoryButtonTappedForRowWithIndexPath:の実装

デリゲートメソッドtableView:accessoryButtonTappedForRowWithIndexPath:は自動生成されないので手動で追加します。

このメソッドはセルの左側に表示されるアクセサリボタンがタップされた際の挙動を記述するメソッドで、ここでは詳細ビューへ選択行の情報を受け渡すと共に、ナビゲーションコントローラへ詳細ビューのプッシュを行っています。

最初に詳細ビューDisclosureDetailControllerクラスのインスタンスchildControllerが存在するかを判定し、無ければinitWithNibName:bundle:でnibファイルDisclosureDetail.xibから作成します。

この後、本書やサンプルコードでは『childController.title = @"Disclosure Button Pressed";』で詳細ビューのタイトルを設定しているのですが、その後でもう一度タイトルを設定しているので、この行は不要と思い削除しています。

次にインデックスパスからrowプロパティで行番号を取得し、配列listから当該行の文字列をobjectAtIndex:メソッドで取得します。
(取得した文字列の変数名を『selectedMovie』から『selectedWitch』に変更しています)

詳細ビューへ渡す情報は2つあり、ラベルに表示するための選択行の文字列を含む文detailMessageと、表示するための選択行の画像ファイル名nameを、initWithFormat:メソッドで作成します。

そして両文字列をDisclosureDetailControllerのプロパティmessageとimageNameにそれぞれ渡します。

詳細ビューのタイトルは、titleプロパティで選択した行の文字列selectedWitchを設定しています。

最後にnavigationControllerプロパティにpushViewController:animated:メソッドで詳細ビューchildControllerをプッシュし、詳細ビューへ移行します。


tableView:accessoryButtonTappedForRowWithIndexPath:

- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath

指定した行に関連付けされたアクセサリ(ディスクロージャ)ビューをユーザがタップした際にデリゲートに伝えます。

デリゲートは通常、ディスクロージャボタン(アクセサリビュー)のタップに応答して、選択された行に関連付けられている新しいビューを表示します。

このメソッドは、indexPathの示す行にアクセサリビューが設定されていない時は呼び出されません。

tableView:イベント情報を伝えるデリゲートのテーブルビューオブジェクトを指定します。

indexPath:tableViewの行の位置を示すインデックスパスを指定します。

13)viewDidUnloadの実装

旧版の本書ではviewDidUnloadは記述されていません。

サンプルコードではプロパティlistだけでなく、インスタンス変数childControllerの所有権放棄も行っているのですが、所有権放棄の直前にreleaseで解放を行っており、その理由はよく分かりません。

deallocでchildControllerの解放を行っていますし、所有権放棄の前に解放してしまうというのも問題がありそうなので、ここでは解放は行わず所有権放棄のみ行っています。

14)deallocの実装

deallocでは本書やサンプルコードと同じく、プロパティlistとインスタンス変数childControllerの解放を行っています。



参考文献

UITableViewDelegate Protocol Reference

詳解 Objective-C 2.0 第3版詳解 Objective-C 2.0 第3版
(2011/12/28)
荻原 剛志

商品詳細を見る

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

商品詳細を見る






Lifestyle 650 home entertainment system
0 Comments
Leave a comment
管理者にだけ表示を許可する
Top
0 Trackbacks
Top
Calendar
10 | 2017/11 | 12
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

Lifestyle 650 home entertainment system
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