Ios UISearchDisplayController-如何预加载SearchResultableView

Ios UISearchDisplayController-如何预加载SearchResultableView,ios,cocoa-touch,uisearchbar,uisearchdisplaycontroller,Ios,Cocoa Touch,Uisearchbar,Uisearchdisplaycontroller,我想在用户点击搜索栏时,但在输入任何文本之前,显示一些默认内容 我有一个使用settext的解决方案: - (void) searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller { [searchDisplayController.searchBar setText:@" "]; } 这是可行的,但并不优雅,搜索栏中的提示文本也消失了 是否有更好的方法将数据预加载到UISearchDi

我想在用户点击搜索栏时,但在输入任何文本之前,显示一些默认内容

我有一个使用settext的解决方案:

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

   [searchDisplayController.searchBar setText:@" "];

}
这是可行的,但并不优雅,搜索栏中的提示文本也消失了

是否有更好的方法将数据预加载到UISearchDisplayController中的SearchResultableView,而不必在自定义控制器中自己实现整个UISearch功能


要获得所需效果的演示,请查看Safari的搜索框,如果点击它,搜索界面将打开,显示以前的搜索。

为什么不看看Xcode中的TableSearch项目?它或多或少地满足了你的需要。它在开始处显示一个表格,并在点击搜索字段时将其隐藏。在帮助下查看Xcode 4中的文档和API参考中的表搜索

此外,还可以通过UISearchBar和UITableView了解它几乎可以满足您的需要。我更喜欢那种方法。调整它


为了进一步满足您的需求,我建议使用两个数据源。一个保存所有内容(这是您将在最开始显示的内容),另一个保存过滤后的搜索结果。现在继续,清空第一个数据源,并用第二个数据源的内容填充它以存储&dim显示上一次搜索的结果。往这边走。在任务的表搜索代码中使用这种方法。

好的,我有了。使用一些数据预加载您的数据源,然后执行以下hack(没有非法操作),您将看到tableView。请注意,可能需要进行一些清理,但这将显示默认数据

在视图控制器的viewDidLoad中,它拥有UISearchBar:

[super viewDidLoad];
[self.searchDisplayController.searchResultsTableView reloadData];
// whatever you named your search bar - mine is property named searchBar
CGRect testFrame = CGRectMake(0, 20, self.searchBar.frame.size.width, 100);
self.searchDisplayController.searchResultsTableView.frame = testFrame;
[self.searchBar.superview addSubview:self.searchDisplayController.searchResultsTableView];
发生的事情如下:
在开始编辑之前,UISearchBar不希望显示searchResultsTableView。如果触摸tableView(例如,重新加载数据),它将加载并保存在内存中,frame=CGRectZero。你给它一个合适的框架,然后把它添加到搜索栏的超级视图中,等等

在正确加载tableView之后,我通过显示搜索栏的superview和tableView的superview验证了这一点——它们具有相同的superview。因此,我返回并提前将tableView添加到superview中,果然它出现了。对我来说,它显示为灰色(可能是上面的另一个视图?alpha设置较低?),但仍然可以单击。我没有进一步讨论,但这肯定会让您在没有任何用户交互的情况下显示tableView

享受


Damien这里有一种预填充searchController的方法

- (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;
}
//一,。用户输入文本后立即保存以前的搜索结果

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

    return YES;
}
//二,。在启动时加载上一个搜索字符串

- (void)viewDidLoad 
{
    // create data source for table view
    // searchData may be a NSMutableArray property defined in your interface

    self.searchData = // search your master list for searchString

    // or create your own list using any search criteria you want

    // or you may act depending on user preference
    if(!showPreviousSearch)
    {
        // [searchData removeAllObjects];
    }
}
//三,。在询问时提供正确的数据源

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) 
    {
        ...
    }

    NSMutableArray *dataSource = nil;
    if (tableView == [[self searchDisplayController] searchResultsTableView])
    {
        dataSource = self.searchData;
    }
    else
    {
        dataSource = self.masterData;
    }

    ...

    return cell;
}
//希望这有帮助


谢谢

