IOS 13 странный разрыв контроллера поиска

Когда я запускаю приложение на iOS 13 beta 6 и Xcode 11 beta 5, я сталкиваюсь со странным пробелом при представлении контроллера представления результатов поиска:

enter image description here

Здесь немного о том, как это настроить:

let searchResultsController = BLSearchResultsController()

let ret = UISearchController(searchResultsController: searchResultsController)
ret.searchResultsUpdater = self
ret.delegate = self
ret.searchBar.delegate = self;
ret.searchBar.autocapitalizationType = .none
ret.searchBar.placeholder = NSLocalizedString("SearchMsg", comment: "")
        ret.searchBar.enablesReturnKeyAutomatically = true

if #available(iOS 13.0, *) {
    ret.searchBar.showsScopeBar = false
    ret.searchBar.backgroundColor = .white

    let searchTextField = ret.searchBar.searchTextField
    searchTextField.font = UIFont.tuttiRegularFont(16)
    searchTextField.accessibilityIdentifier = "Main Search Field"
    if let searchImageView = searchTextField.leftView as? UIImageView {
        searchImageView.image = UIImage(named: "home-search-icon")
     }
}

Контроллер поиска результатов является обычным UITableViewController и только что добавлен в navigationItem.searchController. Там нет причудливого кода презентации. При сборке на последнем живом Xcode и запуске на устройстве iOS 11/12 эта проблема не возникает, что позволяет мне полагать, что некоторые базовые изменения iOS 13 могут вызывать этот сбой.

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

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

Кто-нибудь сталкивался с этой проблемой, и ей повезло, исправляя ее?

Ответы

Ответ 1

Настройка

extendedLayoutIncludesOpaqueBars = true

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

Ответ 2

У нас возникла та же проблема, и было решено установить Under Opaque Bars (поскольку мы используем непрозрачные бары) Under Opaque Bars

Мы уже проверили Top и Bottom, добавив третий, переместил контроллер результатов поиска в правильное местоположение.

Ответ 3

К вашему сведению Я подал отчет об ошибке в Apple - в соответствии с презентацией WWDC, которая описывает недавно переписанный SearchController и некоторые другие обновления пользовательского интерфейса, похоже, что архитектура SearchController была переписана с нуля вверх. Я не могу поверить, что этот пробел, который мы наблюдаем, является ожидаемым поведением - я потратил большую часть двух дней, пытаясь обойти это, и я больше не буду беспокоиться - приложение моего магазина приложений Это бесплатное приложение, которое имеет несколько пользователей, и я не смог посвятить время отслеживанию изменений/поведения в API во время бета-тестирования. Я немного устал от того, что Apple делает подобные вещи ежегодно.

Ответ 4

extendedLayoutIncludesOpaqueBars = true в некоторой степени помог.

Наряду с этим мне пришлось обновить

navigationController?.navigationBar.prefersLargeTitles = false

когда мы начинаем поиск и устанавливаем его обратно в true, когда строка поиска закрывается.

Ответ 5

Вы должны установить для вашего navigationBar.standardAppearance объект UINavigationBarAppearance, описывающий белый фон.

if #available(iOS 13.0, *) {
        let appearance = UINavigationBarAppearance()
        appearance.backgroundColor = .white
        self.navigationController?.navigationBar.standardAppearance = appearance
}

Ответ 6

Наконец пройти через жесткий Просто чтобы первый контроллер содержал UISearchController, чтобы иметь полупрозрачную панель навигации. Работай для меня отлично!

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        self.navigationController?.navigationBar.isTranslucent = true
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillAppear(animated)

        self.navigationController?.navigationBar.isTranslucent = false
    }

Ответ 7

Я наконец решил эту проблему, заменив UISearchController на простой (r) UISearchBar.

Возможно, это не тот ответ, который вы хотели услышать, но UISsearchController уже был беспорядок на iOS12, тот же код на iOS13 работает, но дает ужасные артефакты пользовательского интерфейса. Например, исчезновение или перекрытие панели поиска с заголовком, пробел между строкой поиска и первым элементом таблицы или скрытие первого элемента списка под кнопками области действия... Все разные проблемы между iOS12 и 13, но никогда не выглядят хорошо.

So overall я spent 6 hours trying to fix the searchcontroller, failed, then spent 30 mins migrating to the Searchbar.

В общем, я потратил 6 часов, пытаясь починить контроллер поиска, потерпел неудачу, а затем потратил 30 минут на миграцию на панель поиска. Я добавил UISearchBar, просто используя Interface Builder в Xcode10.3. Для рефакторинга в основном мне пришлось просто заменить searchController.searchBar.xx на searchBar.xx. Основное усилие было переопределить UISeachBarDelegates. Просто чтобы показывать только кнопки и кнопки отмены, пока пользователь выполняет поиск, и удалять их потом. Код ниже дает хороший обзор того, что я сделал:

