iPhoneアプリの画面遷移でエラーが発生する理由について

このQ&Aのポイント
  • iPhoneアプリで画面遷移を行う際に、特定のコードを実行するとエラーが発生する問題があります。
  • エラーメッセージによると、新たに作られた画面に対してモーダル表示する際にnilのビューコントローラを表示しようとしているようです。
  • 生成されたビューコントローラには正常に情報が設定されていない可能性があるため、エラーが発生していると考えられます。
回答を見る
  • ベストアンサー

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 ○○○>と、正常に表示されました) 誰かわかる方ご指摘お願いします。

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

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

nav.viewControllersがnilというよりも、 それ以前にnavやself.storyboardが nilになっているんじゃないでしょうか? (1)のメソッドではBookMarkViewControllerを [[BookMarkViewController alloc] init]; で作っていますから、これで作られたViewControllerの中の self.storyboardはnilのはずです。 このため(2)の処理はinstantiateViewControllerWithIdentifierの呼び出しも viewControllersの設定も無視されて、navがnilのままpresentViewController を呼び出して「Application tried to present a nil modal view controller 」 というエラーになったんじゃないでしょうか? BookMarkViewControllerをinstantiateViewControllerWithIdentifierで 作れば、すべてうまく行きそうな気がします。 そして、(2)の処理もNavigationControllerのルートビューとして BookMarkViewControllerがstoryboardで関連付けられているなら NavigationControllerをinstantiateViewControllerWithIdentifierする だけで自動的にstoryboardでBookMarkViewControllerも作られ、 とても簡単になるはずです。 ただ、老婆心ながらNavigationControllerのStoryboardIDを"BookMarkView" とするのはやめた方がよいと思います。一見BookMarkViewControllerの StoryboardIDに見えますので。StoryboardIDは、クラス名と同じ名前に しておくのがわかりやすくて無難です。

nylonraw999
質問者

お礼

storyboadでインスタンスしないとstoryboadがnilになってしまうとは知りませんでした。 問題解決しました。ありがとうございます。

