我希望在 Swift 中创建与 Apple 地图应用程序类似的功能。无论如何将 UISearchController 集成到常规视图中(即:不是 UITableView)。在连接的搜索栏内单击后,通过 Storyboard 拖放一个会导致崩溃。或者有什么方法可以用 UITableView 实现这个结果?
4 回答
如果您想将 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's 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 方法。
享受!
试图弄清楚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
}
更新:
在实施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:
我在情节提要的视图控制器中添加了搜索栏和搜索显示控制器。视图控制器只包含搜索栏和搜索显示控制器,没有自己的 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 方法中过滤掉数据源并在上述两种方法中正确设置行数和单元格信息,它应该可以工作。
希望这可以帮助!
我在从 UIViewController 中的 SearchDisplayController 转换为 ViewController 中的 SearchController 时遇到了一些麻烦,因为 SearchController 的实现并不那么直观。但是您可以将 SearchController 本身的搜索器添加到任何视图中。但是您不能设置约束,因为当您聚焦/选择它时搜索栏会向上移动(如果您知道如何在将约束添加到任何视图后将其设置为 seachController.searchbar,让我知道!)。下面我分享一个清单,我在 ViewController 中实现 SearchController 时发现它非常重要/有价值。
//您可以将搜索器添加到任何视图。它会自动向上移动以像魔术一样显示 tableView。但是由于这个原因,您不能将搜索栏的约束设置为要添加到的占位符视图。
[self.searchBarPlaceHolderView addSubview:self.searchController.searchBar];
//当你聚焦/选择它时,你需要这个来防止搜索栏下拉。如果要将 searchBar 添加到导航栏的标题视图,则需要将其设置为 NO。
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];