class MasterViewController: UITableViewController, NSFetchedResultsControllerDelegate {

  var fetchedItemsController: NSFetchedResultsController<Item>! = NSFetchedResultsController()

  @IBOutlet weak var searchBar: UISearchBar! //hooked up to IB
  //GONE IS: let searchController = UISearchController(searchResultsController: nil)


  override func viewDidLoad() {
    super.viewDidLoad()

    initializeFetchedResultsControllerForItems()

    //Enable search controller
    searchBar.scopeButtonTitles = [NSLocalizedString("Name", comment: ""),
                                   NSLocalizedString("Birthdate", comment: ""),
                                   NSLocalizedString("Employer", comment: "")    ]
    searchBar.placeholder = NSLocalizedString("Search", comment: "")
    searchBar.delegate = self
    searchBar.showsScopeBar = false
    searchBar.showsCancelButton = false

    tableView.contentInsetAdjustmentBehavior = .automatic
    self.tableView.tableHeaderView = searchBar //add the searchbar as tableheader view

    self.initializeFetchedResultsControllerForItems()

  }

  // MARK: - Data loading from CoreData
  private func initializeFetchedResultsControllerForItems(searchText: String = "", scopeIndex: Int = 0) {
    //print("FETCH RESULTS WITH FILTER: \(searchText) en SCOPE: \(scopeIndex)")
    //Do whatever searches you need to do to update the FetchedResultsController
    //..
    self.tableView.reloadData()
  }
}

extension MasterViewController: UISearchBarDelegate {  //the delegates for the searchbar
  func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
    searchBar.showsScopeBar = true  //show the scopebar when users adds text to searchbar
    searchBar.showsCancelButton = true //also show the cancel button
    searchBar.sizeToFit()
    self.tableView.reloadData() //since the scopebar is there, the table needs to move a bit down

  }
  func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
  }
  func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    initializeFetchedResultsControllerForItems(searchText: searchBar.text!, scopeIndex: searchBar.selectedScopeButtonIndex)
  }
  func searchBar(_ searchBar: UISearchBar, selectedScopeButtonIndexDidChange selectedScope: Int) {
    switch (selectedScope) {
    case 0: searchBar.placeholder = NSLocalizedString("Seach on name", comment: "")
    case 1: searchBar.placeholder = NSLocalizedString("Search on birthdate", comment: "")
    case 2: searchBar.placeholder = NSLocalizedString("Search on employer", comment: "")
    default: searchBar.placeholder = NSLocalizedString("Search", comment: "")

    searchBar.showsScopeBar = true
    searchBar.sizeToFit()
    }

    initializeFetchedResultsControllerForItems(searchText: searchBar.text!, scopeIndex: selectedScope)
  }
  func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
    searchBar.placeholder = NSLocalizedString("Search", comment: "")
    searchBar.showsScopeBar = false
    searchBar.showsCancelButton = false
    searchBar.endEditing(true)
    searchBar.text = ""
    searchBar.sizeToFit()
    initializeFetchedResultsControllerForItems(searchText: searchBar.text!, scopeIndex: searchBar.selectedScopeButtonIndex)
  }
}

Ответ 8

  1. Как уже упоминалось в ответах выше, установите флажок "Расширить края под непрозрачными полосами" как "Вкл." Для UIViewController, который представляет результаты поиска. Для меня этого было недостаточно, потому что я использую НЕ полупрозрачную панель навигации.
  2. Поэтому я добавил следующую реализацию для методов UISearchControllerDelegate:
    - (void)willPresentSearchController:(UISearchController *)searchController
    {
        if (@available(iOS 13.0, *))
        {
            self.navigationController.navigationBar.translucent = YES;
        }
    }

    - (void)willDismissSearchController:(UISearchController *)searchController
    {
        if (@available(iOS 13.0, *))
        {
            self.navigationController.navigationBar.translucent = NO;
        }
    }

Ответ 9

Просто принесу мое решение. В моем случае:

edgesForExtendedLayout = .all

на UIViewController, который содержит UISearchController работал.

//MARK: - Properties
var presenter: ExplorePresenting?
var searchController: UISearchController?
var searchUpdater: SearchUpdating?


//MARK: - Lifecycle methods
public override func viewDidLoad() {
    super.viewDidLoad()

    headerTitle = "explore".localised
    tableView.allowsSelection = false
    registerCell(cellClass: ExploreTableViewCell.self, with: tableView)

    if let searchController = searchController {

        searchController.searchBar.delegate = self
        searchController.searchResultsUpdater = self
        searchController.obscuresBackgroundDuringPresentation = false
        searchController.searchBar.placeholder = "explore_search_placeholder".localised

        definesPresentationContext = true
        navigationItem.hidesSearchBarWhenScrolling = false
        navigationItem.searchController = searchController
        edgesForExtendedLayout = .all

    }

    presenter?.viewReady()

}