UISearchDisplayController 没有结果 tableView?

发布于 2024-07-29 13:21:33 字数 653 浏览 12 评论 0原文

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

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

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

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

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.

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.

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.

Any ideas besides recreating the UISearchDisplayController functionality from scratch?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

烟沫凡尘 2024-08-05 13:21:33

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

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

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

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

烟织青萝梦 2024-08-05 13:21:33

您尝试过吗:

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

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

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.

糖果控 2024-08-05 13:21:33

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

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

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):

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

↘紸啶 2024-08-05 13:21:33

和你有同样的问题,我通过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

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.

@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
幸福丶如此 2024-08-05 13:21:33

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

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

您尝试过吗?

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

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

have you tried this?

放赐 2024-08-05 13:21:33

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

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.

- (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;
}   
触ぅ动初心 2024-08-05 13:21:33

就这么简单地做怎么样:

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

对我来说效果很好..

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

你げ笑在眉眼 2024-08-05 13:21:33

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

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

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 ....
}
余生再见 2024-08-05 13:21:33

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

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

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;
}
南街九尾狐 2024-08-05 13:21:33

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

因此我认为这段代码效果更好。

首先,创建一个BOOL,例如searchButtonTapped,以指示搜索按钮是否被点击。 默认情况下为“否”。

然后:

- (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 的可见选择,而是取消搜索。

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.

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.

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:

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.

Then, crucially, in 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文