Nav(11)~Move Me(2)

2011. 01. 10
●サブビューMove MeのソースファイルMoveMeController.mの編集

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

#import "MoveMeController.h"

@implementation MoveMeController

@synthesize list;

- (IBAction)toggleMove {
    [self.tableView setEditing:!self.tableView.editing animated:YES];
}


#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];
    NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:@"(14)Yoshika Miyafuji",
    @"(19)Mio Sakamoto", @"(18)Minna-Dietlinde Wilcke", @"(15)Lynette Bishop",
    @"(15)Perrine-H.Clostermann", @"(16)Erica Hartmann", @"(18)Gertrud Barkhorn",
    @"(12)Francesca Lucchini", @"(16)Charlotte E Yeager", @"(15)Eila Ilmatar Juutilainen",
    @"(13)Sanya V.Litvyak", nil];
    self.list = array;
    [array release];


    // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
    // self.navigationItem.rightBarButtonItem = self.editButtonItem;

    UIBarButtonItem *moveButton = [[UIBarButtonItem alloc] initWithTitle:@"Move"
    style:UIBarButtonItemStyleBordered target:self action:@selector(toggleMove)];
    self.navigationItem.rightBarButtonItem = moveButton;
    [moveButton 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 *MoveMeCellIdentifier = @"MoveMeCellIdentifier";

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

    // Configure the cell...
    NSUInteger row = [indexPath row];
    cell.textLabel.text = [list objectAtIndex:row];

    return cell;
}

// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
    NSUInteger fromRow = [fromIndexPath row];
    NSUInteger toRow = [toIndexPath row];
    id object = [[list objectAtIndex:fromRow] retain];
    [list removeObjectAtIndex:fromRow];
    [list insertObject:object atIndex:toRow];
    [object release];
}


// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
    // Return NO if you do not want the item to be re-orderable.
    return YES;
}


#pragma mark -
#pragma mark Table view delegate

- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
    return UITableViewCellEditingStyleNone;
}


#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;
}

- (void)dealloc {
    [list release];
    [super dealloc];
}

@end

1052

1)プロパティlistの実装

配列listプロパティを実装します。

2)アクションメソッドtoggleMoveの実装

toggleMoveメソッドは、ナビゲーションバー右側に設置するボタンをタップした際に呼び出され、テーブルビューの編集モードのON/OFF切り替えを行います。

テーブルビューに対しsetEditing:animated:で編集モードを切り替えるのですが、編集モードは現在のテーブルビューのモードをeditingプロパティで取得した値を否定することで、呼び出される度にON/OFFを切り替えています。


setEditing:animated:

- (void)setEditing:(BOOL)editing animated:(BOOL)animate

レシーバの編集モードを切り替えます。

editing値をYESに設定してこのメソッドを呼び出すと、テーブルビューは表示されている各UITableViewCellオブジェクトのsetEditing:animated:を呼び出して編集モードになります。

editing値をNOに設定してこのメソッドを呼び出すと編集モードがオフになります。

編集モードでは、セルの構成にも依りますが、テーブルの各セルの左側に挿入または削除のコントロール、右側に並べ替えのコントロールが表示されます。
(詳細は『UITableViewCellクラス』を参照してください)

テーブルビューのデータソースでは、tableView:canEditRowAtIndexPath:を実装することにより、セルを編集モードから除外する選択ができます。

editing:YESで編集モードになり、NOで解除されます。
デフォルト値はNOです。

animate:YESで編集モードになる際にトランジションアニメーションを行い、NOではすぐに移行します。


editing

@property(nonatomic, getter=isEditing) BOOL editing

レシーバが編集モードかどうかを示すブール値です。

このプロパティ値がYESの場合、テーブルビューは編集モードになり、セルの構成にも依りますが、テーブルの各セルの左側に挿入または削除のコントロール、右側に並べ替えのコントロールが表示されます。
(詳細は『UITableViewCellクラス』を参照してください)

コントロールをタップルすると、テーブルビューのデータソースメソッドtableView:commitEditingStyle:forRowAtIndexPath:が呼び出されます。

デフォルト値はNOです。

3)initWithStyle:の実装

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

4)viewDidLoadの実装

viewDidLoadはコメントアウトを解除し、配列listとナビゲーションバー右側に編集モード切り替え用のボタンを設定します。

一時配列arrayをinitWithObjects:で初期化し配列listに代入していますが、中身の文字列についは本書やサンプルコードとは異なります。

ナビゲーションバーへ追加するボタンはUIBarButtonItemのオブジェクトとしてボタンを作成し、ナビゲーションバーに組み込みます。

ボタンの生成・初期化はinitWithTitle:style:target:action:メソッドで、タイトルを『Move』、スタイルを境界線付き(UIBarButtonItemStyleBordered)、そしてアクションでtoggleMoveメソッドを呼び出す設定になっています。

作成したボタンは、navigationItemプロパティでバーの右側(rightBarButtonItemプロパティ)に設置します。

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


