web-dev-qa-db-ja.com

結果tableViewがないUISearchDisplayController?

通常、UISearchDisplayControllerがアクティブになると、tableViewが暗くなり、searchBarがフォーカスされます。 searchBarにテキストを入力するとすぐに、searchBarとキーボードの間に表示されるsearchResultsTableViewが作成されます。この2番目のUITableViewがロード/表示/非表示/アンロードされると、searchDisplayControllerのデリゲートが呼び出されます。通常、入力中にライブ検索結果またはオートコンプリートエントリが表示されます。

私のアプリでは、Webサービスを検索し、ユーザーが入力する文字ごとにWebサービスを呼び出したくありません。したがって、searchResultsTableViewを完全に無効にし、テキストを入力している間は淡色表示の黒いオーバーレイを維持したいと思います。彼が検索ボタンを押すと、(ロード画面で)検索をトリガーします。

SearchResultsTableViewにゼロ行を返すだけでは、「結果なし」メッセージを含む空のsearchResultsTableViewが表示されるため、見栄えがよくありません。テーブルが表示されたら非表示にしようとしました(searchDisplayController:didLoadSearchResultsTableView:)は機能しますが、黒色の淡色表示のオーバーレイも非表示になるため、基になるtableViewが完全に再び表示されます。

UISearchDisplayController機能をゼロから再作成する以外のアイデアはありますか?

42
Zargony

これは私が理解したちょっとしたトリックで、検索文字列の編集中に結果を0返す必要があります

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
    savedSearchTerm = searchString;

    [controller.searchResultsTableView setBackgroundColor:[UIColor colorWithWhite:0.0 alpha:0.8]];
    [controller.searchResultsTableView setRowHeight:800];
    [controller.searchResultsTableView setScrollEnabled:NO];
    return NO;
}

- (void)searchDisplayController:(UISearchDisplayController *)controller didHideSearchResultsTableView:(UITableView *)tableView
{
    // undo the changes above to prevent artefacts reported below by mclin
}

あなたは次に何をすべきかを理解すると思います

38
user182820

これを試しましたか:

[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(_lookup:) object:nil];
[self performSelector:@selector(_lookup:) withObject:txt afterDelay:0.20];

このように、ユーザーが1/5秒以内に別の文字を入力した場合、Web呼び出しは1回だけです。

19
Raymond W

上記のいずれも最終的にはうまく機能していないようだったので、次のことを思いつきました(結果を表示する準備ができたら、removeTableHeaderを呼び出す必要があります)。

- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar {
    [self setTableHeader];
}

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
    [self setTableHeader];
}

- (void)setTableHeader {
    UIView *headerView = [[UIView alloc] initWithFrame:self.searchDisplayController.searchResultsTableView.frame];
    headerView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.8];

    [self.searchDisplayController.searchResultsTableView setBackgroundColor:[UIColor clearColor]];
    [self.searchDisplayController.searchResultsTableView setScrollEnabled:NO];
    [self.searchDisplayController.searchResultsTableView setTableHeaderView:headerView];

    [headerView release];
}

- (void)removeTableHeader {
    [self.searchDisplayController.searchResultsTableView setBackgroundColor:[UIColor whiteColor]];
    [self.searchDisplayController.searchResultsTableView setScrollEnabled:YES];
    [self.searchDisplayController.searchResultsTableView setTableHeaderView:nil];
}

明らかに、それはテーブルを透明にし、テーブルと同じサイズの黒/半透明のテーブルヘッダーを追加し、ヘッダーの上または先に移動できないようにテーブルのスクロールを無効にします。おまけとして、ヘッダービューに何かを追加できます(「お待ちください...」またはアクティビティインジケーター)。

9
Barry Haanstra

あなたと同じ問題があったので、私はa)検索を開始するときにsearchResultsTableViewのアルファを0に設定し、次にb)にoverlayViewを追加/削除して対処しましたviewControllerのビュー。私にとっては魅力のように機能します。

@interface MyViewController()
//...
@property(nonatomic, retain) UIView *overlayView;
//...
@end

@implementation MyViewController
@synthesize overlayView = _overlayView;

//...

- (void)viewDidLoad
{
    //...

    //define your overlayView
    _overlayView = [[UIView alloc] initWithFrame:CGRectMake(0, 44, 320, 480)];
    _overlayView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.8];
}

//hide the searchResultsTableView
- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller
{
    self.searchDisplayController.searchResultsTableView.alpha = 0.0f;
}

//when ending the search, hide the overlayView
- (void) searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller
{
    [_overlayView removeFromSuperview];
}

//depending on what the user has inputed, add or remove the overlayView to the view of the current viewController 
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{   

    if ([searchString length]>0) 
    {
        [self.view addSubview:_overlayView];
    }
    else
    {
        [_overlayView removeFromSuperview];
    }

    return NO;
}

@end
9
cvursache

uISearchDisplayDelegate(通常はカスタムUITableViewControllerサブクラス)に次のメソッドを実装するだけで十分です。

