Nav(20)~Detail Edit(5)

2011. 01. 19
Nav(19)~Detail Edit(4)』のコメントでbobさんに指摘を受けましたので修正します。

PresidentDetailController.mのsave:メソッドにおいて、一時可変辞書tempValuesの内容を出力する際に高速列挙を使用しています。

    for (NSNumber *key in [tempValues allKeys]) {

tempValues内の全ての要素を取り出すためにallKeysメソッドでキーを取得しており、これはこれで間違いではありません。

しかし詳解 Objective-C 2.0によると、『for...in文のコレクション式(inの後ろに記述するオブジェクト)はコレクションオブジェクトを格納した変数、または値がコレクションになる式』とあります。
(allKeysで返されるオブジェクトはNSArray)

また『コレクションが辞書オブジェクトの場合はキーが取り出される』とありますので、キーだけを抜き出した配列を生成しなくても、tempValuesそのものを指定するだけで済むことになります。

    for (NSNumber *key in tempValues) {

もう一点はtableView:cellForRowAtIndexPath:での判定条件に関するものなので、後述します。


9)shouldAutorotateToInterfaceOrientation:の実装

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

10)numberOfSectionsInTableView:の削除

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

11)tableView:numberOfRowsInSection:の実装

セクションの行数として、tableView:numberOfRowsInSection:では定数kNumberOfEditableRowsを指定します。

12)tableView:cellForRowAtIndexPath:の実装

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

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

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

詳細ビューのセルはラベルとテキストフィールドで構成されており、サブビューとして追加します。

ラベルはまず、UILabelのスーパークラスUIViewのinitWithFrame:メソッドを使い、CGRectMakeで指定した位置とサイズのビューを生成します。

textAlignmentプロパティでレイアウトを右寄せ(UITextAlignmentRight)にし、サブビューの識別用タグとしてtagプロパティで定数kLabelTagを設定、ラベルを明確にするためにfontプロパティにboldSystemFontOfSize:メソッドで太字にし、contentViewプロパティにaddSubview:メソッドでサブビューとして追加します。

テキストフィールドもinitWithFrame:メソッドを使い、CGRectMakeで指定した位置とサイズのビューを生成します。

編集開始時に元の文字列をクリアしないように、clearsOnBeginEditingプロパティはNOに設定しています。

setDelegate:メソッドは、delegateプロパティをドット演算子ではなくアクセサメソッドのセッタとして使用しているもので、自身をテキストフィールドのインスタンスtextFieldのデリゲートにしています。

テキストフィールド編集時に出現するキーボードのreturnキーの文字列は、returnKeyTypeプロパティでDone(UIReturnKeyDone)に設定します。

またDoneボタンをタップしてテキストフィールドの編集を終えた時(UIControlEventEditingDidEndOnExit)の動作として、addTarget:action:forControlEvents:メソッドでアクションメソッドtextFieldDone:を呼び出すように設定します。
(これによりテキストフィールドがファーストレスポンダから外れ、キーボードが片付けられます)

そして、contentViewプロパティでセルにaddSubview:メソッドでtextFieldを追加します。

ラベルとテキストフィールドの下地ができましたので、次に値の設定を行います。

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

セルにはラベルとテキストフィールドの2つのサブビューがあるので、viewWithTag:メソッドで定数kLabelTagを指定し、ラベルを特定します。

テキストフィールドにはラベルを設定していないので、別の方法で特定します。
(タグを付けておけば便利ですが、isMemberOfClass:メソッドを使う方法を説明したかったためと思われます)

今回のセルにはテキストフィールドが一つしかないので、サブビューの中からUITextFieldクラスのビューを検索して特定します。

テキストフィールドのポインタtextFieldを一度nilでクリアします。

高速列挙でセル内のサブビュー(contentViewsubviewsプロパティで指定)を取り出し、そのサブビューがUITextFieldのクラスオブジェクト(classメソッドで指定)かをisMemberOfClass:メソッドで判定し、UITextFieldクラスだった場合にそのサブビューのポインタを設定します。

ラベルの文字列はtextプロパティに対し、固定配列fieldLabelsから行番号rowの値をobjectAtIndex:メソッドで取得します。

テキストフィールドの文字列は、親ビューから受け渡されたpresidentの内容だけでなく、一時可変配列tempValuesに値がある場合に差し替えなければならないので、tempValuesから値を取得するため、キーとなる行番号をinitWithInt:でNSUIntegerからNSNumberのrowAsNumにします。

switch文は行番号で分岐し、各行においてtempValuesに当該行のオブジェクトが含まれているかを判定し、tempValuesに値がある場合はその値を、無ければpresidentの値をテキストフィールドの文字列として設定しています。

