UISearchController в UIViewController

Я хочу создать аналогичную функциональность для приложения Apple maps в Swift. В любом случае необходимо интегрировать UISearchController в обычное представление (т.е.: не UITableView). Сбрасывание одного из них через Storyboard приводит к сбою после нажатия внутри подключенной панели поиска. Или я могу достичь этого результата с помощью UITableView?

Ответ 1

Я добавил панель поиска и поисковый контроллер в моем диспетчере просмотра в раскадровке. Контроллер представления содержит только панель поиска и контроллер отображения поиска и не имеет собственного TableView. Когда вы добавляете панель поиска в свой контроллер просмотра, он устанавливает ваш контроллер представления, поскольку он делегирует автоматически.

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

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

tableView: numberOfRowsInSection:]: непризнанный селектор, отправленный в экземпляр 0x7fbf63449660 *** Завершение приложения из-за неперехваченного исключения "NSInvalidArgumentException"

Если вы видите, ошибка указана в методе numberOfRowsInSection.

Измените определение контроллера просмотра с помощью

class ViewController: UIViewController

к

class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource

и реализовать необходимые методы, которые: -

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    return UITableViewCell()
}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 0
}

Я только что добавил значения возвращаемого значения по умолчанию в приведенных выше методах.

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

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

Ответ 2

Если вы хотите использовать UISearchController с не UITableView, вот как я это сделал.

Так как UISearchController не поддерживается (пока!), поддерживаемым IB, вам не нужно что-то добавить в нем, например UISearchBar.

@interface UIViewControllerSubclass () <UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate, UISearchControllerDelegate, UISearchResultsUpdating>

@property (strong, nonatomic) UISearchController *searchController;

@end

@implementation UIViewControllerSubclass

- (void)viewDidLoad
{        
    [super viewDidLoad];
    // Do any custom init from here...

    // Create a UITableViewController to present search results since the actual view controller is not a subclass of UITableViewController in this case
    UITableViewController *searchResultsController = [[UITableViewController alloc] init];

    // Init UISearchController with the search results controller
    self.searchController = [[UISearchController alloc] initWithSearchResultsController:searchResultsController];

    // Link the search controller
    self.searchController.searchResultsUpdater = self;

    // This is obviously needed because the search bar will be contained in the navigation bar
    self.searchController.hidesNavigationBarDuringPresentation = NO;

    // Required (?) to set place a search bar in a navigation bar
    self.searchController.searchBar.searchBarStyle = UISearchBarStyleMinimal;

    // This is where you set the search bar in the navigation bar, instead of using table view header ...
    self.navigationItem.titleView = self.searchController.searchBar;

    // To ensure search results controller is presented in the current view controller
    self.definesPresentationContext = YES;

    // Setting delegates and other stuff
    searchResultsController.tableView.dataSource = self;
    searchResultsController.tableView.delegate = self;
    self.searchController.delegate = self;
    self.searchController.dimsBackgroundDuringPresentation = NO;
    self.searchController.searchBar.delegate = self;        
}

@end

Надеюсь, что этого достаточно: -)

Тогда, конечно, вам нужно, по крайней мере, реализовать UITableViewDelegate, UITableViewDataSource, методы UISearchResultsUpdater.

Наслаждайтесь!

Ответ 3

Попытка выяснить UISearchController себя. Установка его на titleView удобна, но на одной из моих страниц мне пришлось поставить searchBar в верхней части UIViewController:

// Add a normal View into the Storyboard.
// Set constraints:
// - height: 44
// - leading and trailing so that it spans the width of the page
// - vertical position can be anywhere based on your requirements, like near the top
@IBOutlet weak var searchContainerView: UIView!

var searchResultsController = UISearchController()

override func viewDidLoad() {
    // TODO: set the searchResultsController to something
    let controller = UISearchController(searchResultsController: nil)
    // have the search bar span the width of the screen
    controller.searchBar.sizeToFit()
    // add search bar to empty View
    searchContainerView.addSubview(controller.searchBar)
    searchResultsController = controller
}

UPDATE:

После реализации UISearchController в проекте или двух, я обнаружил, что тяготеет к подходу @adauguet к встраиванию панели поиска в панель навигации.

Вот код в Swift. Одно отличие состоит в том, что он не устанавливает делегата searchBar, так как searchResultsUpdater уже прослушивает изменения текста.

override func viewDidLoad() {
    super.viewDidLoad()
//        locationManager.delegate = self
//        locationManager.desiredAccuracy = kCLLocationAccuracyBest
//        locationManager.requestWhenInUseAuthorization()
//        locationManager.requestLocation()
    let locationSearchTable = storyboard!.instantiateViewControllerWithIdentifier("LocationSearchTable") as! LocationSearchTable
    resultSearchController = UISearchController(searchResultsController: locationSearchTable)
    resultSearchController?.searchResultsUpdater = locationSearchTable
    let searchBar = resultSearchController!.searchBar
    searchBar.sizeToFit()
    searchBar.placeholder = "Search for places"
    navigationItem.titleView = resultSearchController?.searchBar
    resultSearchController?.hidesNavigationBarDuringPresentation = false
    resultSearchController?.dimsBackgroundDuringPresentation = true
    definesPresentationContext = true
}

Кроме того, я написал сообщение в блоге, которое создает проект с нуля, который использует UISearchController для отображения результатов поиска по карте. Он также делает другие вещи, которые вы можете захотеть в проекте карты, например, получить местоположение пользователя, вытащить булавки, разложить метки в однострочный адрес и создать кнопки выносок, которые доставят вас в Apple Maps для проезда.

http://www.thorntech.com/2016/01/how-to-search-for-location-using-apples-mapkit/

Сообщение в блоге довольно длинное, поэтому вот ссылка git repo, если вы просто хотите пропустить код:

https://github.com/ThornTechPublic/MapKitTutorial

Ответ 4

У меня возникли проблемы с преобразованием из SearchDisplayController в UIViewController в SearchController в ViewController, потому что реализация SearchController не такая интуитивная. Но вы можете просто добавить поисковика из самого SearchController в любое представление. Вы не можете установить ограничение, потому что панель поиска будет двигаться вверх, когда вы фокусируете/выбираете ее (если вы знаете, как установить ограничение для seachController.searchbar после добавления его в любое представление, LET ME KNOW!). Ниже я использую контрольный список, который я нашел очень важным/ценным при реализации SearchController в ViewController.

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

[self.searchBarPlaceHolderView addSubview:self.searchController.searchBar];

//вам нужно это, чтобы предотвратить отображение панели поиска при ее фокусировке/выборе. Вы хотите установить это значение НЕТ, если вы добавляете searchBar в заголовок заголовка панели навигации.

self.searchController.hidesNavigationBarDuringPresentation = YES;

//убедитесь, что вы установили это в свой viewController

self.extendedLayoutIncludesOpaqueBars = true;
self.definesPresentationContext = YES;

//вам также нужно предоставить контроллеру поиска tableViewController, который можно отобразить. Вы также можете сделать только self.searchResultsController = [[UITableView alloc] init] для общей версии.

self.searchResultsController = (UITableViewController *)[ [UIStoryboard storyboardWithName:@"Main" bundle:nil] instantiateViewControllerWithIdentifier:@"searchResultsTableViewController"];

self.searchResultsController.tableView.dataSource = self;
self.searchResultsController.tableView.delegate = self;
self.searchResultsController.definesPresentationContext = NO;
self.searchController = [[UISearchController alloc] initWithSearchResultsController:self.searchResultsController];