iPhoneのViewの切り替えは、まだまだ日が浅いせいか色々頭を悩ませる部分。
UINavigationControllerのような階層的な切り替えでなく、多様なレイアウトが混在するような画面繊維、 例えばUITabBarControllerとUIViewControllerが独立して存在し、これらをある条件によって切替える場合。
例えば、iPhoneアプリ入門(Viewの変更)の方法のようにaddSubview:newViewやremoveFromSuperviewで 親viewに子のviewを追加、削除しています。
ただこのサンプルでは、viewが増えるごとにif文で条件分岐しなきゃいけない感じ(?)なので修正してみる。
(1) UITabBarControllerを利用するので、プロジェクトはTabBarApplicationを選択する。 ※その他UINavigationController等を利用する場合は、手動でDelegate等の追加が必要
(2) 第一階層の画面は以下の2つを利用する
・トップ画面(ログイン前の画面群):(UIViewController) topViewController ・メイン画面(ログイン後の画面群):(TabBarController) mainViewController
topViewControllerは、ViewControllerで.h、.m、.xibを作成する。 ※サンプルではLoginViewControllerの名称で作成 mainViewControllerは、タブで表示する数だけViewControllerの.h、.m、.xibを作成する。
(3) アプリケーションデリゲート.hを修正する。 StockAppDelegate.h
@interface StockAppDelegate : NSObject <UIApplicationDelegate, UITabBarControllerDelegate> {
UIWindow *window;
UITabBarController *mainViewController;
UIViewController *topViewController;
}
@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet UITabBarController *mainViewController;
@property (nonatomic, retain) IBOutlet UIViewController *topViewController;
-(void) showMainView;
-(void) showTopView;
-(void) showView:(UIView *)view;
(4) UIViewController、TabBarControllerを追加し、アウトレットを設定する。 ※UIViewControllerは、NibにLoginViewControllerを指定している
(5) TabBarControllerに表示したいViewControllerを追加する。
(6) AppDelegateでUIViewController、TabBarControllerのdelgateを設定する。
次にStockAppDelegate.mを修正
(1) mainViewController、topViewControllerを@synthesizeする。
@synthesize window;
@synthesize mainViewController;
@synthesize topViewController;
(2) showViewの実装
-(void) showView:(UIView *)view {
for (UIView *subView in window.subviews) {
[subView removeFromSuperview];
}
[window addSubview:view];
[window makeKeyAndVisible];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.75];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.window cache:YES];
[UIView commitAnimations];
}
windowに追加されたsubviewsがあれば全て削除し、指定したviewを追加する。 adddSubviewの他に、insertSubview、bringSubview、sendSubview、eschangeSubviewAtIndexがあるので、 削除する方式ではなく、これらを利用しても良いかも知れない。 ※参考:福井高専IT研究所 UIView
切り替えアニメーションは、viewではなくアプリケーションのメインビュー(window)で実現している。
(3) showTopView、showMainViewの実装
-(void) showTopView {
[self showView:topViewController.view];
}
-(void) showMainView {
[self showView:mainViewController.view];
}
showViewで、表示したいviewを引数として実行している。
(4) didFinishLaunchingWithOptionsの実装
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self showTopView];
return YES;
}
アプリケーション起動時に、topViewController.viewを表示するようにする。
----2010/09/01追記 didFinishLaunchingWithOptionsに記述するのはあまりよろしくない処理と思います。 View遷移を管理するクラスを作った方がよさげです。
(5) LoginViewControllerで、ビュー切替えの処理を実装する。 LoginViewController.xib ※ログインボタンをクリックしたらmainViewController.viewを表示する。
-(IBAction) changeView:(id)sender {
if (TRUE) {
StockAppDelegate *delegate = (StockAppDelegate*)[[UIApplication sharedApplication] delegate];
[delegate showMainView];
}
}
ただ、これだとDelegateの意味がないか・・・。 普通に、UIApplication showMainViewでいいもんね。 そもそもUIApplicationにメソッド書いてる時点で駄目っすね。
----2010/09/01追記 LoginViewControllerにdelegateを定義し、showMainView:の定義されているクラスでLoginViewControllerにdelegateを受け渡してやるのが正しいか?
View切替をするカスタムクラス
- (void)viewDidLoad {
loginViewController.delegate = self;
}
- (void)showMainView {
....
}
@protocol LoginViewControllerDelegate;
@interface LoginViewController : UIViewController {
id delegate;
}
@property (nonatomic, assign) id <LoginViewControllerDelegate> delegate;
@end
@protocol LoginViewControllerDelegate
-(void)showMainView;
@end
これで、LoginViewController上でdelegateを経由してshowMainView:を実行できる。
delegate云々もそうですが、UIViewController、UITabNavigationController、UITabBarControllerが複雑に入り組んだアプリを作成する場合、どんな画面設計にするか?の方が重要ですね(^_^;)