UISearchController не отображает панель навигации при повороте

Я реализовал UISearchController, и он отлично работает, кроме...

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

Однако, когда я поворачиваю телефон обратно в портретный режим (все еще выбранный в области поиска), я получаю следующий вид.

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

self.venueSearchController = [[UISearchController alloc] initWithSearchResultsController:nil];
self.venueSearchController.searchResultsUpdater = self;
self.venueSearchController.searchBar.delegate = self;
self.venueSearchController.dimsBackgroundDuringPresentation = NO;
self.venueSearchController.hidesNavigationBarDuringPresentation = YES;
self.venueSearchController.searchBar.frame = CGRectMake(self.venueSearchController.searchBar.frame.origin.x, self.venueSearchController.searchBar.frame.origin.y, self.venueSearchController.searchBar.frame.size.width, 44.0);

self.definesPresentationContext = YES;

self.navigationController.navigationBar.translucent = YES;
self.venueSearchController.searchBar.translucent = YES;

self.tableView.tableHeaderView = self.venueSearchController.searchBar;

4 ответа

Решение

Похоже, UISearchController забывает сбросить кадр searchBar когда строка состояния появляется снова. Я думаю, что это, вероятно, ошибка в UISearchController; там, кажется, некоторые из перечисленных в радаре. Кажется, что суперпредставление панели поиска (которое является внутренним для UISearchController) заканчивается с неправильной высотой. Это неприятно, поскольку решение, таким образом, включает в себя доступ к иерархии представлений searchController, которую Apple может изменить... вы можете добавить проверку версии iOS, чтобы она работала только для указанных версий.

Если вы добавите приведенный ниже код в свой контроллер представления, он будет вызываться при изменении коллекции признаков. Он проверяет, чтобы увидеть a) контроллер поиска активен, b) statusBar не скрыт и c) searchBar origin-y равен 0, и если это так, он увеличивает высоту суперпредставления на высоту statusBar, который перемещается панель поиска вниз.

override func traitCollectionDidChange(previousTraitCollection: UITraitCollection?) {
    let app = UIApplication.sharedApplication()
    if searchController!.active && !app.statusBarHidden && searchController?.searchBar.frame.origin.y == 0 {
        if let container = self.searchController?.searchBar.superview {
            container.frame = CGRectMake(container.frame.origin.x, container.frame.origin.y, container.frame.size.width, container.frame.size.height + app.statusBarFrame.height)
        }
    }
}

Цель С

- (void) traitCollectionDidChange: (UITraitCollection *) previousTraitCollection {

    [super traitCollectionDidChange: previousTraitCollection];

    if(self.venueSearchController.active && ![UIApplication sharedApplication].statusBarHidden && self.venueSearchController.searchBar.frame.origin.y == 0)
    {
        UIView *container = self.venueSearchController.searchBar.superview;

        container.frame = CGRectMake(container.frame.origin.x, container.frame.origin.y, container.frame.size.width, container.frame.size.height + [UIApplication sharedApplication].statusBarFrame.size.height);
    }
}

Возможно, вам придется реализовать UIBarPositioningDelegate на ваш взгляд контроллер.

self.venueSearchController.searchBar.delegate = self;

Панель поиска ищет ответ от своего делегата.

@protocol UISearchBarDelegate <UIBarPositioningDelegate> 

Добавьте следующее к вашему self (Я предполагаю, что это ViewController)

#pragma mark - <UIBarPositioningDelegate>

// Make sure NavigationBar is properly top-aligned to Status bar
- (UIBarPosition)positionForBar:(id<UIBarPositioning>)bar
{
    if (bar == self.venueSearchController.searchBar) {
        return UIBarPositionTopAttached;
    }
    else { // Handle other cases
        return UIBarPositionAny;
    }
}

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

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

Это должно гарантировать, что таблица всегда остается ниже строки состояния и будет по-прежнему правильно перемещаться, когда панель навигации возвращается и возвращается.

Смотрите это обсуждение: iOS 7: UITableView отображается под строкой состояния

I've faced a similar issue with UISearchController using it with navigationItem. It looks differently, but caused by the very same problem: UISearchController does NOT update searchBar frame when status bar reappears.

But instead of manually adjusting frames of searchBar's view hierarchy you should simply force it to update layout by toggling hidesNavigationBarDuringPresentation back and forth during rotation either in traitCollectionDidChange or viewWillTransition(to size: CGSize, with cooridnator: UIViewControllerTransitionCoordinator):

So the fix would look like this:

 override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraitCollection)
    if #available(iOS 11, *) {
        navigationItem.hidesSearchBarWhenScrolling.toggle()
        navigationItem.hidesSearchBarWhenScrolling.toggle()
    }
}

And here is how the original issue looks like.

Then rotating and got this:

Я временно "исправил" это, отключив "Скрыть строку состояния" в настройках.

Другие вопросы по тегам