関連するQ&A

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

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

  • iPhoneアプリ とあるプログラムの質問です。

    色々調べたり、書き換えてみたりしたのですが、原因がいまいちよくわかりません。お手上げなので質問させていただきます。 Nabigation-Basedのアプリ製作の中で、テーブル表示から下層画面を選択して、画面遷移をするためのプログラムをRootViewController.mに書いているのですが、シミュレータで実行すると [self.navigationController pushViewController:detailViewController animated:YES]; で、Thread1:Program received signal:"SIGABRT"の表示がでます。(iOS 4.1です) 考えられる原因は何があるでしょうか。ヒントでも構いませんのでよろしくお願い致します。前後の文は下記です。 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { indexPath.section == 0 ; if( indexPath.row == 0 ) { cal_1_UIViewController *detailViewController = [[cal_1_UIViewController alloc] initWithNibName:@"cal_1_UIViewController" bundle:nil]; ☆☆☆[self.navigationController pushViewController:detailViewController animated:YES];☆☆☆→エラーがでます。 [detailViewController release]; }else if( indexPath.row == 1 ) { cal2_UIViewController *detailViewController = [[cal2_UIViewController alloc] initWithNibName:@"cal2_UIViewController" bundle:nil]; [self.navigationController pushViewController:detailViewController animated:YES]; [detailViewController release]; }else if( indexPath.row == 2 ) { cal3_UIViewController *detailViewController = [[cal3_UIViewController alloc] initWithNibName:@"cal3_UIViewController" bundle:nil]; [self.navigationController pushViewController:detailViewController animated:YES]; [detailViewController release]; }

  • xcodeでのiOS開発で、コードで画面遷移する時

    xcodeでのiOS開発で、コードで画面遷移する方法について質問です。 テーブルビューで、セルをタップすると呼び出されるメソッドで コードで画面遷移をさせようとしています。 しかし、画面遷移をすると遷移先の画面が真っ黒になってしまいます。 どうすればなおりますか? - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { NextViewController *nvc = [[NextViewController alloc] init]; nvc.hidesBottomBarWhenPushed = YES; [self.navigationController pushViewController:nvc animated:YES]; } ちなみに、遷移先のクラスはインポートしてあります。 StoryBoardは使っていません。

  • 【iphoneアプリ開発】ボタン&処理の共通化

    突然の質問失礼致しますm(_ _)m ナビゲーションバーを使用したアプリを作っています。 右に「使い方」の画面へ遷移するUIBarButtonItemを配置したいと考えております。 このとき、各画面のボタンの配置、遷移したときのアクションを書けば 遷移できるのは確認できたのですが、全てのページにそれを書くのがあまり よくないような気がしています。 ボタンとボタンのアクションを共通化することは可能でしょうか? また、その場合どのファイルにどのように書くのが後々の変更等にも耐えやすいでしょうか? (例えば、「使い方」ボタンを「設定」ボタンに変更する等。。。) 実装しているボタンとボタンのアクションのソースは以下になります。 //ボタンの配置(viewDidLoad) UIBarButtonItem *btn = [[UIBarButtonItem alloc] initWithTitle:@"使い方" style:UIBarButtonItemStylePlain target:self action:@selector(howtoButtonTouched:)]; self.navigationItem.rightBarButtonItem = btn; //ボタンのをタップしたときのアクション -(void)howtoButtonTouched:(id)sender { //使い方画面へ遷移 HowtoViewController *howtoViewController = [[HowtoViewController alloc] init]; [self.navigationController pushViewController:howtoViewController animated:YES]; } どなたか、良い方法があればご教授頂けますと 大変ありがたいです。

  • iPad NavigationにSplitView

    Navigation Basedアプリで、画面遷移してSplitViewを表示したいのです。 以下を参考に、Viewを切り替えてのSplit Viewの表示はできました。 http://temping-amagramer.blogspot.com/2010/09/ipadobjective-c.html LeftTableViewController *lefttableviewcontroller = [[LeftTableViewController alloc] initWithStyle:UITableViewStylePlain]; LeftNavigationController *leftnavigationcontroller = [[LeftNavigationController alloc] initWithRootViewController:lefttableviewcontroller]; RightViewController *rightviewcontroller = [[RightViewControlleralloc] initWithNibName:nil bundle:nil]; RightNavigationController *rightnavigationcontroller = [[RightNavigationController alloc] initWithRootViewController:rightviewcontroller ]; MainSplitViewController *mainsplitviewcontroller = [[MainSplitViewController alloc] init]; mainsplitviewcontroller.viewControllers = [NSArray arrayWithObjects:leftnavigationcontroller,rightnavigationcontroller,nil]; [self.view addSubview:mainsplitviewcontroller.view]; これで、最後の addSubviewしている箇所を [self.navigationController pushViewController:mainsplitviewcontroller animated:YES]; と書き換えれば、Navigation Baseed アプリにも Split Viewが表示されるのでは? と考えたのですが、エラーも出ずにスルーされます。 ちなみに、Split View関連のソースをコピーして、別プロジェクトでsubViewとして表示されるので、 Split View自体のコードは正そうです。 悪い箇所を教えていただけますでしょうか。

  • iPhone IBを使用しないでUITabBarControllerを

    iPhone IBを使用しないでUITabBarControllerを実装 - (void)applicationDidFinishLaunching:(UIApplication *)application { window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // UIViewControllerを継承したクラス page1Controller = [[Page1Controller alloc] initWithNibName:nil bundle:nil]; page2Controller = [[Page2Controller alloc] initWithNibName:nil bundle:nil]; // 質問1 tabBarController = [[UITabBarController alloc] initWithNibName:nil bundle:nil]; [tabBarController setViewControllers:[NSArray arrayWithObjects:page1Controller, page2Controller, nil] animated:NO];  // 質問2 [window addSubview:tabBarController.view]; tabBarController.selectedIndex = 1; } 上記プログラムなのですが、 質問1.UITabBarControllerのsetViewControllersメソッドを利用して、     UIViewControllerのインスタンスをセットしているのですが、     setViewControllersメソッドは、     UITabBarControllerのプロパティviewControllersに     値をセットするためのセッターなのでしょうか? 質問2.[window addSubview:tabBarController.view]のviewは、     UITabBarControllerが継承しているUIViewControllerの     view(ゲッター)なのでしょうか? 上記の流れで、UITabBarControllerが、UIVeiwControllerを集約?しているので、 (@property(nonatomic, copy) NSArray *viewControllersとUITabBarControllerのヘルプに明記しているので) WindowのaddSubViewにセットするのは、UITabBarControllerのUIViewControllerのviewじゃないのかな? と初心者ながらの疑問です。 継承などの理解不足があると思いますが、ご教授の程お願いいたします

  • Xcodeで子のViewから親の変数を変更する

    こんにちは 現在Xcodeでの作業をしています。 画面の遷移の際に現在は (親から子どもへの値を渡す場合<遷移する場合>) ViewcontrollerA *svc = [[ViewcontrollerA alloc] init]; svc->hogehoge = 1; //値などを入れる場合 [self presentModalViewController:svc animated:yes]; [self.parentViewController dissmissModalViewControllerAnimated:YES]; と値を入れているのですが、 逆に上記のAという子どもの(インスタンス内)から親の変数をいじるにはどうすればいいですか? super->parenthogehoge =1 みたいにできればいいのですが、これだとうまくいかなくて・・・。 よろしくお願い致します。

  • 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]; }

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

    iPhoneアプリにディレクトリ階層を管理し、テーブルビューに表示する機能を実装中です。 パスの後ろに、"/○○○(ディレクトリ名)"という文字列を足して指定のディレクトリのパスを取得し中のファイルやフォルダの一覧を取得するという手法を用いています。 次のディレクトリに進む分には問題ないのですが、元のフォルダに戻るときに問題が生じてしまいます。 セルをタップすることで元のパスの後ろに選択したフォルダの名前を足していますが、ナビゲーションコントローラーで戻る際にパスの後ろに足されたフォルダ名を取り除かなくてはなりません。 もちろん戻るボタンが押されたことを検知するコードを調べたのですが、 -(void) viewWillDisappear:(BOOL)animated { if ([self.navigationController.viewControllers indexOfObject:self]==NSNotFound) { //ここでパスから文字列を取り除く } [super viewWillDisappear:animated]; } これではルートフォルダ→次のフォルダの間でしか検知されません。僕がやりたいのはルートフォルダ→次のフォルダ→次のフォルダ→・・・とすべてのフォルダ間の戻るボタンの検知をしたいのです。 didSelectRowAtIndexPathメソッドに UITableViewController *nextDir = [[UITableViewController alloc] init]; nextDir.tableView.delegate = self; nextDir.tableVIew.dataSourse = self; と記述することで、ストーリーボードにいくつもコントローラーを置かずにテーブルビューにディレクトリの内容を表示しています。 自前のコントローラー→nextDir間の戻るボタン検知は先ほど乗せたコードで検知できましたが、nextDir→nextDir間の戻るボタン検知はどうすればいいでしょうか? 簡単ですが説明図を作ってみました。わかりにくかったらすみません。

  • iOSアプリ起動時にビューを移す方法

    iOSアプリ開発初心者です。 初めてアプリを起動するときに、ビューを"passtest"に移したいのですが、以下のコードを書いたんですが、動作しません。メインコントローラの.mファイル((void)viewDidLoadメソッドの中で)で書きました。 int firstvalue = 1; if (firstvalue==1) { passtest *controller = [[passtest alloc] initWithNibName:@"passtest" bundle:nil]; controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal; [self presentModalViewController:controller animated:YES]; [controller release]; } IBActionにしてアクションをボタンに割り当てれば、問題なくビューを移せます。 起動時にどうやってビューを移すことができるのでしょうか? iOSアプリに詳しい方がいらっしゃいましたら、ご回答をよろしくお願いします。

専門家に質問してみよう