tempValues内に値があるかどうかの判定ですが、本書ではallKeysメソッドでtempValuesのキーを配列で取得し、containsObject:メソッドで行番号が含まれているかを判別しています。

    if ([[tempValues allKeys] containsObject:rowAsNum])

bobさんが『Nav(19)~Detail Edit(4)』のコメントで指摘された方法は、(値を設定するのと同じように)objectForKey:メソッドで行番号のオブジェクトがあるかどうかを判別しています。

    if ([tempValues objectForKey:rowAsNum])

確かにキーが無ければそのオブジェクトも存在しないのですから、キーの有無と値の有無の判別は同義ですし、この方が単純で分かり易いですね。

セルの設定の仕上げとして処理が2つあります。

1つは編集中のテキストフィールドを示すポインタtextFieldBeingEditedで、セルの内容を確定した後で編集中状態を保持されると困るのでnilで解除します。

もう1つはテキストフィールドにtagプロパティでタグを行番号rowに設定しています。
(このタグはsave:メソッドでtempValueの値を設定する際のキーになります)


clearsOnBeginEditing

@property(nonatomic) BOOL clearsOnBeginEditing

編集開始時に、テキストフィールドにある古いテキストを削除するかをブール値で示します。

このプロパティをYESに設定した場合、ユーザがテキストフィールドを選択して編集を開始した時にテキストフィールドの以前のテキストはクリアされます。

NOを設定した場合、ユーザがテキストフィールドをタップした場所が挿入点となります。

:このプロパティがYESに設定されている場合でも、その前にtextFieldShouldClear:メソッドでNOを返すことにより、テキストフィールドのデリゲートをオーバーライドすることができます。


delegate

@property(nonatomic, assign) id<UITextFieldDelegatedelegate

レシーバのデリゲートを設定します。

テキストフィールドのデリゲートは、テキストフィールドからの編集に関連付けされたメッセージに応答します。

returnボタンが押された時など、ユーザや特殊なコマンドによってテキストが入力された際に、デリゲートを使用して応答することができます。


returnKeyType

@property(nonatomic) UIReturnKeyType returnKeyType

returnキーの内容を設定します。(必須)

このプロパティは様々なキータイプを設定するもので、キーのタイトルを変更し、通常は押された時にキーボードを片付けます。

このプロパティのデフォルト値はUIReturnKeyDefaultです。


UIReturnKeyType

キーボードのreturnキーに表示するテキスト文字列を設定します。

typedef enum {
    UIReturnKeyDefault,
    UIReturnKeyGo,
    UIReturnKeyGoogle,
    UIReturnKeyJoin,
    UIReturnKeyNext,
    UIReturnKeyRoute,
    UIReturnKeySearch,
    UIReturnKeySend,
    UIReturnKeyYahoo,
    UIReturnKeyDone,
    UIReturnKeyEmergencyCall,
} UIReturnKeyType;

UIReturnKeyDefault
returnキーのテキストを『return』に設定します。

UIReturnKeyGo
returnキーのテキストを『Go』に設定します。

UIReturnKeyGoogle
returnキーのテキストを『Google』に設定します。

UIReturnKeyJoin
returnキーのテキストを『Join』に設定します。

UIReturnKeyNext
returnキーのテキストを『Next』に設定します。

UIReturnKeyRoute
returnキーのテキストを『Route』に設定します。

UIReturnKeySearch
returnキーのテキストを『Search』に設定します。

UIReturnKeySend
returnキーのテキストを『Send』に設定します。

UIReturnKeyYahoo
returnキーのテキストを『Yahoo』に設定します。

UIReturnKeyDone
returnキーのテキストを『Done』に設定します。

UIReturnKeyEmergencyCall
returnキーのテキストを『Emergency Call』に設定します。


UIControlEvents

Control Events』に記載されているenum定数の型です。

typedef NSUInteger UIControlEvents;


Control Events

コントロールオブジェクトに対してすることができるイベントの種類です。

enum { 
    UIControlEventTouchDown= 1 << 0,
    UIControlEventTouchDownRepeat= 1 << 1,
    UIControlEventTouchDragInside= 1 << 2,
    UIControlEventTouchDragOutside= 1 << 3,
    UIControlEventTouchDragEnter= 1 << 4,
    UIControlEventTouchDragExit= 1 << 5,
    UIControlEventTouchUpInside= 1 << 6,
    UIControlEventTouchUpOutside= 1 << 7,
    UIControlEventTouchCancel= 1 << 8,
  
    UIControlEventValueChanged= 1 << 12,
  
    UIControlEventEditingDidBegin= 1 << 16,
    UIControlEventEditingChanged= 1 << 17,
    UIControlEventEditingDidEnd= 1 << 18,
    UIControlEventEditingDidEndOnExit= 1 << 19,
  
