Подтвердить что ты не робот

UISearchBar не будет отвечать в UISplitviewController Master

У меня довольно стандартная настройка UITableview в качестве главного контроллера в UISplitviewController, универсальном iOS9 приложении.

Опять же, стандартный тариф, я вставил UISearchBar в качестве заголовка таблицы.

self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
self.searchController.searchResultsUpdater = self;
self.searchController.dimsBackgroundDuringPresentation = NO;
self.searchController.hidesNavigationBarDuringPresentation = NO;

[self.searchController.searchBar sizeToFit];
self.tableView.tableHeaderView = self.searchController.searchBar;

self.definesPresentationContext = YES;

Не нужно показывать остальную часть моего кода, искать и все работать как ожидалось, на iPhone. Моя проблема в том, что панель поиска никогда не получает фокуса или присутствует клавиатура при запуске на iPad. Никакой ответ, кажется, не получает прикосновений. Даже не реагирует на программную попытку becomeFirstResponder.

Ничего не происходит.

Панель поиска видна и размещена соответствующим образом, нет проблем с подслоем или наложением.

Он отлично работает на iPhone. Получает касание, представляет клавиатуру, выполняет поиск. Предположительно, существует критическая разница в представлении, когда UISplitviewController рушится. С часами поиска, пролистывая документацию и каждый обучаемый, с которым я сталкиваюсь, я не нашел подобного опыта, который удивляет.

Дополнительное примечание. Если я использую многозадачность для сокращения раздвоенного вида, чтобы свернуть на iPad, панель поиска работает так же, как и на iPhone. Это определенно связано с сложенным состоянием вида split.

ОБНОВЛЕНИЕ: (ближе)

После дальнейших экспериментов я обнаружил, что панель поиска работает на iPad, если вы запускаете приложение в ландшафте. В портретном режиме мой основной контроллер скрыт. Он перемещается по выбору displayModeButtonItem, который установлен в leftBarButtonItem подробного контроллера. То есть, когда searchBar ломается и больше не будет реагировать на касания.

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

Я попытался переместить definesPresentationContext в метод viewWillAppear главного контроллера, но это не повлияло.

Дальнейшее обновление:

Еще одно неожиданное обстоятельство заключается в том, что никаких проблем с панелью поиска вообще нет на iPhone 6plus. Работает независимо от ориентации, рушится или нет и не имеет значения, в каком состоянии она начинается. Я ожидаю, что это будет так же, как iPad, когда в альбомной ориентации. Полностью работает на iPhone.

Я до сих пор не понял этого. Моя последняя попытка исправить, я переместил всю инициализацию контроллера поиска в метод viewDidLayoutSubviews. Никаких изменений.

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

Пример проекта, загруженного в GitHub: Репозиторий Github

ПРИМЕЧАНИЕ. Не было проблем, пока я не добавил в проект мои методы UISplitview Delegate. Я хотел бы сразу добавить это к моему вопросу, поэтому я даже не пытался понять, как эти методы делегирования влияют на панель поиска, но, очевидно, проблема там создается где-то.

Обновление:

Я попробовал еще несколько вариантов без успеха.

  • Переместить панель поиска в заголовок раздела. Нет радости.
  • Поместите панель поиска в UIView в виде содержимого. Нет радости.
  • Удалить панель поиска при исчезновении, снова включить. Нет радости.
  • Манипулируйте размер рамки панели поиска, чтобы убедиться, что она не обрезана. Нет радости.

Я также посмотрел на иерархию представлений в профилировщике, панель поиска - верхний уровень, не покрытый чем-либо еще.

Заключительная обертка:

@tomSwift обходное решение действительно исправило мою проблему на iPad. При дальнейшем тестировании я обнаружил, что он нарушил мой интерфейс iPhone. Предположительно, это больше проблема с моей собственной настройкой и временем создания контроллеров Master/Detail View. Казалось бы, некоторые важные объекты больше не были созданы вовремя, поскольку, возможно, контроллер подробного представления еще не существовал. Я ткнул, чтобы исправить, переместив критические элементы в App Delegate, но это стало громоздким, и я не мог его легко сузить, поэтому я взломал исправление с помощью

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
    splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModeAllVisible;
}

Более элегантное решение, скорее всего, будет, но это заняло достаточно моего времени. Сейчас все работает. Радиолокационная заявка-28304096

4b9b3361

Ответ 1

Это явно ошибка в UISplitViewController и/или UISearchController. Конечно, подайте радар с Apple и прикрепите образец кода.

Я думаю, что ошибка включает UISplitViewController.displayMode UISplitViewControllerDisplayModeAutomatic. Когда я меняю preferredDisplayMode на UISplitViewControllerDisplayModeAllVisible, тогда все начинает работать:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
    UINavigationController *navigationController = [splitViewController.viewControllers lastObject];
    navigationController.topViewController.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem;
    splitViewController.delegate = self;
    splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModeAllVisible;

    return YES;
}

Главное, что это изменение - это макет по умолчанию для портрета на iPad, который, как я понимаю, может быть не идеальным. Я также играл с настройкой preferredDisplayMode на UISplitViewControllerDisplayModeAllVisible, а затем вернул его к UISplitViewControllerDisplayModeAutomatic; это отлично работало до тех пор, пока экранная ориентация не изменилась - тогда все это снова сломалось. Возможно, вам удастся пойти дальше по этому пути.

Я также сделал следующее дополнение в AppDelegate, чтобы заставить контроллер поиска деактивироваться при изменении displayMode. (Я также должен был публиковать свойство searchController публично в MasterViewController).

- (void)splitViewController:(UISplitViewController *)svc willChangeToDisplayMode:(UISplitViewControllerDisplayMode)displayMode {

    UINavigationController *navigationController = [svc.viewControllers firstObject];
    MasterViewController* mvc = (MasterViewController*) navigationController.topViewController;
    [mvc.searchController setActive: NO];
}

Ответ 2

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

Используйте этот метод делегата для создания уведомления:

- (void)splitViewController:(UISplitViewController *)svc willChangeToDisplayMode:(UISplitViewControllerDisplayMode)displayMode {
    NSLog(@"WILL CHANGE TO DISPLAY MODE: %ld", (long)displayMode);

    NSNumber *displayNumber = [NSNumber numberWithInteger:displayMode];
    NSDictionary *userInfo = @{ @"displayMode": displayNumber };
    NSNotification *modeChangedNotif = [NSNotification notificationWithName:@"modeChanged" object:nil userInfo:userInfo];
    [[NSNotificationCenter defaultCenter] postNotification:modeChangedNotif];
}

Затем в вашем MasterViewController вы можете сделать это в viewDidLoad:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(modeChanged) name:@"modeChanged" object:nil];

В этом методе вы можете сделать чек для определенного перечисления displayMode, но ради получения его работы я просто сделал:

- (void) modeChanged {
    [self.searchController setActive:YES];
}