Nav(9)~Row Controls(2)

2011. 01. 08
●サンプルコードとの差異

Nav(8)~Row Controls(1)』の概要で触れましたが、旧版の本書と新版のサンプルコードではアクセサリとその処理が異なります。

1044

サンプルコードではスイッチの代わりにカスタムボタンが設置されており、行をタップした時とボタンをタップした時に異なるアラートが表示されます。

行をタップした場合)
1045

ボタンをタップした場合)
1046


●ヘッダファイルRowControlsController.hの修正

ヘッダファイルでは、ボタンがタップされた時の処理を行うアクションメソッドを追加します。
(太字が追加した部分)

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

#define kSwitchTag 100

@interface RowControlsController : SecondLevelViewController <UITableViewDelegate, UITableViewDataSource> {
    NSArray *list;
}

@property (nonatomic, retain) NSArray *list;

- (IBAction)buttonTapped:(id)sender;

@end

1047

セル内のアクセサリを識別するための定数kSwitchTagは使用しませんので、気になる方はコメントアウトや削除をして構いません。

アクションメソッドは戻り値の型をIBActionとしていますが、Interface Builderは使用せず、コードでボタンの設置および処理を行います。


●ソースファイルRowControlsController.mの修正

ソースファイルでは、アクションメソッドbuttonTapped:の実装と、アクセサリをスイッチからボタンに変更するためにtableView:cellForRowAtIndexPath:メソッドを、行選択時の処理を変更するためにtableView:didSelectRowAtIndexPath:メソッドを修正します。

1)アクションメソッドbuttonTapped:の実装

buttonTapped:は、各セル内にスイッチの代わりに設置するカスタムボタンに対応するアクションメソッドで、ボタンがタップされたことを示すアラートを表示します。
(太字が追加した部分)

#import "RowControlsController.h"

@implementation RowControlsController

@synthesize list;

- (IBAction)buttonTapped:(id)sender {
    UIButton *senderButton = (UIButton *)sender;
    UITableViewCell *buttonCell = (UITableViewCell *)[senderButton superview];
    NSUInteger buttonRow = [[self.tableView indexPathForCell:buttonCell] row];
    NSString *buttonTitle = [list objectAtIndex:buttonRow];
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"You tapped the button." 
                message:[NSString stringWithFormat:@"You tapped the button for %@.", buttonTitle] 
                delegate:nil 
                cancelButtonTitle:@"OK" 
                otherButtonTitles:nil];
    [alert show];
    [alert release];
}

1048

このアクションメソッドは、セルに設置されたボタンをタップした際に呼び出され、どのセルがタップされたかを示す情報を含むアラートを表示します。

そのため最初に呼び出し元であるボタンを引数senderから(UIButtonに型変換して)取得し、更にsuperviewプロパティでボタンのスーパービュー(親ビュー)であるセルbuttonCellを特定します。

次にbuttonCellを使って、テーブルビューからindexPathForCell:メソッドでインデックスパスを取得し、rowプロパティで行番号rowを得ます。

そしてセルのタイトルを、配列listからrowの文字列をobjectAtIndex:メソッドで取得します。

得られたタイトルbuttonTitleはstringWithFormat:メソッドでメッセージとして組み込み、initWithTitle:message:delegate:cancelButtonTitle:otherButtonTitles:メソッドでアラートを表示します。


superview

@property(nonatomic, readonly) UIView *superview

レシーバのスーパービュー、無い場合はnilになります。(読み込みのみ)


indexPathForCell:

- (NSIndexPath *)indexPathForCell:(UITableViewCell *)cell

指定したテーブルビューのセルのセクションと行を表すインデックスパスを返します。

戻り値はセルのセクションと行を表すインデックスパスで、インデックスパスが無効な場合はnilを返します。

cell:テーブルビューのセルを指定します。


stringWithFormat:

+ (id)stringWithFormat:(NSString *)format,...

指定したフォーマットで作った引数リストの文字列を返します。
formatがnilの場合、NSInvalidArgumentExceptionを呼び出します)

format:文字列の書式を指定します。nilを指定することはできません。

2)tableView:cellForRowAtIndexPath:の修正

tableView:cellForRowAtIndexPath:では、セルの初期化処理でスイッチの代わりにカスタムボタンを設置します。
(太字が追加・修正した部分)

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

    static NSString *ControlRowIdentifier = @"ControlRowIdentifier";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ControlRowIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ControlRowIdentifier] autorelease];
/*
        UISwitch *switchView = [[UISwitch alloc] init];
        switchView.tag = kSwitchTag;
        cell.accessoryView = switchView;
        [switchView release];
*/

        UIImage *buttonUpImage = [UIImage imageNamed:@"button_up.png"];
        UIImage *buttonDownImage = [UIImage imageNamed:@"button_down.png"];
        UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
        button.frame = CGRectMake(0.0, 0.0, buttonUpImage.size.width, buttonUpImage.size.height);
        [button setBackgroundImage:buttonUpImage forState:UIControlStateNormal];
        [button setBackgroundImage:buttonDownImage forState:UIControlStateHighlighted];
        [button setTitle:@"Tap" forState:UIControlStateNormal];
        [button addTarget:self action:@selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside];
        cell.accessoryView = button;

    }

    // Configure the cell...
    NSUInteger row = [indexPath row];
    NSString *rowTitle = [list objectAtIndex:row];
    cell.textLabel.text = rowTitle;
    return cell;
}

