iPhone: Показать модальный UITableViewController с панелью навигации


87

Я показываю модальное представление, которое является 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. Идеи?

Ответы:


146

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

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

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

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

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


Спасибо, я ценю объяснение, поэтому я знаю, что сделал не так.
— Ник Хаббард

1
Если вы используете раскадровку, для этого не требуется никакого кодирования. Хорошее решение!
— Jelle

36

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

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

  1. В представлении структуры выберите View Controller.
  2. Выделив контроллер представления, выберите «Редактор»> «Вставить в»> «Контроллер навигации».

Убедитесь, что вы добавили модальный переход к контроллеру навигации, а не к TableViewController
— bickster

В случае страницы редактирования профиля пользователя Twitter. Это модально представленный UITableViewController с кнопками DONE и CANCEL вверху. Этот ответ не имеет семантического смысла в этой ситуации, потому что не происходит навигации.
— Уильям Энтрикен,

17

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

Шов - отличный способ делать вещи. но когда я тестирую его на Static UITableViewController, я больше не могу прокручивать табличное представление. есть идеи почему?
— Thomas Besnehard

2
в настоящее время вам было бы лучше встроить его в контроллер навигации.
— Malhal

Это хорошее решение, но одна небольшая проблема заключается в том, что при прокрутке заголовки ячеек отображаются поверх панели навигации.
— Али

Решил, добавив [self.view bringSubviewToFront:self.navigationBar];в конце -(void)layoutNavigationBar.
— Али

7

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

Простой подход состоит в том, чтобы вставить пустой навигационный контроллер раскадровки перед 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 как:

Ведущая ВК -> Ведущая ВК

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


5

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


Это зависит от ViewController: я думаю, вы не можете добавить UINavigationBar к UITableViewController, не так ли?
— Тобиас

В IB перейдите в Editor -> Embed in Navigation Controller, и у вас будет панель навигации. Перетащите и добавьте к нему BarButtonItems.
— AmitaiB

5

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

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

Затем просто добавьте переход, перетащив элемент управления из исходного контроллера представления в целевой (тот, который вы хотите показать модально), выберите «Представить модально», когда появится небольшое представление с вариантами выбора типа перехода. Вероятно, неплохо было бы дать ему имя (в примере ниже я использую "presentMyModalViewController").

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

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

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

- (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!";
    }
}

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.