web-dev-qa-db-ja.com

iPhone:モーダルUITableViewControllerをナビゲーションバーで表示する

UITableViewControllerクラスであるモーダルビューを表示しています。何らかの理由で、表示したときにナビゲーションバーが表示されません。ここに私のコードがあります:

SettingsCreateAccount *detailViewController = [[SettingsCreateAccount alloc] initWithStyle:UITableViewStyleGrouped];
    detailViewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
    detailViewController.navigationController.navigationBarHidden = NO;
    [self.navigationController presentModalViewController:detailViewController animated:YES];
    detailViewController = nil;
    [detailViewController release];

デフォルトで表示されると思いましたか?役立つ場合は、UITableViewControllerによって管理されるUINavigationControllerでもある別のクラスからこれを呼び出しています。アイデア?

86
Nic Hubbard

モーダルView Controllerを提示する場合、既存のNavigation ControllerまたはNavigation Barを使用しません。必要なのがナビゲーションバーを表示するだけであれば、ナビゲーションバーをモーダルビューのサブビューとして追加し、実行中に表示する必要があります。

ナビゲーション機能を備えたモーダルビューコントローラーを表示する場合は、代わりに、詳細ビューコントローラーを含むモーダルナビゲーションコントローラーを表示する必要があります。

SettingsCreateAccount *detailViewController = [[SettingsCreateAccount alloc] initWithStyle:UITableViewStyleGrouped];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:detailViewController];
[detailViewController release];

navController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentModalViewController:navController animated:YES];
[navController release];

モーダルコントローラーは、独自のナビゲーションスタックを管理します。

144
BoltClock

AppleのStoryboardのチュートリアル で提案されている、ストーリーボードを使用している人にナビゲーションバーを表示する方法の1つです。

モーダルView ControllerはNavigation Stackに追加されないため、Table View ControllerのNavigation ControllerからNavigation Barを取得しません。モーダルモードでView ControllerにNavigation Barを表示するには、独自のNavigation Controllerに埋め込みます。

  1. アウトラインビューで、[View Controller]を選択します。
  2. View Controllerを選択した状態で、[エディター]> [埋め込み]> [Navigation Controller]を選択します。
36
Scott

IOS 7では、モーダルビューコントローラーのナビゲーションバーにタイトルといくつかのボタンを表示するだけですか? UITableViewControllerでこの魔法を試してください:

// in the .h
@property (strong) UINavigationBar* navigationBar;

//in the .m
- (void)viewDidLoad {
    [super viewDidLoad];

    self.navigationItem.title = @"Awesome";
    self.navigationBar = [[UINavigationBar alloc] initWithFrame:CGRectZero];
    [self.view addSubview:_navigationBar];
    [self.navigationBar pushNavigationItem:self.navigationItem animated:NO];
}

-(void)layoutNavigationBar{
    self.navigationBar.frame = CGRectMake(0, self.tableView.contentOffset.y, self.tableView.frame.size.width, self.topLayoutGuide.length + 44);
    self.tableView.contentInset = UIEdgeInsetsMake(self.navigationBar.frame.size.height, 0, 0, 0);
}

-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
    //no need to call super
    [self layoutNavigationBar];
}

-(void)viewDidLayoutSubviews{
    [super viewDidLayoutSubviews];
    [self layoutNavigationBar];
}
17
malhal

ストーリーボードを使用したプロジェクトで受け入れられたソリューションをどのように使用できるかを共有したい:

シンプルなアプローチは、VC=の前にストーリーボードの空白のナビゲーションコントローラーを配置することです。

(Presenter VC)->モードで表示->(ルートとして表示されるコントローラーを持つナビゲーションコントローラー).

私たちはしばらくの間このアプローチを試しましたが、ストーリーボードは、それぞれがそのような多数の中間ナビゲーションコントローラーによって「汚染」されることに気付きました。それらのうちの1つは排他的に使用されます!ナビゲーションバーでモーダルに表示する他のコントローラーの表示。

現在のソリューションは、受け入れられた回答からカスタムセグエへのコードをカプセル化することです。

#import "ModalPresentationWithNavigationBarSegue.h"

@implementation ModalPresentationWithNavigationBarSegue

- (void)perform {
    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:self.destinationViewController];

    [self.sourceViewController presentViewController:navigationController animated:YES completion:nil];
}
@end

プロジェクトでこのセグエを使用することで、ストーリーボードに中間ナビゲーションコントローラーを作成しなくなり、次のようにこのModalPresentationWithNavigationBarSegueを使用します。

プレゼンターVC-> Presentee VC

この回答が、アプリのストーリーボードで不必要な重複を避けたい人に役立つことを願っています。

7

@Scottが言ったことに何かを追加したかっただけです。彼の答えは間違いなく、Storyboards、iOS 7および8(そしてすぐに9)を使って行う最も簡単で最も受け入れられた方法です。

間違いなく、StoryboardにView Controllerを追加し、@ Scottの説明に従ってそれを埋め込むのが正しい方法です。

次に、ソースビューコントローラーからターゲット(モーダルで表示したいもの)にコントロールドラッグしてセグエを追加し、セグエのタイプを選択できる小さなビューが表示されたら[プレゼントモーダル]を選択します。おそらく名前を付けるのも良いでしょう(以下の例では「presentMyModalViewController」を使用しています)。

不足していたことの1つは、@ Scottの場合です。NavigationControllerに組み込まれている、モーダルで提示されたView Controllerに実際にデータを渡したい場合です。

Segue.destinationViewControllerを取得すると、UINavigationControllerに埋め込まれたコントローラーではなく、UINavigationControllerになります。

だから、Navigation Controller内の組み込みView Controllerを取得するために、私がしたことは次のとおりです:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([segue.identifier isEqualToString:@"presentMyModalViewController"]) {
        // This could be collapsed, but it's a little easier to see
        // what's going on written out this way.

        // First get the destination view controller, which will be a UINavigationController
        UINavigationController *nvc = (UINavigationController *)segue.destinationViewController;

        // To get the view controller we're interested in, grab the navigation controller's "topViewController" property
        MyModalViewController *vc = (EmailReceiptViewController *)[nvc topViewController];

        // Now that we have the reference to our view controller, we can set its properties here:
        vc.myAwesomeProperty = @"awesome!";
    }
}

お役に立てれば!

5
Evan Stone

NavigationBarのみが必要な場合は、UINavigationBarのインスタンスを追加して、それにBarItemsを割り当てることができます。

5
xhan