appを組むためのテストappをいろいろ書いているのだが、なかなかうまくいかない。
TableViewにモーダルビューから取り込んだテキストを表示したいのだが、Delegateでつまづく。
そこでもう一度、きちんとDelegateをやり直してみることにした。
スケルトンプロジェクトを作成
View-based Applicationで名前は"ModalViewEX2"
子ビューの追加
"ファイル"->"新規ファイル..."を選択、"UIViewController subclass"を選び、"With XIB for user interface"にチェックを入れて、"次へ"進む。
ファイル名は"ChildViewController"として、"同時にChildViewController.hも作成"にチェックする。
Text Fieldを入れる
"ModalViewEX2ViewController.h"、"ChildViewController.h"にそれぞれUITextFieldを参照するIBOutletを作る。
"ModalViewEX2ViewController.xib"、"ChildViewController.xib"を(Interface Builderで)開き、Text Fieldを追加する。
作ったUITextFieldへの参照と、Text Fieldを接続する。
さらに、Text FieldのDelegateを"File's owner"に設定する。
TextFieldDelegateを追加する
"ModalViewEX2ViewController.h"、"ChildViewController.h"のそれぞれに
"ModalViewEX2ViewController.m"、"ChildViewController.m"に以下を追加
ここまででビルドし実行すると、親ウインドウのテキストフィールドに入力ができ、return/改行するとソフトウェアキーボードが閉じるはずだ。
- (BOOL) textFieldShouldReturn:(UITextField *)textField
{
[ textField resignFirstResponder ];
return YES;
}
モーダルビューを開く
"ModalViewEX2ViewController.m"の行頭の"#import..."の下に、"#import "ChildViewController.h""を追加した上で、以下のメソッドを実装
ここで出てくる"textfieldParent"と"textfiledChild"は、先ほどInterface Builderで作ったText Fieldへの参照である。
- (void) changeToChildViewController
{
ChildViewController* childVC = [ [ ChildViewController alloc ] init ];
[ self presentModalViewController: childVC animated: YES ];
childVC.textfieldChild.text = textfieldParent.text;
[ childVC release ];
}
"textfieldChild"がプロパティとして使えるように、宣言を追加する必要があるが、これは後記を参照のこと。
先ほど、"ModalViewEX2ViewController.m"に実装した"textFiledShouldReturn"に、以下のように一行追記する。
これでビルドし実行すると、親ビューのテキストフィールドに入力ができ、return/改行するとソフトウェアキーボードが閉じた後に、子ビューがアニメーション付きで表示されるはずだ。
- (BOOL) textFieldShouldReturn:(UITextField *)textField
{
[ textField resignFirstResponder ];
[ self changeToChildViewController ];
return YES;
}
しかもそのときには、親ビューのテキストフィールドに入力した内容が、子ビューのテキストフィールドにも反映されているはずである。
親ビューへのDelegateの実装
まず子ビュー側の準備をする。
"ChildViewController.h"を以下のように、変更する。
ここで新しく追加している@protocolが、親ビューへdelegateする内容である。
@protocol ModalViewEX2ViewControllerDelegate;@interface ChildViewController : UIViewController
{
IBOutlet UITextField* textfieldChild;
idparentDelegate;
}- (void) setNameToParent;
@property ( assign, nonatomic ) id
parentDelegate;
@property ( retain, nonatomic ) UITextField* textfieldChild;@end
@protocol ModalViewEX2ViewControllerDelegate
- (void) setName: (NSString*) stringName;
@end
@interfaceで設定しているプロパティ"id
2個目の@propertyが、先ほど触れた"textfiledChild"をプロパティとして他のクラスから使用できるための宣言である。
これに加えて"ChildViewController.m"にも、
と、synthesizeを加える必要がある。
@implementation ChildViewController@synthesize parentDelegate;
@synthesize textfieldChild;
次に、子ビューが親ビューにdelegateするメソッドの追加である。
"DelegateEX2ViewController.h"を以下のように、変更する。
2個目のメソッド"(void) setName: (NSString*) stringName"が子ビューが親ビューにdelegateするメソッドである。
#import
#import "ChildViewController.h"@interface ModalViewEX2ViewController : UIViewController
{
IBOutlet UITextField* textfieldParent;
}- (void) changeToChildViewController;
- (void) setName: (NSString*) stringName;
@end
そしてメソッドを"DelegateEX2ViewController.m"に実装する。
- (void) setName:(NSString *)stringName
{
textfieldParent.text = stringName;
}
Delegateを使用する
実装したDelegateを使用するための記述を追加する。
- 親ビューへの参照を子ビューに引き渡す
"ModalViewEX2ViewController.m"の"changeToChildViewController"に、親ビューへの参照を子ビューに引き渡す記述を追加。
- (void) changeToChildViewController
{
ChildViewController* childVC = [ [ ChildViewController alloc ] init ];
childVC.parentDelegate = self;
[ self presentModalViewController: childVC animated: YES ];
childVC.textfieldChild.text = textfieldParent.text;
[ childVC release ];
}
- 子ビューでdelegateされたメソッドを使用する
"ChildViewController.h"で宣言だけしてあった"setNameToParent"を実装する。
"ChildViewController.m"に以下を追加する。
そしてこのメソッドが、ソフトウェアキーボードが閉じられた時に使用されるように、"textFieldShouldReturn"を以下のように変更する。
- (void) setNameToParent;
{
[ parentDelegate setName: textfieldChild.text ];
[ self dismissModalViewControllerAnimated: YES ];
}
これで、子ビューでソフトウェアキーボードが閉じられると、子ビューが閉じ、そのときの子ビューのテキストフィールドの内容が、親ビューのテキストフィールドに反映されるはずである。
- (BOOL) textFieldShouldReturn:(UITextField *)textField
{
[ textField resignFirstResponder ];
[ self setNameToParent ];
return YES;
}