Objective-c画面推移のメモリ管理について

このQ&Aのポイント
  • Objective-c画面推移のメモリ管理についてF
  • iPhoneアプリ開発の画面推移方法とメモリ管理についての質問です。
  • 画面推移する際にメモリ使用量が増えていく問題について解決策を教えてください。
回答を見る
  • ベストアンサー

Objective-c画面推移のメモリ管理について

iPhoneアプリ開発を初めて間もなく拙い質問ですがお願いします。 StoryBoardを使わずにxibを指定して直接画面推移を行っています。 その周辺のコードは http://www.bhnt.co.jp/blog/雑記/社員:cobra/イチから学ぶiphoneipadアプリ開発-第6回-「interface-builderを使って ...を参考にしました。 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { SecondViewController *vc = [[SecondViewController alloc] initWithNibName:@"SecondViewController" bundle:nil]; [self presentViewController:vc animated:NO completion:nil]; // [self removeFromParentViewController]; // [self.view removeFromSuperview]; } 画面がタッチされたときにSecondViewControllerを呼び出して、画面を遷移しています。 SecondViewControllerにも似たコードを記述しMainViewControllerに遷移しています。 これを繰り返していると数MByteずつ使用メモリが増えていきます。まだメモリも小さく支障は全くないのですが、いずれ悩まされる前に解決したいと思い質問しました。 遷移したあとに元の画面が破棄されていないのでは無いかと思い、コメントアウトにしてある下二行を追加してみましたが、結果は変わりませんでした。 破棄されたことを示すviewDidDisappearをNSLogで確認してみたところ、呼び込まれているのですが、これはC++などでいうデストラクタとは似つかない処理でしょうか? 長々と要点の掴みづらい質問ですがどうかよろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

> SecondViewControllerにも似たコードを記述しMainViewControllerに遷移しています。 これが気になるのですが、SecondViewControllerからMainViewControllerに遷移するのに --------------------------------------------------------- [self dismissViewControllerAnimated:YES completion:nil]; --------------------------------------------------------- で呼び出し元の画面に戻っているのではなく、 --------------------------------------------------------- MainViewController *vc = [[MainViewController alloc] initWithNibName:@"MainViewController" bundle:nil]; [self presentViewController:vc animated:NO completion:nil]; --------------------------------------------------------- という感じにしているのですか? だとしたら使用メモリがどんどん増えていくのは当たり前です。 このコードだと、元の画面に戻っているのではなく、別の新しい MainViewControllerを生成して、それに移動しています。 そして、その別の新しいMainViewControllerは、さらに 別の新しいSecondViewControllerを生成して、それに移動します。 呼び出し元のViewControllerは、いずれ呼び出し先から dismissViewControllerAnimatedされて戻ってくるのを 期待してそれぞれ解放されずに待っている状態です。 元の画面に戻りたいなら、冒頭のdismissViewControllerAnimatedを 使って戻ってください。 > 遷移したあとに元の画面が破棄されていないのでは無いかと思い、コメントアウトにしてある下二行を追加してみましたが、結果は変わりませんでした。 [self removeFromParentViewController]; で自分自身のビューコントローラーを削除していますが、これだけではオブジェクトは破棄 されません。そのビューコントローラーオブジェクトを変数に保持しているものがなくなって 初めて破棄されます。上記のケースだとSecondViewControllerのparentViewControllerプロパティ に、MainViewControllerが保持されていますから、SecondViewController(またはその中の parentViewControllerプロパティ)が破棄されない限り、MainViewControllerは破棄されません。 > 破棄されたことを示すviewDidDisappearをNSLogで確認してみたところ、呼び込まれているのですが、これはC++などでいうデストラクタとは似つかない処理でしょうか? viewDidDisappearは、そのビューコントローラーが画面に表示されなくなった 時に呼ばれます。オブジェクト破棄とは別の話です。

tojoheader
質問者

お礼

回答ありがとうございます。 はい、おっしゃられるとおりのコードを書いていました。 [self dismissViewControllerAnimated:YES completion:nil]; をSecondViewControllerで使ったところ、何度行き来してもメモリが増えることはありませんでした。 他の部分の解説も大変有難いです。本当にありがとうございました。

