12

検索バーを含む非テーブルビュービューがあります。これは完全に機能しますが、検索ディスプレイコントローラーは、空の文字列が検索バーにある場合、テーブルビューを非表示にし、暗い淡色表示をオーバーレイします。テーブルビューを非表示にして検索バーの下に暗い淡色表示をオーバーレイするのではなく、空の文字列が検索バーにあるときにプリロードされたデータを表示したいと思います。SafariforiOSのGoogle検索バーがどのように機能するかと同じです。

以前にstackoverflowで尋ねられた同様の質問を見つけました: UISearchDisplayController-searchResultTableViewをプリロードする方法、私はそれを実際に機能させることができませんでした。

プリロードされたデータを取得して現在のデータを設定することに問題はありませんが、ディスプレイコントローラーがsearchResultsTableViewを削除しないようにする方法がわかりません。

前もって感謝します。

4

7 に答える 7

13

私はついにこれを行う方法を見つけました。

searchDisplayController は単純にスーパービューから searchResultsTableView を削除することがわかったので、ディスプレイ コントローラーがテーブル ビューを非表示にしようとするたびに、テーブル ビューをスーパービューに追加し直しました。

- (void)searchDisplayController:(UISearchDisplayController *)controller didHideSearchResultsTableView:(UITableView *)tableView
{
    // add the tableview back in
    [self.view addSubview:self.searchDisplayController.searchResultsTableView];
}

そして、検索バーが初めてクリックされたときにテーブルビューも表示する必要があるため、次のようにしました。

- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller
{
    // after the data has been preloaded
    self.searchResults = self.allItems;
    [self.searchDisplayController.searchResultsTableView reloadData];
}

- (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller
{
    [self.view addSubview:self.searchDisplayController.searchResultsTableView];
}

私にとって、「allItems」は検索可能なすべてのアイテムを保存した場所であり、「searchResults」はフィルター処理されたアイテム (検索後) が保存された場所です。もちろん、データをリロードする前にアイテム (検索履歴など) をプリロードする必要があります。

これがパフォーマンスの点で良い方法なのかどうかはわかりませんが、私にとっては完璧に機能し、他の人にも役立つことを願っています. これを行うためのより良い方法があればコメントしてください。

于 2012-05-28T04:43:14.073 に答える
4

この問題に対するより良い解決策を見つけました.iOS 6 と 7 で完全に動作するようです. 他のソリューションは一貫して機能せず、一部の UISearchDisplayDelegate メソッドが起動されません! さらに、上記の方法では解決できない複雑なはめ込みの問題がありました。他のソリューションの主な問題は、UISearchDisplayController の内部をひどく混乱させることです。私の解決策は、UISearchDisplayContoller が UISearchbarDelegate であり、検索フィールドでキーを押すことをシミュレートすることで、結果テーブルの自動非調光と表示をトリガーできるという観察に基づいています! そう:

- (void) searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller 
{
    if ([controller respondsToSelector: @selector(searchBar:textDidChange:)])
        [(id<UISearchBarDelegate>)controller searchBar: controller.searchBar textDidChange: @" "];
}

このコードは、UISearchbarDelegate メソッドに応答することをチェックすることでクラッシュに対する将来の証明となり、スペース @" " を送信して UISearchDisplayController をだましてユーザーが文字を入力したと思わせるようにします。

ユーザーが何かを入力してから消去すると、テーブルが再び暗くなります。他のソリューションでは、searchDisplayController:didHideSearchResultsTableView: メソッドで何かを行うことで、これを回避しようとします。しかし、これは私には意味がありません。検索をキャンセルすると、結果テーブルを完全に非表示にする必要があり、この場合はコードを実行する必要があるかもしれません。この部分に対する私の解決策は、サブクラス化することです (プロジェクトで必要に応じて、Method Swizzled カテゴリを使用してどこでも機能させることができることに注意してください):

// privately declare protocol to suppress compiler warning
@interface UISearchDisplayController (Super) <UISearchBarDelegate>
@end

// subclass to change behavior
@interface GMSearchDisplayController : UISearchDisplayController
@end

@implementation GMSearchDisplayController

- (void) searchBar: (UISearchBar *) searchBar textDidChange: (NSString *) searchString
{
    if (searchString.length == 0)
        searchString = @" ";
    if ([super respondsToSelector: @selector(searchBar:textDidChange:)])
        [super searchBar: searchBar textDidChange: searchString];
}

@end

このコードは、textDidChange デリゲート メソッドをインターセプトし、nil または空の文字列をスペース文字列 @" " に変更することで機能し、空の検索バーで発生する通常の非表示/淡色表示を防ぎます。この 2 番目のビットのコードを使用している場合は、最初のビットを変更して @" " の代わりに nil を渡すことができます。これは、この 2 番目のビットが必要な @" " への変換を行うためです。

私自身のプロジェクトでは、ユーザーがスペースを入力した場合を処理する必要があったため、上記の @" " の代わりに、定義済みのトークンを使用しました。

// arbitrary token used internally
#define SEARCH_PRELOAD_CONDITIONAL @"_#preresults#_"

そして、nil 文字列に変換して内部的に処理します。

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
    if ([searchString isEqualToString: SEARCH_PRELOAD_CONDITIONAL])
        searchString = nil;
}