- (BOOL) searchDisplayController: (UISearchDisplayController *) controller shouldReloadTableForSearchString: (NSString *) searchString
{
    [self startMyCustomWebserviceSearchAsBackgroundProcessForString: searchString]; //starts new NSThread
    return NO; 
}

これを試しましたか?

2
xoconoxtle

以下のuser182820のコードに基づくのは私のバージョンです。 UISearchDisplayControllerのテーブルビューを非表示にします。検索ボックスに文字が入力されると、「薄暗い表示」を配置します。これにより、UISearchDisplayControllerの「薄暗い表示」が消えることはなく、検索が終了したときに削除されます。いくつかの文字を入力してキャンセルを押すと、テーブルビューが一瞬真っ白になり、これを回避する方法がわかりません。

- (void)viewDidLoad {
    ...
    tableViewMask=[UIView new];
    tableViewMask.backgroundColor = [UIColor blackColor];
    tableViewMask.alpha = 0.8;
}

- (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller{
    tableViewMask.frame=CGRectMake(self.tableView.frame.Origin.x, self.tableView.frame.Origin.y+controller.searchBar.frame.size.height, self.tableView.frame.size.width, self.tableView.frame.size.height-controller.searchBar.frame.size.height);
    controller.searchResultsTableView.hidden=YES;
}

- (void)searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller{
    [tableViewMask removeFromSuperview];
}

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString{
    if (searchString.length==0)
        [tableViewMask removeFromSuperview];
    else 
        [self.tableView addSubview:tableViewMask];
    [searchText autorelease];
    searchText=[searchString retain];
    return NO;
}   
2
Mark Horgan

次のように単純にそれを行うのはどうですか?

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
self.searchDisplayController.searchResultsTableView.hidden=YES;
return YES;
}

私にとってはうまくいきます。

2
ingenspor

既存の回答はすべて非常に複雑です。結果テーブルビューをすぐに非表示にするだけで、問題を回避できます。

-(void)searchDisplayController:(UISearchDisplayController *)controller didShowSearchResultsTableView:(UITableView *)tableView
{
    tableView.hidden = YES;
}
1
Chris Allwein

「ベストアンサー」にバグがあるため、より良い方法を見つけました。黒い背景のテーブルをスクロールすると、セパレーターと「結果なし」が表示されます。

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {

    controller.searchResultsTableView.backgroundColor = [UIColor blackColor];
    controller.searchResultsTableView.alpha = 0.8;
    controller.searchResultsTableView.separatorStyle = UITableViewCellSeparatorStyleNone;

    for(UIView *subview in tableView.subviews) {
        if([subview isKindOfClass:UILabel.class]) {
            subview.hidden = YES;
        }
    }

    return NO;
}

- (void) searchBarSearchButtonClicked:(UISearchBar *)searchBar {

    self.searchDisplayController.searchResultsTableView.backgroundColor = [UIColor whiteColor];
    self.searchDisplayController.searchResultsTableView.alpha = 1;
    self.searchDisplayController.searchResultsTableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;

    for(UIView *subview in tableView.subviews) {
        if([subview isKindOfClass:UILabel.class]) {
            subview.hidden = NO;
        }
    }

    // search results and reload data ....
}
1
user398952

私はこの問題のより良い実装を見つけたと思います。以前のすべての回答は、検索前のUITableViewと同じ淡色表示を正しく示していますが、各ソリューションには、検索をキャンセルするために領域をタップする機能がありません。

そのため、このコードはうまく機能すると思います。

まず、searchButtonTappedなどのBOOLを作成して、検索ボタンがタップされたかどうかを示します。デフォルトではNOです。

次に:

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
if (!searchButtonTapped) {        
    // To prevent results from being shown and to show an identical look to how the tableview looks before a search
    [controller.searchResultsTableView setBackgroundColor:[UIColor clearColor]];
    [controller.searchResultsTableView setRowHeight:160];
    self.searchDisplayController.searchResultsTableView.scrollEnabled = NO;
} else {
    // Restore original settings
    [controller.searchResultsTableView setBackgroundColor:[UIColor whiteColor]];
    [controller.searchResultsTableView setRowHeight:44];
    self.searchDisplayController.searchResultsTableView.scrollEnabled = YES;
}

return YES;
}

これは、他の回答に基づいて、今は明らかです。また、ユーザーが[検索]ボタンをタップした場合は、必ず元の設定を復元してください。

さらに、cellForIndexPathメソッドに以下を追加します。

cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.contentView.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.8];

テキストを入力する前に表示されるのと同じ淡色表示を作成するため。これらのプロパティを正しいセルに適用していることを確認してください。つまり、アクティブなUITableViewと、ユーザーが[検索]ボタンをタップしていないことを確認してください。

次に、決定的に、didSelectRowAtIndexPathで:

if (tableView == self.searchDisplayController.searchResultsTableView) {
    if (searchButtonTapped) {
           // Code for when the user select a row after actually having performed a search
    {
else 
    [self.searchDisplayController setActive:NO animated:YES];

これで、ユーザーは淡色表示された領域をタップできるようになりました。これにより、UITableViewCellの表示は選択されず、代わりに検索がキャンセルされます。

0
Willem Sleegers