显示预加载的搜索结果?

时间:2012-05-24 09:27:09

标签: objective-c ios uisearchbar xcode4.3 uisearchdisplaycontroller

我有一个带有搜索栏的非tableview视图,虽然它工作正常,但当搜索栏中有一个空字符串时,搜索显示控制器会隐藏表格视图并叠加一个暗灰色视图。我希望它在空字符串位于搜索栏中时显示预加载的数据,而不是隐藏表格视图并覆盖搜索栏下方的暗灰色视图。就像Safari for iOS中的Google搜索栏一样。

我之前在stackoverflow上发现了类似的问题: UISearchDisplayController - how to preload searchResultTableView,我无法真正开始工作。

获取预加载数据并将当前数据设置为它没有问题,但我不确定如何阻止displaycontroller删除searchResultsTableView。

提前致谢。

7 个答案:

答案 0 :(得分:13)

我终于找到了办法。

我发现searchDisplayController只是从superview中删除了searchResultsTableView,所以每当显示控制器试图隐藏表视图时,我只是将表视图添加回superview:

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

然后我还必须在第一次点击搜索栏时显示tableview,所以我做了:

- (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'是存储过滤项目(搜索后)的地方。当然,在重新加载数据之前,您必须预先加载项目(例如搜索历史记录)。

我不知道这是不是一个很好的方式或者不是这样做的表现和不是,但它对我来说很完美,我希望这对其他人也有用。如果有更好的方法,请评论。

答案 1 :(得分:4)

经过数小时和数小时后,我终于找到了适用于iOS 7的解决方案

在UISearchDisplayDelegate

中实现以下两种方法
-(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;
    }
}

搜索开始时,searchResultsTableView会自动隐藏,所以我们需要再次取消隐藏

- (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller {

    controller.searchResultsTableView.hidden = NO;

    // Then we need to remove the semi transparent overlay which is here
    for (UIView *v in [[[controller.searchResultsTableView superview] superview] subviews]) {

        if (v.frame.origin.y == 64) {
            [v setHidden:YES];
        }
    }

}

答案 2 :(得分: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:方法。但这对我来说没有意义,因为当您取消搜索时,它需要真正隐藏您的结果表,在这种情况下您可能需要运行代码。我对这部分的解决方案是子类(注意你可以使用一个方法调配类别,使其在项目中需要时可以在任何地方工作):

// 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或空字符串更改为空格字符串@“”来阻止在空搜索栏上发生的正常隐藏/调暗。如果您正在使用第二位代码,那么您可以修改第一位以传递nil而不是@“”,因为第二位将为您执行所需的转换为@“”。

在我自己的项目中,我需要处理用户输入空格的情况,因此我使用定义的标记而不是上面的@“”:

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

然后通过将其转换回nil string来内部处理它:

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

享受! :)

答案 3 :(得分: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);
}

答案 4 :(得分: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;
}

答案 5 :(得分: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;
    }
}

答案 6 :(得分:0)

Swift 2.0+版本

<form method="POST" class="form-horizontal submit-form" onsubmit="return checkform(this);">

    <!-- Text input-->
    <div class="form-group">
        <label class="col-md-4 control-label" for="name">Name</label>  
        <div class="col-md-8">
            <input id="name" name="name" type="text" placeholder="insert full Name" class="form-control input-md" required="" />
        </div>
    </div>

    <!-- Button -->
    <div class="form-group">
        <label class="col-md-4 control-label" for="send-btn"></label>
        <div class="col-md-8">
            <button id="send-btn" name="send-btn" class="btn btn-primary">Submit</button>
        </div>
    </div>
</form>