関連するQ&A

  • Objective-c 画面遷移について

    やはり、画面遷移ではまっていますので、助けて下さい。 navigationControllerで作成しています。 (内容は以前に質問させて頂いているものとほぼ同じですが、) 「FirstViewController」はUIScrollViewでスクロールさせている画面で、タッチイベントを取得する為に UIScrollView のサブクラスを作っています。 そこでタッチすると、「SecondViewController」へ遷移するようにしたいのですが、下記のように単純にpushViewControllerを使ってサブクラスへ書くと、「Property 'navigationContoroller' not found on object of type 'MyScrollview'」というエラーが表示されてしまいます。 このクラスへ書いたらいけないというのは、なんとなく分かりますが、かと言って何からどう手をつければ良いのか分かりません…… 問題なく画面遷移させるにはどうしたらよいのでしょうか。 詳しく教えて頂けると、大変助かります。。 ↓FirstViewController.h↓ @interface FirstViewController : UIViewController{   MyScrollview *controller; IBOutlet UIScrollView *scrollView; } ↓FirstViewController.m↓ - (void)viewDidLoad { controller = [[ MyScrollview alloc] initWithFrame:CGRectMake(0, 0, 1100, 1100)]; self.view = controller; [super viewDidLoad]; [super loadView]; scrollView.contentSize = controller.frame.size; [scrollView addSubview:controller]; } ↓MyScrollview .h↓ @interface MyScrollview : UIView<UIScrollViewDelegate>{ } @end ↓MyScrollview .m↓ -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent*)event{ ~省略~ SecondViewController *mvc = [[[SecondViewController alloc] initWithNibName:nil bundle:nil] autorelease]; [self.navigationController pushViewController:mvc animated:YES]; }

  • Objective-c  画面遷移について

    毎回、初歩的な質問内容で申し訳ありませんが、困っているので教えて下さい。 「FirstViewController」はUIScrollViewでスクロールさせている画面で、タッチイベントを取得する為に UIScrollView のサブクラスを作っています。 そこでタッチすると、「SecondViewController」へ固定の画面で遷移するようにしたいのですが、「SecondViewController」の画面もそのままスクロール画面で表示されてしまいます。。。 「SecondViewController」をスクロールさせず、位置x=0 y=0で表示させるにはどうしたら良いのでしょうか? 詳しく教えて頂けると、大変助かります。。 ↓FirstViewController.h↓ @interface FirstViewController : UIViewController{   MyScrollview *controller; IBOutlet UIScrollView *scrollView; } ↓FirstViewController.m↓ - (void)viewDidLoad { controller = [[ MyScrollview alloc] initWithFrame:CGRectMake(0, 0, 1100, 1100)]; self.view = controller; [super viewDidLoad]; [super loadView]; scrollView.contentSize = controller.frame.size; [scrollView addSubview:controller]; } ↓MyScrollview .h↓ @interface MyScrollview : UIView<UIScrollViewDelegate>{ } @end ↓MyScrollview .m↓ -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent*)event{ SecondViewController *svc; svc = [[SecondViewController alloc] init]; [self addSubview:[svc view]]; }

  • iPhoneアプリの開発についてです。

    元のビューからモーダルで表示させるビューに画面遷移に伴い値を受け渡したいのですがうまくいきません。 私は主に画面遷移する際 ○○○ *△△△ = [self.storyboard instantiateViewControllerWithIdentifier:@"□□□"]; [self presentViewController:△△△ animated:YES completion: nil]; とコーディングしています。 インスタンス生成部分を ○○○ *△△△ = [[○○○ alloc] init]; とすれば簡単に値が受け渡しできるのですが、storyboadで作ったような表示になりません。(セルの高さが違う、ラベルが表示されないなど) グローバル変数などを使っても解決できますが、なるべく複雑にはしたくありません。 ご指摘お願いします。

  • Objective-Cのエラーコードの意味

    タイトルの通りです。 エラー部分は最下部にあります。 ------------------------------------------------------------------------------------------------- // // ViewController.m // Kadai // // Created by on 2014/08/10. // Copyright (c) 2014年 saikoro. All rights reserved. // #import "ViewController.h" @interface ViewController () <UIAlertViewDelegate> @property (weak, nonatomic) IBOutlet UITextField *tfMyouji; @property (weak, nonatomic) IBOutlet UITextField *tfName; @property (weak, nonatomic) IBOutlet UILabel *Aisatsu; @end @implementation ViewController // 画面タッチ時 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ // キーボード非表示 [self.tfMyouji resignFirstResponder]; [self.tfName resignFirstResponder]; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } // [挨拶する]ボタン押下 - (IBAction)introduce:(id)sender { UIAlertView *av = [[UIAlertView alloc]initWithTitle:@"確認" message:@"挨拶しますか?" delegate:self cancelButtonTitle:@"キャンセル" otherButtonTitles:@"はい", nil]; // 表示 [av show]; } // AlertViewボタン押下 - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{ UIAlertView *av = [[UIAlertView alloc] initWithTitle:@"再確認" message:@"本当に挨拶しますか?" delegate:nil cancelButtonTitle:@"やっぱりやめときます" otherButtonTitles:@"早く!", nil]; [av show]; } // AlertViewボタンさらに押下 + (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{ // 入力された名前の保持 NSString *str = self.tfMyouji.text; ←ここでエラーが出ます。なぜか「tfMyouji」が                    予測で出てきません } @end ------------------------------------------------------------------------------------------------- どなたかエラーの理由をご教授頂けないでしょうか。 以上、何卒宜しくお願い致します。

  • objective-c 画面遷移について

    プログラミングに関して素人です。 UIViewControllerからPushコードを使って別のUIViewに画面遷移したいのですが 遷移先にTableViewを2つ並べております。 画面遷移する際のコードはどのように記述したらいいのでしょうか? 詳しいかたお力お貸しいただければと思います。 ViewController.m - (IBAction)NewsPage:(UIButton *)sender { //こちらの記述方法が不明 } TViewController.h // XibファイルとUIViewの紐づけ。 @property (weak, nonatomic) IBOutlet UITableView *leftTableView; @property (weak, nonatomic) IBOutlet UITableView *rightTableView; - (IBAction)TopButton:(UIButton *)sender; 根本的になにか違えばご指摘お願いします。

  • TableViewでタップした時にキーボードを隠す

    ObjectiveCを用いてiPhnoneアプリ開発の勉強をしています。 TableViewControllerのセルにUITextFieldを設置し、そのTextFieldをタッチして表示されたキーボードを キーボードの外がタップされた時に引っ込める(隠す)処理をしたいのですが、うまくできませんでしたので助言をいただきたいです。 Tap Gesture Recognizerを用いる方法や touchesBeganメソッドを用いてタップを検知し[self.view endEditing:YES];でキーボードを閉じる という方法を試したのですが、これらたUIViewControllerでないとできないようで、 キーボードの外をタップしても、セルが選択されてしまい、キーボードは閉じませんでした。 この問題に関して、以下のサイトが参考になると思ったのですが、 http://onno.jp/dev/2012/02/uitableview-touchesbegan-uiviewcontroller.html >IB で TableView のクラスを TouchableTableView に変更 という部分が、どこを指しているのか分からず、どうしたら良いのか分かりません。 どこのTableViewのクラスを、TouchableTableViewに変更したら良いのでしょうか? 試しにキーボードを引っ込ませる処理を組み込みたいTableViewControllerのスーパークラスを UITableViewController から TouchabeTableViewに変更してみましたが、うまくいきませんでした・・ タップした時にキーボードが引っ込ませたいTableViewControllerと、 新たに作成したTouchableTableViewはどのようにして関連付けるのでしょうか? 以下にTouchableTableViewのソースコードを書いておきます。 (Xcode6になり、Fileの新規作成画面が変わり、クラスの書き方がいつもと違うようになっているのが気になりますが・・・。) ----------- ■TouchableTableView.h #import <UIKit/UIKit.h> @interface UITableView (TouchableTableView) @end ■TouchableTableView.m #import "TouchableTableView.h" @implemention UITableView (TouchableTableView) - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [self.nextResponder touchesBegan:touches withEvent:event]; [super touchesBegan:touches withEvent:event]; } @end --------- 回答お願いします

  • iPhoneアプリの開発についてです。

    UINavigationControllerのルートに紐づけられたBookMarkViewControllerというビューがあります。 このBookMarkViewControllerはテーブルビューで、 (1) BookMarkViewController *nextDir = [[BookMarkViewController alloc] init]; [self.navigationController pushViewController:nextDir animated:YES]; 上記のようなコードで、次々と画面遷移していきます。 また、BookMarkViewControllerには、 (2) BookMarkViewController *move = [[BookMarkViewController alloc] init]; move.isMove = YES; UINavigationController *nav = [self.storyboard instantiateViewControllerWithIdentifier:@"BookMarkView"]; [nav setViewControllers:[NSArray arrayWithObjects:move, nil]]; [self presentViewController:nav animated:YES completion:nil]; 上記のような内容のメソッドがあり、次々と画面遷移することのできる新たなUINavigationControllerをモーダル表現で表示します。 画面遷移する前のBookMarkViewControllerでは、上記のコードでうまくモーダルがでるのですが、(1)のメソッドを実行し新たに作り遷移したBookMarkViewControllerではなぜか、 *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Application tried to present a nil modal view controller on target <BookMarkViewController: 0x11822e070>.' というエラーが吐き出されうまくいきません。 (2)のメソッドで「nav」を生成した直後にnav.viewControllersをNSLogしてみたのですが、nullがかえされてしまいました。(成功した例では<BookMarkViewController ○○○>と、正常に表示されました) 誰かわかる方ご指摘お願いします。

  • objective-c 画面遷移について

    今、iPhoneアプリを開発しています。簡単なカードゲームですが、 画面遷移について困っています。 サブクラス内のタッチイベントに、 [super presentModalViewController:viewController animated:YES]; と記述し、画面を切り替えたいのですが、 「'UIView' may not respond to 'presentModalViewController : animated:'」と 注意メッセージが表示され、 また、実行すると「Thread 1: received signal: "SIGABRT"」 となり、落ちてしまいます。 何分、初心者なもので、どこからどう手をつけたら良いのか分かりません。 色々調べたのですが、中々該当する答えが見つかりませんでした。 どなたか、お分かりになる方教えて頂けないでしょうか。 宜しくお願いします。

  • ios/初回起動時に表示させる画面

    初回起動時にだけ、WelcomeViewControllerというViewControllerを表示させたいのですが、うまくいきません Is Initial View Controllerに設定してあるFirstViewControllerの.mファイルに以下のコードを書きました -(void)viewWillAppear:(BOOL)animated{ BOOL HasLaunchedOnce = [[NSUserDefaults standardUserDefaults] boolForKey:@"HasLaunchedOnce"]; if (HasLaunchedOnce == NO) { // 初回起動時 [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"HasLaunchedOnce"]; [[NSUserDefaults standardUserDefaults] synchronize]; WelcomeViewController *welcomeViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"welcome"]; [self presentViewController:welcomeViewController animated:YES completion:nil]; } }

  • 一つの画面でスクロールとフリックをする方法について

    今、画像を左右に数枚スクロールさせれて、かつ、その画像を上や下にフリックすると各々、上や下に他の画像がでてきて、さらに拡大縮小もできるようなコードを書いているのですが、 ViewContorller(以下、VC)にスクロールと上下のフリックのメソッドを書き、 もう一つのPageView(UIScrollVIewクラスを親にもつ。以下、PV)に画像が拡大縮小するようなメソッドをdelegateを使って書いています。 その際に、VCのほうに書いているスクロールのメソッドがフリックのメソッドを邪魔してうまくフリックのtouchメソッドを呼んでくれません。スクロールメソッドを消すと、フリックが使えますが、そうでないときは、スクロールと拡大縮小だけができます。 調べたところ、        scrollView.canCancelContentTouches=NO;        scrollView.delaysContentTouches=NO; を使うと良いというのでやってみたのですが、うまくいきません。 もし、お分かりになる方がいらっしゃいましたら、大変お手数かけますが、ご教授ください。 以下が VC.mです。 xcodeは5.0バージョンです。 - (void)viewDidLoad { [super viewDidLoad]; UIScrollView *scrollView = [[UIScrollView alloc] init]; //ここに先ほどのを入れてみました。 scrollView.canCancelContentTouches=NO; scrollView.delaysContentTouches=NO; scrollView.frame = self.view.bounds; scrollView.contentSize = CGSizeMake(self.view.frame.size.width * kPageNum, self.view.frame.size.height); scrollView.pagingEnabled = YES; [self.view addSubview:scrollView]; for (int i=0;i<kPageNum;i++) { PageView *page = [[PageView alloc] initWithFrame:self.view.bounds]; //setImageメソッドはPVのほうで定義しています。 [page setImage:[NSString stringWithFormat:@"%d.png", i]]; page.frame = CGRectMake( self.view.frame.size.width * i, 0, self.view.frame.size.width, self.view.frame.size.height ); [scrollView addSubview:page]; } } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; _timestampBegan = event.timestamp; _pointBegan = [touch locationInView:self.view]; } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { static const NSTimeInterval kFlickJudgeTimeInterval = 0.3; static const NSInteger kFlickMinimumDistance = 10; UITouch *touchEnded = [touches anyObject]; CGPoint pointEnded = [touchEnded locationInView:self.view]; NSInteger distanceHorizontal = ABS(pointEnded.x - _pointBegan.x); NSInteger distanceVertical = ABS(pointEnded.y - _pointBegan.y); if (kFlickMinimumDistance > distanceHorizontal && kFlickMinimumDistance > distanceVertical) { return; } NSTimeInterval timeBeganToEnded = event.timestamp - _timestampBegan; if (kFlickJudgeTimeInterval > timeBeganToEnded) { if (distanceHorizontal > distanceVertical) { if(pointEnded.x>_pointBegan.x) {} //上下のフリックだけなのでここには書いていません。 else{}} else{ if (pointEnded.y > _pointBegan.y) { NSLog(@"あ");//NSLogで反応の仕方をみてます。 } else { NSLog(@"い"); } 初心者のため色々と質問の内容から間違いがあるかもしれませんが、宜しくお願い申し上げます。

専門家に質問してみよう