initWithTitle:style:target:action:

- (id)initWithTitle:(NSString *)title style:(UIBarButtonItemStyle)style target:(id)target action:(SEL)action

指定したタイトルとその他プロパティを使用した、新しいアイテムを生成して返します。

戻り値は指定したプロパティで新規に初期化されたアイテムです。

title:アイテムのタイトルを指定します。
nilを指定するとタイトルは表示されません。

style:アイテムのスタイルを指定します。
UIBarButtonItemStyleで定義されている定数の中から一つを指定します。

target:actionメッセージを受信するオブジェクトを指定します。

action:このアイテムを選択した時にtargetに送信するアクションを指定します。


UIBarButtonItemStyle

typedef enum {
    UIBarButtonItemStylePlain,
    UIBarButtonItemStyleBordered,
    UIBarButtonItemStyleDone,
} UIBarButtonItemStyle;

UIBarButtonItemStylePlain
タップすると点灯します。
デフォルトのアイテムスタイルです。

UIBarButtonItemStyleBordered
境界線を持つ単純なボタンスタイルです。

UIBarButtonItemStyleDone
『done(実行)』ボタンのスタイルです。
例えば、いくつかのタスクが完了したり、以前のビューに戻るボタンに使用します。


navigationItem

@property(nonatomic, readonly, retain) UINavigationItem *navigationItem

ナビゲーションアイテムは、ビューコントローラを表すために使用します。
(読み込みのみ)

これはナビゲーションバーにプッシュされた時に、ビューコントローラを表す独自のUINavigationItemのインスタンスを生成します。

このプロパティに最初にアクセスした時にUINavigationItemが生成されます。

したがって、ナビゲーションコントローラを使用しない場合は、このプロパティにアクセスしないでください。

ビューコントローラのビューでナビゲーションアイテムを生成する際に、バーボタンアイテムを生成して接続するのは避ける必要があります。

ビューコントローラのナビゲーションアイテムは、ビューコントローラのビューと独立させてください。

例えば、二つのビューコントローラを持つナビゲーションのスタックにプッシュした時、最上位のビューは表示されますが、他のビューコントローラのナビゲーションアイテムはbackボタンで戻らないと表示されません。

確実にナビゲーションアイテムを構成するには、このプロパティをオーバーライドし、バーボタンアイテムの読み込みにコードを追加するか、ビューコントローラの初期化コード内でアイテムを読み込んでください。


rightBarButtonItem

@property(nonatomic, retain) UIBarButtonItem *rightBarButtonItem

このアイテムが上表部のアイテムの時、ナビゲーションバーの右側にカスタムバーアイテムを表示します。

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:では、サブビューMove Meのテーブルセルの内容を設定します。

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

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

そしてshowsReorderControlプロパティで、全てのセルに並べ替えコントロールを表示するように設定しています。

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

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

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


showsReorderControl

@property(nonatomic) BOOL showsReorderControl

並べ替えコントロールをセルに表示するかを決定するブール値です。

並べ替えコントロールはグレーで、セルの右側に複数の水平なバーのコントロールです。

ユーザはこのコントロールをドラッグすることで、テーブル内のセルを並べ替えます。

デフォルト値はNOです。

この値がYESの場合、一時的に全てのアクセサリビューを並べ替えコントロールに置き換えます。

並べ替えコントロールを表示するには、このプロパティの設定だけではなく、UITableViewDataSourceメソッドのtableView:moveRowAtIndexPath:toIndexPath:を実装する必要があります。

加えて、データソースがtableView:canMoveRowAtIndexPath:がNOを返す実装をしている場合、その指定された行に並べ替えコントロールは表示されません。

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

tableView:canEditRowAtIndexPath:、tableView:commitEditingStyle:forRowAtIndexPath:の2つは今回使用しないので削除します。

11)tableView:moveRowAtIndexPath:toIndexPath:の実装

tableView:moveRowAtIndexPath:toIndexPath:はテーブルビューで行が移動された時に呼び出されるメソッドで、それに対してデータソースを対応させる処理を記述します。

コメントアウトを解除し、最初に引数fromIndexPathとtoIndexPathから、rowプロパティで移動元/先の行番号を取得します。

そして移動元の行にあるオブジェクトを、配列listからobjectAtIndex:メソッドで一時置き場objectに確保します。

この際retainで保持し、次のremoveObjectAtIndex:で移動元の行を削除した時にオブジェクトが解放されないようにします。

移動するオブジェクトを保持したら配列listからremoveObjectAtIndex:メソッドで移動元の行fromRowを削除し、insertObject:atIndex:メソッドで保持していたオブジェクトを移動先の行toRowへ挿入します。


tableView:moveRowAtIndexPath:toIndexPath:

- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath

データソースに、テーブルビュー内の別の場所となる指定した場所に行を移動するように伝えます。

fromRow内の並べ替えコントロールが押された時に、UITableViewオブジェクトはデータソースにこのメッセージを送信します。

