画面遷移する際の概念がやっと理解できたので、構成を残しておく。
サンプルは以下の通り。
処理順のイメージ
- AppDelegateがWindowを生成
- AppDelegateがTopViewControllerを生成してWindowに表示
- TopViewControllerがViewに載ったらイベント付きのボタンを2つ生成
- ボタンが押されたらViewController1を生成してWindowのViewに掲示。
- ViewController1がViewに載ったらイベント付きのボタンを1つ生成
- ボタンが押されたらTopViewControllerを生成してViewに乗せる。
気をつけなければ成らないのは以下の点
- このサンプルではUINavigationControllerを利用しているので、遷移経路が全て保持されており、経路上の画面自体も保持され続ける。
- よって、メモリオーバー必至。
- メモリオーバー時用の対処はUIKit詳細リファレンスに載ってるのでそれを参照。
サンプル
AppDelegate.h
#import @interface AppDelegate:NSObject { UIWindow* window_; UIViewController* rootController_; } @property (strong, nonatomic) UIWindow *window; @end
AppDelegate.m
#import "AppDelegate.h" #import "TopViewController.h" @implementation AppDelegate @synthesize window = _window; - (void)applicationDidFinishLaunching:(UIApplication *)application{ // window を自分で作成 CGRect bounds = [[UIScreenmainScreen]bounds]; window_ = [[UIWindowalloc] initWithFrame:bounds]; TopViewController* top = [[[TopViewController alloc]init]autorelease]; rootController_ = [[UINavigationController alloc] initWithRootViewController:top]; [window_addSubview:rootController_.view]; [window_makeKeyAndVisible]; } - (void)dealloc{ [rootController_release]; [window_release]; [superdealloc]; } @end
TopViewController.h
#import @interface TopViewController : UIViewController @end
TopViewController.m
#import "TopViewController.h" @implementation TopViewController - (UIButton*)makeButton:(CGRect)rect text:(NSString*)text tag:(NSInteger)tag{ UIButton* button = [UIButtonbuttonWithType:UIButtonTypeRoundedRect]; [button setFrame:rect]; [button setTag:tag]; [button setTitle:text forState:UIControlStateNormal]; [button addTarget:selfaction:@selector(clickButton:) forControlEvents:UIControlEventTouchUpInside]; return button; } - (void)viewDidLoad{ NSLog(@"top view did load"); [superinit]; UIButton* milkButton = [self makeButton:CGRectMake(10, 20, 300, 100) text:@"milk"tag:0]; [self.viewaddSubview:milkButton]; UIButton* soltButton = [self makeButton:CGRectMake(10, 120, 300, 100) text:@"solt"tag:1]; [self.viewaddSubview:soltButton]; NSLog(@"top view did load end"); } - (IBAction)clickButton:(UIButton*)sender{ NSLog(@"click Milk: tag is : %d",sender.tag); /* 画面遷移の処理を行う。 1:viewControllerを生成する。 2:その画面に遷移。 */ //UIViewControllerを生成 Class class = NSClassFromString(@"ViewController1"); id viewController = [[[class alloc] init ]autorelease]; [self.navigationController pushViewController:viewController animated:YES]; } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { return (interfaceOrientation == UIInterfaceOrientationPortrait); } @end
ViewController1.h
#import @interface ViewController1 : UIViewController @end
ViewController1.m
#import "ViewController1.h" @implementation ViewController1 - (void)viewDidLoad{ [super viewDidLoad]; //Hello,world!ラベルを追加 //背景は白、文字は黒で。 UILabel* label = [[[UILabel alloc] initWithFrame:self.view.bounds] autorelease]; label.text = @"Hello, world"; label.textAlignment = UITextAlignmentCenter; label.backgroundColor = [UIColor whiteColor]; label.textColor = [UIColor blackColor]; label.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; [self.view addSubview:label]; //これをタップしたら画面遷移する UIButton* button = [UIButton buttonWithType:UIButtonTypeRoundedRect]; [button setTitle:@"画面遷移" forState:UIControlStateNormal]; [button sizeToFit]; CGPoint newPoint = self.view.center; newPoint.y += 50; button.center = newPoint; button.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin; [button addTarget:self action:@selector(buttonDidPush:) forControlEvents:UIControlEventTouchUpInside]; [self.viewaddSubview:button]; } -(id)init{ if((self = [superinit])){ self.title=@"Hello"; } returnself; } - (void)buttonDidPush:(UIButton*)sender{ NSLog(@"Pushed!!"); id TopViewController = [[[TopViewController alloc] init ]autorelease]; [self.navigationController pushViewController:TopViewController animated:YES]; } @end
おまけ
ちなみにViewController1のbuttonDidPush:senderメソッドを以下の様に書き換えると、トップに戻る様になるので遷移経路を保持せずにメモリを節約できる。
- (void)buttonDidPush:(UIButton*)sender{ NSLog(@"Pushed!! tag:%d",sender.tag); [self.navigationController popToRootViewControllerAnimated:YES]; // id viewController = [[[TopViewController alloc] init ]autorelease]; // [self.navigationController pushViewController:viewController animated:YES]; }