    UIControlEventAllTouchEvents= 0x00000FFF,
    UIControlEventAllEditingEvents= 0x000F0000,
    UIControlEventApplicationReserved= 0x0F000000,
    UIControlEventSystemReserved= 0xF0000000,
    UIControlEventAllEvents= 0xFFFFFFFF
}; 

UIControlEventTouchDown
コントロール内でのタッチダウンのイベントです。

UIControlEventTouchDownRepeat
コントロール内での繰り返しのタッチダウンイベントです。
このイベントは、UITouchのtapCountメソッドの値より1大きいです。

UIControlEventTouchDragInside
コントロールの矩形の内側で指をドラッグしたイベントです。

UIControlEventTouchDragOutside
コントロールの矩形の外側で指をドラッグしたイベントです。

UIControlEventTouchDragEnter
コントロールの矩形の内側へ指をドラッグしたイベントです。

UIControlEventTouchDragExit
矩形の内側から外側へ指をドラッグしたイベントです。

UIControlEventTouchUpInside
コントロールの矩形の内側に指がある、コントロール内でのタッチアップイベントです。

UIControlEventTouchUpOutside
コントロールの矩形の外側に指がある、コントロール内でのタッチアップイベントです。

UIControlEventTouchCancel
コントロールへの現在のタッチをキャンセルするシステムイベントです。

UIControlEventValueChanged
コントロールをタッチドラッグまたは他の操作によって、異なる値を連続して出力します。

UIControlEventEditingDidBegin
矩形に組み込まれているUITextFieldオブジェクトの編集セッションがタッチにより開始したイベントです。

UIControlEventEditingChanged
UITextFieldオブジェクトをタッチによって編集変更したイベントです。

UIControlEventEditingDidEnd
矩形から外れた場所のタッチにより、UITextFieldオブジェクトの編集セッションが終了したイベントです。

UIControlEventEditingDidEndOnExit
UITextFieldオブジェクトの編集セッションがタッチにより終了したイベントです。

UIControlEventAllTouchEvents
全てのタッチイベントです。

UIControlEventAllEditingEvents
UITextFieldオブジェクトに対する全ての編集タッチイベントです。

UIControlEventApplicationReserved
アプリケーションで使用できるコントロールイベントの値の範囲です。

UIControlEventSystemReserved
内部のフレームワークで使用するために予約したコントロールイベントの値の範囲です。

UIControlEventAllEvents
システムイベントを含む全てのイベントです。


isMemberOfClass:

- (BOOL)isMemberOfClass:(Class)aClass

レシーバが指定したクラスのインスタンスかどうかを示すブール値を返します。(必須)

戻り値は、レシーバがaClassのインスタンスである場合はYES、それ以外の場合はNOを返します。

例えば、以下のコードの場合、isMemberOfClass:はNOを返します。

NSMutableData *myData = [NSMutableData dataWithCapacity:30];
id anArchiver = [[NSArchiver alloc] initForWritingWithMutableData:myData];
if ([anArchiver isMemberOfClass:[NSCoder class]])
    ...

クラスオブジェクトはコンパイラが生成するオブジェクトですが、メンバーシップの概念をサポートしています。

したがってこのメソッドは、レシーバと指定したクラスオブジェクトの照合に使用することができます。

aClass:テストに用いるObjective-Cクラスで表されるクラスオブジェクトを指定します。


class

+ (Class)class

クラスオブジェクトを返します。

クラス名がメッセージのレシーバの場合、そのクラスを参照します。

それ以外の場合は全て、クラスオブジェクトはこのメソッドまたは類似するメソッドを介して取得する必要があります。

例えば、(NSObjectプロトコルで宣言されている)isKindOfClass:メソッドに引数としてSomeClassを渡す場合は以下のようになります。

BOOL test = [self isKindOfClass:[SomeClass class]];


containsObject:

- (BOOL)containsObject:(id)anObject

指定したオブジェクトが配列内に存在しているかどうかを示すブール値を返します。

戻り値は、配列内にanObjectが存在する場合はYES、それ以外はNOを返します。

このメソッドは、配列内の各オブジェクトに(各isEqual:メッセージにパラメータとしてanObjectを渡して)isEqual:メッセージを送信し、配列内にanObjectが存在するかを決定します。

anObject:オブジェクトを指定します。



参考文献

UITextField Class Reference

UITextInputTraits Protocol Reference

UIControl Class Reference

NSObject Protocol Reference

NSObject Class Reference

NSArray Class Reference

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

商品詳細を見る

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

商品詳細を見る






SoundLink Mini Bluetooth speaker_ii_limited
0 Comments
Leave a comment
管理者にだけ表示を許可する
Top
0 Trackbacks
Top
Calendar
05 | 2017/06 | 07
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

SoundLink Mini Bluetooth speaker_ii_limited
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