在 SearchBar Tap 上显示 UISearchController 的 SearchResultsController
Show UISearchController's SearchResultsController on SearchBar Tap
我使用的是 UISearchController 而不是 UISearchDisplayController,我想立即在 SearchBar Tap 上显示 SearchResultController。现在它显示如下(当我点击搜索栏时):
当结果为空时,UISearchController
的viewController
仍然隐藏。这就是为什么我们必须 fiddle 使用 UISearchControllerDelegate
的 willPresentSearchController:
初始化后 self.searchController
让你的 ViewController 符合 `UISearchControllerDelegate:
self.searchController.delegate = self;
在您的 ViewController 中实施 willPresentSearchController:
:
- (void)willPresentSearchController:(UISearchController *)searchController
{
dispatch_async(dispatch_get_main_queue(), ^{
searchController.searchResultsController.view.hidden = NO;
});
}
异步调度是必要的,否则它会被内部行为覆盖。您可以在这里使用动画让 table 视图淡入。
此外,实施 didPresentSearchController:
以保持理智:
- (void)didPresentSearchController:(UISearchController *)searchController
{
searchController.searchResultsController.view.hidden = NO;
}
I think this method is better, be careful when searchBar is empty then preload tableview will disappear again.
UISearchBarDelegate
func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
if searchText.isEmpty {
dispatch_async(dispatch_get_main_queue()) {
self.searchController.searchResultsController?.view.hidden = false
}
}
}
func searchBarTextDidBeginEditing(searchBar: UISearchBar) {
dispatch_async(dispatch_get_main_queue()) {
self.searchController.searchResultsController?.view.hidden = false
}
}
UISearchControllerDelegate
func willPresentSearchController(searchController: UISearchController) {
dispatch_async(dispatch_get_main_queue()) {
self.searchController.searchResultsController?.view.hidden = false
}
}
我发现其他答案由于使用dispatch_async
而出现闪烁。他们使用它以便在搜索控制器的内部行为完成后应用他们的更改,但这会留下几个框架,在内部行为被覆盖之前应用内部行为。使用 KVO 让我可以立即覆盖内部行为而不会出现任何闪烁。
我还发现当用户点击 ⓧ 按钮清除搜索栏的内容时,其他答案并没有保持搜索结果控制器可见,这对我来说似乎不正确。
- (void) viewDidLoad
{
...
self.searchController.delegate = self;
[self.searchController.searchResultsController.view addObserver:self forKeyPath:@"hidden" options:0 context:NULL];
}
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
if ( object == self.searchController.searchResultsController.view &&
[keyPath isEqualToString:@"hidden"] &&
self.searchController.searchResultsController.view.hidden &&
self.searchController.searchBar.isFirstResponder )
{
self.searchController.searchResultsController.view.hidden = NO;
}
}
- (void) willPresentSearchController:(UISearchController *)searchController
{
searchController.searchResultsController.view.hidden = NO;
}
- (void) searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
if ( searchText.length == 0 )
self.searchController.searchResultsController.view.hidden = NO;
}
- (void) searchBarTextDidEndEditing:(UISearchBar *)searchBar
{
self.searchController.searchResultsController.view.hidden = YES;
}
Chris Vasselli 的回答是最简洁的实现方式。
这里是Swift3
override func viewDidLoad() {
super.viewDidLoad()
searchController.delegate = self
self.searchController.searchResultsController?.view.addObserver(self, forKeyPath: "hidden", options: [], context: nil)
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if let someView: UIView = object as! UIView? {
if (someView == self.searchController.searchResultsController?.view &&
(keyPath == "hidden") &&
(searchController.searchResultsController?.view.isHidden)! &&
searchController.searchBar.isFirstResponder) {
searchController.searchResultsController?.view.isHidden = false
}
}
}
func willPresentSearchController(_ searchController: UISearchController) {
searchController.searchResultsController?.view.isHidden = false
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
if (searchText.characters.count == 0) {
searchController.searchResultsController?.view.isHidden = false
}
}
func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
searchController.searchResultsController?.view.isHidden = true
}
我使用的是 UISearchController 而不是 UISearchDisplayController,我想立即在 SearchBar Tap 上显示 SearchResultController。现在它显示如下(当我点击搜索栏时):
当结果为空时,UISearchController
的viewController
仍然隐藏。这就是为什么我们必须 fiddle 使用 UISearchControllerDelegate
的 willPresentSearchController:
初始化后 self.searchController
让你的 ViewController 符合 `UISearchControllerDelegate:
self.searchController.delegate = self;
在您的 ViewController 中实施 willPresentSearchController:
:
- (void)willPresentSearchController:(UISearchController *)searchController
{
dispatch_async(dispatch_get_main_queue(), ^{
searchController.searchResultsController.view.hidden = NO;
});
}
异步调度是必要的,否则它会被内部行为覆盖。您可以在这里使用动画让 table 视图淡入。
此外,实施 didPresentSearchController:
以保持理智:
- (void)didPresentSearchController:(UISearchController *)searchController
{
searchController.searchResultsController.view.hidden = NO;
}
I think this method is better, be careful when searchBar is empty then preload tableview will disappear again.
UISearchBarDelegate
func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
if searchText.isEmpty {
dispatch_async(dispatch_get_main_queue()) {
self.searchController.searchResultsController?.view.hidden = false
}
}
}
func searchBarTextDidBeginEditing(searchBar: UISearchBar) {
dispatch_async(dispatch_get_main_queue()) {
self.searchController.searchResultsController?.view.hidden = false
}
}
UISearchControllerDelegate
func willPresentSearchController(searchController: UISearchController) {
dispatch_async(dispatch_get_main_queue()) {
self.searchController.searchResultsController?.view.hidden = false
}
}
我发现其他答案由于使用dispatch_async
而出现闪烁。他们使用它以便在搜索控制器的内部行为完成后应用他们的更改,但这会留下几个框架,在内部行为被覆盖之前应用内部行为。使用 KVO 让我可以立即覆盖内部行为而不会出现任何闪烁。
我还发现当用户点击 ⓧ 按钮清除搜索栏的内容时,其他答案并没有保持搜索结果控制器可见,这对我来说似乎不正确。
- (void) viewDidLoad
{
...
self.searchController.delegate = self;
[self.searchController.searchResultsController.view addObserver:self forKeyPath:@"hidden" options:0 context:NULL];
}
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
if ( object == self.searchController.searchResultsController.view &&
[keyPath isEqualToString:@"hidden"] &&
self.searchController.searchResultsController.view.hidden &&
self.searchController.searchBar.isFirstResponder )
{
self.searchController.searchResultsController.view.hidden = NO;
}
}
- (void) willPresentSearchController:(UISearchController *)searchController
{
searchController.searchResultsController.view.hidden = NO;
}
- (void) searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
if ( searchText.length == 0 )
self.searchController.searchResultsController.view.hidden = NO;
}
- (void) searchBarTextDidEndEditing:(UISearchBar *)searchBar
{
self.searchController.searchResultsController.view.hidden = YES;
}
Chris Vasselli 的回答是最简洁的实现方式。
这里是Swift3
override func viewDidLoad() {
super.viewDidLoad()
searchController.delegate = self
self.searchController.searchResultsController?.view.addObserver(self, forKeyPath: "hidden", options: [], context: nil)
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if let someView: UIView = object as! UIView? {
if (someView == self.searchController.searchResultsController?.view &&
(keyPath == "hidden") &&
(searchController.searchResultsController?.view.isHidden)! &&
searchController.searchBar.isFirstResponder) {
searchController.searchResultsController?.view.isHidden = false
}
}
}
func willPresentSearchController(_ searchController: UISearchController) {
searchController.searchResultsController?.view.isHidden = false
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
if (searchText.characters.count == 0) {
searchController.searchResultsController?.view.isHidden = false
}
}
func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
searchController.searchResultsController?.view.isHidden = true
}