objective-c UISearchDisplayController 没有结果 tableView?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1214185/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 21:59:58  来源:igfitidea点击:

UISearchDisplayController with no results tableView?

iphoneobjective-cuisearchbarsearchdisplaycontroller

提问by Zargony

Usually, a UISearchDisplayController, when activated, dims the tableView and focuses the searchBar. As soon as you enter text into the searchBar, it creates a searchResultsTableView that displays between the searchBar and the keyboard. The searchDisplayController's delegate gets called when this second UITableView is loaded/shown/hidden/unloaded. Usually it shows live search results or autocompletion entries while typing.

通常,UISearchDisplayController 在激活时会使 tableView 变暗并聚焦 searchBar。只要您在搜索栏中输入文本,它就会创建一个显示在搜索栏和键盘之间的 searchResultsTableView。当加载/显示/隐藏/卸载第二个 UITableView 时,将调用 searchDisplayController 的委托。通常它会在输入时显示实时搜索结果或自动完成条目。

In my app, I want to search a webservice and I don't want to call the webservice for each letter the user enters. Therefore, I want to entirely disable the searchResultsTableView and keep the dimmed black overlay while he enters text. I would then trigger the search (with a loading screen) once he hits the search button.

在我的应用程序中,我想搜索一个网络服务,但我不想为用户输入的每个字母调用网络服务。因此,我想完全禁用 searchResultsTableView 并在他输入文本时保留变暗的黑色叠加层。一旦他点击搜索按钮,我就会触发搜索(带有加载屏幕)。

Just returning zero rows for the searchResultsTableView doesn't look nice since it displays an empty searchResultsTableView with a "no results" message. I tried to hide the table when it appears (searchDisplayController:didLoadSearchResultsTableView:) which works, but the blacked dimmed overlay is also hidden so that the underlying tableView is completely visible again.

只为 searchResultsTableView 返回零行看起来不太好,因为它显示一个空的 searchResultsTableView 并带有“无结果”消息。我试图在表格出现时隐藏它 ( searchDisplayController:didLoadSearchResultsTableView:) ,但是变黑的变暗覆盖层也被隐藏,因此底层的 tableView 再次完全可见。

Any ideas besides recreating the UISearchDisplayController functionality from scratch?

除了从头开始重新创建 UISearchDisplayController 功能之外,还有什么想法吗?

采纳答案by user182820

here is a little trick that i just figured out and also you have to return 0 results while editing searchstring

这是我刚刚想出的一个小技巧,而且你必须在编辑搜索字符串时返回 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
}

i think you'll figure out what to do next

我想你会弄清楚下一步该做什么

回答by Raymond W

Have you tried this:

你有没有试过这个:

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

This way, if the user types another char within 1/5sec, you only make one web call.

这样,如果用户在 1/5 秒内键入另一个字符,您只需进行一次网络调用。

回答by Barry Haanstra

Nothing of the above seemed to work well in the end, so I came up with the following (you have to call removeTableHeader when you are ready to display your results):

最后,上面的所有内容似乎都不起作用,所以我想出了以下内容(当你准备好显示你的结果时,你必须调用 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];
}

Obviously, it make the table transparent, adds a black/translucent table header with the same size as the table, and disables scrolling on the table so you cannot get above or past the header. As a bonus, you could add something to the header view ('please wait...' or an activity indicator).

显然,它使表格透明,添加一个与表格大小相同的黑色/半透明表格标题,并禁用在表格上滚动,因此您无法超过或超过标题。作为奖励,您可以在标题视图中添加一些内容(“请稍候...”或活动指示器)。

回答by cvursache

Had the same problem as you, I handled it by a)setting the alpha of the searchResultsTableView to 0 when beginning searching, and then by b)adding/removing the overlayView to the viewController's view. Works like a charm for me.

和你有同样的问题,我通过a)在开始搜索时将searchResultsTableView的alpha设置为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

回答by ingenspor

What about just doing it as simple as this:

像这样简单地做它怎么样:

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

Works fine for me..

对我来说很好用..

回答by Mark Horgan

Based on user182820's code below is my version. I hide the UISearchDisplayController's table view. When a character is entered in the search box I place a 'dimmed view' so it looks like UISearchDisplayController's 'dimmed view' never went away and then remove it when the search is finished. If you enter some characters and press cancel, the table view briefly goes all white and I don't know how to get around this.

下面基于 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;
}   

回答by xoconoxtle

it should be sufficient to implement the following method in your UISearchDisplayDelegate (which usually is your custom UITableViewController subclass)

在您的 UISearchDisplayDelegate(通常是您的自定义 UITableViewController 子类)中实现以下方法应该就足够了

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

have you tried this?

你试过这个吗?

回答by xoconoxtle

I foud a better way, since there is a bug with the "best answer" - the separator and the "No Results" will be shown when scrolling the black background table.

我提出了一个更好的方法,因为“最佳答案”存在一个错误 - 滚动黑色背景表时将显示分隔符和“无结果”。

- (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 ....
}

回答by Chris Allwein

All of the existing answers are overly complicated. You can get away by just hiding the results table view immediately.

所有现有的答案都过于复杂。您可以通过立即隐藏结果表视图来逃脱。

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

回答by Willem Sleegers

I think I found a better implementation for this problem. All the previous answers correctly show a dimmed view identical to what the UITableView looks like before a search, but each solution lacks the functionality to tap the area in order to cancel the search.

我想我为这个问题找到了更好的实现。之前的所有答案都正确地显示了与 UITableView 在搜索前的外观相同的变暗视图,但每个解决方案都缺乏点击该区域以取消搜索的功能。

For that reason I think this code works better.

出于这个原因,我认为这段代码效果更好。

First of all, create a BOOL such as searchButtonTapped to indicate whether the search button was tapped. By default it is NO.

首先,创建一个 BOOL 例如 searchButtonTapped 来指示搜索按钮是否被点击。默认为否。

Then:

然后:

- (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;
}

This should be clear now based on the other answers. Make sure to also restore the original settings when the user taps on the Search button.

根据其他答案,现在应该很清楚了。确保在用户点击“搜索”按钮时也恢复原始设置。

Furthermore, in the cellForIndexPath method add:

此外,在 cellForIndexPath 方法中添加:

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

In order to create the same dimmed view that is shown before text is entered. Make sure you apply these properties to the right cell, i.e., check which UITableView is active and that the user has not tapped the Search button.

为了创建在输入文本之前显示的相同的变暗视图。确保将这些属性应用于正确的单元格,即检查哪个 UITableView 处于活动状态以及用户没有点击搜索按钮。

Then, crucially, in didSelectRowAtIndexPath:

然后,至关重要的是,在 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];

Now the user can tap the dimmed area, which will not result in a visible selection of a UITableViewCell, but instead cancels the search.

现在用户可以点击变暗的区域,这不会导致 UITableViewCell 的可见选择,而是取消搜索。