UISearchDisplayController - 如何预加载searchResultTableView

时间:2011-06-03 09:14:41

标签: ios cocoa-touch uisearchbar uisearchdisplaycontroller

我希望在用户点按搜索栏时,但在输入任何文字之前显示一些默认内容。

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

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

   [searchDisplayController.searchBar setText:@" "];

}

这有效,但它不优雅,搜索栏中的提示文字消失了。

有没有更好的方法将数据预加载到UISearchDisplayController中的SearchResultTableView,而无需在自定义控制器中自己实现整个UISearch功能?

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

8 个答案:

答案 0 :(得分:9)

好的,我有。使用一些数据预加载dataSource并执行以下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(例如reloadData)它将加载并在那里,坐在内存中frame = CGRectZero。你给它一个合适的框架,然后将它添加到searchBar的超级视图,等等。

我通过在正确加载tableView之后显示searchBar的superview和tableView 的superview来验证这是正确的 - 它们具有相同的superview。所以,我回过头来尽早将tableView添加到superview,确定它会显示出来。对我来说,它显示为暗淡(可能在它之上的另一个视图?alpha设置较低?),但仍然可以点击。我没有进一步,但这肯定会让你的tableView显示没有任何用户交互。

享受,

达明

答案 1 :(得分:8)

我找到了一个很多更好的解决方案来解决这个问题,它似乎在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方法来防止崩溃,并发送空间@&#34; &#34;欺骗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或空字符串更改为空格字符串@&#34; &#34;防止在空搜索栏上发生的正常隐藏/调暗。如果你使用第二位代码,那么你可以修改第一位来传递一个nil而不是@&#34; &#34;因为这第二位将进行所需的转换为@&#34; &#34;对你而言。

在我自己的项目中,我需要处理用户输入空格的情况,而不是@&#34; &#34;上面我使用了一个定义的标记:

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

享受! :)

答案 2 :(得分:4)

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

答案 3 :(得分:1)

我有解决方案。插入这三种方法。您必须预先加载数据的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;
}

答案 4 :(得分:1)

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

但是,我不喜欢这个hack并用我自己的实现替换了searchDisplayController(UISearchBar和UITableView)。

答案 5 :(得分:1)

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

默认情况下,只要UISearchBar中没有文本,所显示的表格就是您原来的表格视图(从此处开始称为 originalTableView )。根据{{​​1}}的值,这可能有也可能没有黑色透明层。

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

请注意,在这两个解决方案中,我都是以类似于Apple在this example中这样做的方式实现UISearchController;也就是说,有两个单独的UITableViewController负责显示数据。

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

更顺畅的动画:

  1. 实现UISearchControllerDelegate的willPresentSearchController和willDismissSearchController方法。
  2. 在willPresent中,更新您的originalTableView数据以准备显示您想要的任何零文本数据,然后调用dimsBackgroundDuringPresentation
  3. 在willDismiss中,恢复流程以显示原始内容并致电reloadData()
  4. 示例:

    reloadData()

    在这个虚构的示例中,当用户没有关注UISearchBar时,数据显示为// 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() } } ,但是当用户点击UISearchBar时,数据显示为a,b,c

    解决方案2:快速实施,动荡不安

    除了在originalTableView和searchTableView中实现搜索控制器的逻辑外,您可以使用此解决方案简单地显示searchTableView,即使它默认是隐藏的。

    最有可能的是,您已经在实施UISearchResultsUpdating协议。只需在该方法中调用A,B,C,就可以获得您所追求的行为;虽然有一个不太出色的动画。

    tableView.hidden = false

答案 6 :(得分:-1)

为什么不看看Xcode中的TableSearch项目?它或多或少地满足您的需求。它在开头显示一个表格,并在点击搜索字段时将其缩小。在帮助下检查Xcode 4中的文档和API参考中的TableSearch。

另请查看this它几乎可以满足您对UISearchBar和UITableView的需求。我更喜欢这种方法。调整它。

为了进一步满足您的需求,我建议使用两个数据源。一个保存所有内容(这是您将在一开始显示的内容),另一个保存已过滤的搜索结果。现在继续清空第一个数据源,并用第二个数据源的内容填充它以存储&amp;暗淡显示上一次搜索的结果。继续这样做。在TableSearch代码中使用此方法来完成任务。

答案 7 :(得分:-1)

这是预先填充searchController的方法。

// 1.用户输入文字后立即保存以前的搜索结果

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

    return YES;
}

// 2.在启动时加载上一个搜索字符串

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

// 3.在询问时提供正确的数据源

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

//希望这有帮助。

由于