1049

最初にimageNamed:メソッドで、カスタムボタンの画像ファイルをUIImageオブジェクトにします。

次にbuttonWithType:でボタン(UIButtonオブジェクト)を生成しますが、スタイルでUIButtonTypeCustom(指定無し)を設定しているので、全てを自分で指定することになります。

まずボタンの位置とサイズをCGRectMake関数で作成し、frameプロパティで指定します。

ボタンのサイズは画像ファイルから読み込んだUIImageオブジェクトから、sizeプロパティおよびCGSize構造体(widthとheight)で指定します。

続いて最初にオブジェクト化した画像ファイルをボタンの背景画像としてsetBackgroundImage:forState:メソッドで指定します。

通常状態(UIControlStateNormal)はbuttonUpImage(button_up.png)、タップした時の状態(UIControlStateHighlighted)はbuttonDownImage(button_down.png)になります。

ボタンのタイトルはsetTitle:forState:で『Tap』と指定します。

addTarget:action:forControlEvents:はターゲットのアクションを指定する物で、ここではターゲットをボタン自身にし、ボタンの内側でタッチアップされた時(UIControlEventTouchUpInside)、アクションとして前述のbuttonTapped:メソッドを呼び出します。

最後にaccessoryViewプロパティで、セルのアクセサリとしてボタンを追加しています。

旧版の本書では、後の改変への耐性を付けるためにスイッチにタグを付けて識別していましたが、サンプルコードではタグを使用せず単純にアクセサリとして追加しています。


addTarget:action:forControlEvents:

- (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents

ディスパッチテーブルの内部に特定のイベントのためのターゲットとアクションを追加します。

このメソッドは複数回呼び出すことができ、特定のイベントのために複数のターゲットとアクションのペアを指定することができます。

アクションメッセージに応じて、その順序でパラメータとしてセンダーとイベントをオプションで含めることができます。

target:アクションメッセージが送信されるオブジェクトを指定します。
nilの場合、レスポンダチェーンはアクションメッセージに応答できるオブジェクトを検索します。

action:アクションメッセージを識別するセレクタを指定します。
NULLにすることはできません。

controlEvents:アクションメッセージが送信されるコントロールイベントを、ビットマスクで指定します。
ビットマスク定数は『Control Events』を参照してください。

3)tableView:didSelectRowAtIndexPath:の修正

tableView:didSelectRowAtIndexPath:では、行選択時にアラートを表示する点は変わりませんが、アクセサリがスイッチからボタンに変更されて、『スイッチの状態取得 → メッセージ文字列の生成と結合』という処理が不要になり、単純にセルのタイトルをメッセージに加えたものとなっています。
(太字が追加・修正した部分)

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    NSUInteger row = [indexPath row];
/*
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
    UISwitch *switchView = (UISwitch *)[cell viewWithTag:kSwitchTag];
    NSString *baseString = @"%@ %@.";
    NSString *onString = (switchView.on) ? @"is ON" : @"is not ON";
    NSString *familiarSpirit = [list objectAtIndex:row];
    NSString *messageString = [[NSString alloc] initWithFormat:baseString, familiarSpirit, onString];
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Row Selected." message:messageString delegate:nil cancelButtonTitle:@"Thanks!" otherButtonTitles:nil];
*/

    NSString *rowTitle = [list objectAtIndex:row];
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"You tapped the row."
                message:[NSString stringWithFormat:@"You tapped %@.", rowTitle]
                delegate:nil
                cancelButtonTitle:@"OK"
                otherButtonTitles:nil];

    [alert show];
    [alert release];
//  [messageString release];
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
}

1050

引数のインデックスパスからrowプロパティで行番号を取得する部分はそのままです。

配列listからobjectAtIndex:メソッドで行番号のタイトルを取得する部分は元にもありますが、説明時の見易さを考えて改めて記述しています。

取得したタイトルをメッセージに組み込み、initWithTitle:message:delegate:cancelButtonTitle:otherButtonTitles:メソッドでアラートを表示します。

最後にdeselectRowAtIndexPath:animated:で行の選択状態の解除が追加されています。



参考文献

UIView Class Reference

UITableView Class Reference

NSString Class Reference

UIButton Class Reference

UIImage Class Reference

UIControl Class Reference

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

商品詳細を見る






QuietControl 30 wireless headphones
0 Comments
Leave a comment
管理者にだけ表示を許可する
Top
0 Trackbacks
Top
Calendar
04 | 2017/05 | 06
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 31 - - -
Recent Articles
iTunes


Swift
Categories
Tips
Profile

水月杏香

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

Wish List
WACOM


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

QuietControl 30 wireless headphones
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