UIVeController中的UISearchController

时间:2014-10-17 03:51:45

标签: uitableview swift uisearchcontroller

我希望在Swift中创建与Apple的地图应用程序类似的功能。无论如何,将UISearchController集成到常规视图中(即:不是UITableView)。在连接的搜索栏内单击后,通过Storyboard删除一个导致崩溃。或者有什么方法可以用UITableView实现这个结果?

4 个答案:

答案 0 :(得分:37)

如果你想将UISearchController与非UITableView一起使用,我就是这样做的。

由于IB不支持UISearchController,但需要在其中添加任何内容,例如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方法。

享受!

答案 1 :(得分:7)

试着弄清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地图以获取行车路线。

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

博客帖子很长,所以如果您只想跳到代码,请点击相关的git repo:

https://github.com/ThornTechPublic/MapKitTutorial

答案 2 :(得分:3)

我在故事板中的View Controller中添加了搜索栏和搜索显示控制器。视图控制器仅包含搜索栏和搜索显示控制器,并且没有它自己的TableView。在视图控制器中添加搜索栏时,它会自动将视图控制器设置为其委托。

现在,搜索栏和搜索显示控制器具有自己的表格视图,当您在框内单击并开始键入时,它用于显示搜索结果。此表视图要求您的视图控制器提供numberOfRowsInSection和cellForRowAtIndexPath函数的实现,以便它正确显示数据。

当您运行没有这些项目并点击搜索栏内部时,您将收到以下错误: -

tableView:numberOfRowsInSection:]:无法识别的选择器发送到实例0x7fbf63449660 ***因未捕获的异常终止应用程序&#39; NSInvalidArgumentException&#39;

如果你看到,错误是在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方法中过滤掉数据源并正确设置上述两种方法中的行数和单元格信息,那么它应该可以正常工作。

希望这有帮助!

答案 3 :(得分:0)

我在从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];