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. Идеи?

Ответ 1

Когда вы представляете контроллер модального представления, он не использует никаких существующих навигационных контроллеров или навигационных панелей. Если вы хотите отобразить панель навигации, вам нужно добавить панель навигации в качестве подсмотра вашего модального представления и представить ее так, как вы делаете.

Если вы хотите представить контроллер модального вида с функциями навигации, вам нужно вместо этого представить модальный контроллер навигации, содержащий ваш контроллер представления подробностей, например:

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

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

Ваш модальный контроллер будет управлять своим собственным стекем навигации.

Ответ 2

Вот один из способов отображения панели навигации для тех, кто использует раскадровки, предложенные Apple Tutorial on Storyboard.

Поскольку контроллер модального представления не добавляется в стек навигации, он не получает панель навигации от контроллера навигации контроллера табличного представления. Чтобы дать контроллеру вида навигационную панель, когда она представлена ​​модально, встройте ее в свой собственный контроллер навигации.

  • В представлении схемы выберите "Просмотр контроллера".
  • С выбранным контроллером просмотра выберите "Редактор" > "Вставить" > "Контроллер навигации".

Ответ 3

На 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];
}

Ответ 4

Я хочу поделиться тем, как принятое решение можно использовать в проектах с раскадными версиями:

Простой подход заключается в том, чтобы поставить пульт управления навигацией раскадровки перед VC, который должен быть представлен модально, поэтому отношения выглядят следующим образом:

(Presenter VC) → представляет модально → (навигационный контроллер с контроллером, который будет представлен в качестве его корня).

Мы пробовали этот подход на некоторое время и заметили, что наши раскадровки становятся "загрязненными" большим количеством таких промежуточных навигационных контроллеров, когда каждый! из них используется исключительно для одного! презентация какого-либо другого контроллера, который мы хотим представить с помощью навигационной панели.

Нашим текущим решением является инкапсуляция кода из принятого ответа в пользовательский сегмент:

#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

Я надеюсь, что этот ответ будет полезен для людей, которым нравится избегать ненужного дублирования в своих раскадрах приложений.

Ответ 5

Если вам нужен только NavigationBar, вы можете добавить экземпляр UINavigationBar и назначить ему BarItems.

Ответ 6

Я просто хотел добавить что-то к тому, что сказал @Scott. Его ответ, безусловно, самый простой и наиболее приемлемый способ сделать это сейчас с помощью раскадровки, iOS 7 и 8... (и вскоре, 9).

Определенное добавление контроллера просмотра в раскадровку и его внедрение, как описано в @Scott, - правильный путь.

Затем просто добавьте segue, перетащив управление с контроллера исходного вида на объект (тот, который вы хотите показать модально), выберите "Present Modally", когда появится небольшое представление с выбором типа segue. Наверное, хорошо дать ему имя (в приведенном ниже примере я использую "presentMyModalViewController" ).

Одна вещь, в которой я нуждалась, отсутствовала, это случай @Scott - это когда вы хотите передать некоторые данные этому модульно представленному контроллеру представления, встроенному в контроллер навигации.

Если вы захватите segue.destinationViewController, это будет UINavigationController, а не контроллер, встроенный в UINavigationController.

Итак, чтобы получить встроенный контроллер просмотра внутри контроллера навигации, вот что я сделал:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([segue.identifier isEqualToString:@"presentMyModalViewController"]) {
        // This could be collapsed, but it a little easier to see
        // what 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 "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!";
    }
}

Надеюсь, это поможет!