UISearchDisplayControllerではなくUISearchControllerを使用していますが、SearchBarTapにSearchResultControllerをすぐに表示したいと思います。現在、次のように表示されています(検索バーをタップすると):
結果が空の場合でも、UISearchController
のviewController
は非表示のままです。そのため、UISearchControllerDelegate
のwillPresentSearchController:
を使用する必要があります。
self.searchController
を初期化した後、ViewControllerを `UISearchControllerDelegate:に準拠させます。self.searchController.delegate = self;
willPresentSearchController:
を実装します。- (void)willPresentSearchController:(UISearchController *)searchController
{
dispatch_async(dispatch_get_main_queue(), ^{
searchController.searchResultsController.view.hidden = NO;
});
}
非同期ディスパッチが必要です。そうしないと、内部動作によってオーバーライドされるためです。ここで空想にふけり、アニメーションを使用してテーブルビューをフェードインさせることができます。
didPresentSearchController:
を実装します。- (void)didPresentSearchController:(UISearchController *)searchController
{
searchController.searchResultsController.view.hidden = NO;
}
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の答えは、これを実装するための最もクリーンな方法です。
ここにありますSwift
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
}
この方法の方が良いと思います。searchBarが空の場合は注意してください。そうすると、プリロードされたテーブルビューが再び消えます。
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
}
}
func willPresentSearchController(searchController: UISearchController) {
dispatch_async(dispatch_get_main_queue()) {
self.searchController.searchResultsController?.view.hidden = false
}
}