我有办法了。插入这三种方法。必须在tableview中预加载数据才能正常工作。我的代码中有这些代码,所以只要您已经预加载了数据并且正在使用搜索显示控制器,它就必须对您有效

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

iOS 7的工作解决方案:

// When the tableView is hidden, put it back
- (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller {
    [self.searchDisplayController.searchResultsTableView reloadData];
    controller.searchResultsTableView.hidden = NO;

    // Also, remove the dark overlay
    for (UIView *v in [[controller.searchResultsTableView superview] subviews]) {
        // This is somewhat hacky..
        if (v.alpha < 1) {
            [v setHidden:YES];
        }
    }
}

-(void)searchDisplayController:(UISearchDisplayController *)controller didHideSearchResultsTableView:(UITableView *)tableView {
    [self.searchDisplayController.searchResultsTableView reloadData];
    if (self.searchDisplayController.active == YES) {
        tableView.hidden = NO;
    }
}
//隐藏tableView时,将其放回
-(void)SearchDisplayControllerIDBeginSearch:(UISearchDisplayController*)控制器{
[self.searchDisplayController.searchResultsTableView重新加载数据];
controller.searchResultsTableView.hidden=否;
//此外,删除黑暗的覆盖
对于(UIView*v在[[controller.searchResultsTableView superview]子视图]中){
//这有点骇人听闻。。
如果(v.alpha<1){
[v:是];
}
}
}
-(void)searchDisplayController:(UISearchDisplayController*)控制器didHideSearchResultsTableView:(UITableView*)tableView{
[self.searchDisplayController.searchResultsTableView重新加载数据];
如果(self.searchDisplayController.active==是){
tableView.hidden=否;
}
}

我找到了一个更好的解决方案,它似乎可以在iOS 6和iOS 7上完美运行。虽然它仍然是一种黑客行为,但它比上面提到的更干净、更能抵御未来的黑客行为。其他解决方案的工作不一致,并阻止某些UISearchDisplayDelegate方法触发!此外,我有复杂的插入问题,我无法解决上述方法。其他解决方案的主要问题是它们严重混淆了UISearchDisplayController的内部。我的解决方案基于这样的观察:UISearchDisplayContoller是一个UISearchbarDelegate,通过模拟搜索字段中的按键可以触发结果表的自动解封和显示!因此:

- (void) searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller 
{
    if ([controller respondsToSelector: @selector(searchBar:textDidChange:)])
        [(id<UISearchBarDelegate>)controller searchBar: controller.searchBar textDidChange: @" "];
}
然后通过将其转换回nil字符串对其进行内部处理:

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

这适用于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);
}

但是,我不喜欢这种黑客行为,用我自己的实现(带UITableView的UISearchBar)替换了searchDisplayController。

我用UISearchController在iOS 9中测试了以下内容

- (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;
}
默认情况下,每当UISearchBar中没有文本时,显示的表格将是您的原始表格视图(从这里开始称为originalTableView)。根据演示过程中
DIMSBackground的值,该层可能有黑色透明层,也可能没有黑色透明层

一旦用户在UISearchBar中输入任何文本,就会显示新表视图的内容(我将其称为searchTableView

请注意,在这两种解决方案中,我以类似于苹果在中的方式实现UISearchController;也就是说,有两个独立的UITableViewController负责显示数据

解决方案1:复杂的实施,更流畅的动画

要获得更平滑的动画,请执行以下操作:

  • 实现UISearchControllerDelegate的willPresentSearchController和willDismis
    // here tableView refers to originalTableView
    
    extension ViewController: UISearchControllerDelegate {
        func willPresentSearchController(searchController: UISearchController) {
            data = ["A", "B", "C"]
            tableView.reloadData()
        }
    
        func willDismissSearchController(searchController: UISearchController) {
            data = ["a", "b", "c"]
            tableView.reloadData()
        }
    }
    
    // here tableView refers to searchTableView
    
    extension SearchViewController: UISearchResultsUpdating {
        func updateSearchResultsForSearchController(searchController: UISearchController) {
            tableView.hidden = false
            filterData(text: searchController.searchBar.text!)
            tableView.reloadData()
        }
    }