tableView:このアクションを要求するテーブルビューを指定します。

fromIndexPath:tableView内にある移動する行の場所を示すインデックスパスを指定します。

toIndexPath:tableView内にある移動先の場所を示すインデックスパスを指定します。


removeObjectAtIndex:

- (void)removeObjectAtIndex:(NSUInteger)index

indexの場所にあるオブジェクトを削除します。

ギャップを埋めるため、index以降の全ての要素はインデックス番号がそれぞれ1が引かれて移動します。

index:配列内のオブジェクトを削除するためのインデックスを指定します。
この値は配列の範囲を超えて指定することはできません。
重要:配列の要素数を超えるindexを場合、NSRangeExceptionが発生します。


insertObject:atIndex:

- (void)insertObject:(id)anObject atIndex:(NSUInteger)index

指定したインデックスにある配列のコンテンツに、指定したオブジェクトを挿入します。

indexで示される場所が既に使用されている場合、indexの示す場所とそれ以降のオブジェクトはインデックス番号にそれぞれ1が加えられてシフトします。

NSArrayオブジェクトはC配列とは異なることに注意してください。

つまり、たとえ配列の生成時にサイズを指定しても、指定したサイズはヒントに過ぎず、実際の配列のサイズは0のままです。

これは配列の現在の要素数より大きいインデックスの場所に、オブジェクトを挿入することはできないことを意味します。

例えば、配列の要素数が2で2つのオブジェクトが含まれている場合、インデックス番号の0、1、2にオブジェクトを追加することができます。

インデックス番号3は範囲外の不正なものとなり、要素数2の配列にインデックス番号3でオブジェクトを追加しようとすると、NSMutableArrayは例外を発生させます。

anObject:配列のコンテンツに追加するオブジェクトを指定します。
この値はnilにすることはできません。
重要:anObjectがnilの場合、NSInvalidArgumentExceptionが発生します。

index:anObjectを挿入するための配列の場所となるインデックスを指定します。
この値は配列の要素数より大きい値を指定することはできません。
重要:配列の要素数を超えるindexを指定した場合、NSRangeExceptionが発生します。

12)tableView:canMoveRowAtIndexPath:の実装

tableView:canMoveRowAtIndexPath:は行が移動可能であるかどうかを指定するメソッドです。

今回はコメントアウトを解除し、(デフォルト実装の)無条件でYESを返して全ての行が移動可能であることを示します。

13)tableView:didSelectRowAtIndexPath:の削除

tableView:didSelectRowAtIndexPath:は今回使用しないので削除します。

14)tableView:editingStyleForRowAtIndexPath:の実装

本書やサンプルコードでは(#pragmaによる区切りがなく)Table view data sourceメソッドのように記述されていますが、tableView:editingStyleForRowAtIndexPath:はデリゲートメソッドで、行の編集スタイルを指定します。

今回は無条件でデフォルト値のUITableViewCellEditingStyleNoneを返しており、全ての行に対して削除や挿入ができないことになっています。


tableView:editingStyleForRowAtIndexPath:

- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath

テーブルビューの特定の場所にある行の編集スタイルをデリゲートに伝えます。

戻り値はindexPathで識別された行のセルの編集スタイルです。

このメソッドは、indexPathの場所にあるセルの編集スタイルをカスタマイズできることをデリゲートに許します。

デリゲートがこのメソッドが実装されておらず、UITableViewCellオブジェクトが編集可能(editingプロパティがYESに設定)の場合、セルはUITableViewCellEditingStyleDeleteスタイルが設定されます。

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

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


Cell Editing Style

セルで使用される編集コントロールです。

typedef enum {
    UITableViewCellEditingStyleNone,
    UITableViewCellEditingStyleDelete,
    UITableViewCellEditingStyleInsert
} UITableViewCellEditingStyle;

これらの定数はeditingStyleプロパティの値の設定に使用されます。

UITableViewCellEditingStyleNone
セルは編集コントロールを持ちません。
これはデフォルト値です。

UITableViewCellEditingStyleDelete
セルは削除編集コントロールを持ちます。
このコントロールはマイナス記号を赤い円で囲んでいます。

UITableViewCellEditingStyleInsert
セルは挿入編集コントロールを持ちます。
このコントロールはプラス記号を緑の円で囲んでいます。

15)viewDidUnloadの実装

本書やサンプルコードではviewDidUnloadは記述されていませんが、プロパティlistの所有権放棄を行います。

16)deallocの実装

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



参考文献

UIBarButtonItem Class Reference

UITableView Class Reference

UIViewController Class Reference

UINavigationItem Class Reference

UITableViewCell Class Reference

UITableViewDataSource Protocol Reference

NSMutableArray Class Reference

UITableViewDelegate Protocol Reference

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

商品詳細を見る






Wave SoundTouch music system IV
0 Comments
Leave a comment
管理者にだけ表示を許可する
Top
0 Trackbacks
Top
Calendar
06 | 2017/07 | 08
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

Wave SoundTouch music system IV
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