楽しみ!:)

于 2014-07-17T12:05:54.233 に答える
2

これは iOS 8 で機能します。

- (void)searchDisplayController:(UISearchDisplayController *)controller didHideSearchResultsTableView:(UITableView *)tableView
{
  self.searchDisplayController.searchResultsTableView.hidden = NO;
}

- (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller
{
    self.searchDisplayController.searchResultsTableView.hidden = NO;
    [self.searchDisplayController.searchResultsTableView.superview.superview bringSubviewToFront:self.searchDisplayController.searchResultsTableView.superview];

    CGRect frame = self.searchDisplayController.searchResultsTableView.frame;
    self.searchDisplayController.searchResultsTableView.frame = CGRectMake(frame.origin.x, 64, frame.size.width, frame.size.height);
}
于 2015-01-07T02:18:37.523 に答える
1

iOS 9 の作業コード。

- (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller {
    // Bring the search table view to the view's front
    self.searchDisplayController.searchResultsTableView.hidden = NO;
    [self.searchDisplayController.searchResultsTableView.superview bringSubviewToFront:self.searchDisplayController.searchResultsTableView];
}

- (void)searchDisplayController:(UISearchDisplayController *)controller didHideSearchResultsTableView:(UITableView *)tableView {
    // We need to prevent the resultsTable from hiding if the search is still active
    if (self.searchDisplayController.active == YES) {
        tableView.hidden = NO;
    }
}
于 2016-01-07T14:24:07.073 に答える
1

検索を開始すると、このメソッドが呼び出されます。searchResultsTableView を追加して再表示します。その後、すでにプリロードされたデータが表示されます。これを機能させるには、データをプリロードする必要があります。

- (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller
{
    CGRect testFrame = CGRectMake(0, self.notesSearchBar.frame.size.height, self.notesSearchBar.frame.size.width, self.view.frame.size.height - self.notesSearchBar.frame.size.height);
    self.searchDisplayController.searchResultsTableView.frame = testFrame;
    [self.notesSearchBar.superview addSubview:self.searchDisplayController.searchResultsTableView];

//    [self.view addSubview:self.searchDisplayController.searchResultsTableView];
    controller.searchResultsTableView.hidden = NO;
}

-(void) searchDisplayController:(UISearchDisplayController *)controller didHideSearchResultsTableView:(UITableView *)tableView
{
    CGRect testFrame = CGRectMake(0, self.notesSearchBar.frame.size.height, self.notesSearchBar.frame.size.width, self.view.frame.size.height - self.notesSearchBar.frame.size.height);
    self.searchDisplayController.searchResultsTableView.frame = testFrame;
    [self.notesSearchBar.superview addSubview:self.searchDisplayController.searchResultsTableView];

    //    [self.view addSubview:self.searchDisplayController.searchResultsTableView];
    controller.searchResultsTableView.hidden = NO;
}


-(void) searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller
{
    controller.searchResultsTableView.hidden = YES;
}
于 2013-10-30T02:22:09.910 に答える
0

Swift 2.0+ バージョン

func searchDisplayControllerDidBeginSearch(controller: UISearchDisplayController) {
    controller.searchResultsTableView.hidden = false
    controller.searchResultsTableView.superview!.bringSubviewToFront(controller.searchResultsTableView)
}

func searchDisplayController(controller: UISearchDisplayController, didHideSearchResultsTableView tableView: UITableView) {
    if ((searchDisplayController?.active) != nil) {
        tableView.hidden = false
    }
}
于 2016-03-09T15:12:50.660 に答える