2011-06-03 43 views
27

我想显示一些默认内容,当用户点击搜索栏,但在任何文本输入之前。UISearchDisplayController - 如何预先载入searchResultTableView

我有一个解决方案使用的setText工作:

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

    [searchDisplayController.searchBar setText:@" "]; 

} 

这工作,但它不是优雅,并在搜索栏的提示文本消失。

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

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

+0

3班轮!当然,这是大约40行和很多阅读,直到我找出了那个UISearchDisplayController发生了什么。好问题,我喜欢学习iOS这样的小挑战。 – 2012-03-01 18:38:29

+0

看到这个链接 http://stackoverflow.com/a/21344947/747719 这是一个回车的解决方案。 – kapukinz 2014-01-25 00:33:14

回答

-1

为什么不看看Xcode中的TableSearch项目?它或多或少地解决你需要的东西。它在开头显示一个表格,并在搜索字段被点击时显示出来。在帮助中检查Xcode 4中的文档和API参考中的TableSearch。

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

为了进一步满足您的需求,我建议使用两个数据源。其中一个包含所有内容(这是您将在一开始显示的内容),一个包含过滤的搜索结果。现在继续并清空第一个数据源,并用第二个数据源的内容填充以存储&以显示先前搜索的结果。继续这种方式。在您的任务的TableSearch代码中使用此方法。

9

好的,我有。用一些数据预先加载你的dataSource并执行以下hack(没有任何非法),你将得到tableView。请注意,可能需要执行一些清理操作,但这会显示默认数据。

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

[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,et瞧的超级视图。

我通过显示searchView的超级视图和tableView 的超级视图正确加载tableView - 它们具有相同的超级视图来验证这是正确的。所以,我回去把tableView添加到superview中,并且确实显示出来了。对我来说,它显示变暗了(也许上面的另一个视图?alpha设置较低?),但仍然可以点击。我没有更进一步,但是这绝对让你的tableView显示没有任何用户交互。

享受,

达明

+0

这不适合我。我已经将我的搜索栏放置在故事板中。我不想再次定位它。当我点击搜索栏时,数据未加载。 – coolcool1994 2013-10-09 03:14:33

+0

这不是一个简单的问题 - 如果你通读“这是发生了什么”,你会看到为什么添加子视图是必要的。我还没有在ios6或7中验证过行为 - 现在可能有更好的方法来做到这一点。祝你好运! – 2013-10-10 20:28:11

+0

在iOS 8中,您需要执行self.view.superview addSubview ...而不是使用搜索栏。然后你需要用状态栏调整tabview的大小,如下所示:CGRect testFrame = CGRectMake(0,self.notesSearchBar.frame.size.height + [UIApplication sharedApplication] .statusBarFrame.size.height,self.notesSearchBar.frame。 size.width,self.view.frame.size.height - self.notesSearchBar.frame.size.height); – coolcool1994 2016-05-28 02:08:00

-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; 
} 
提供正确的数据源

//希望这会有所帮助。

谢谢

+0

没有为我工作..我有我的数据源都准备好了.. – 2012-07-10 08:45:43

1

我有解决方案。插入这三个方法。你必须预先在tableview中加载数据才能工作。我的代码工作在我的代码中,只要您已经预装了数据并且您正在使用搜索显示控制器,它就必须为您工作。针对iOS 7

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

这是一个很好的解决方案。也许还应该有一个 [self.searchDisplayController.searchResultsTableView removeFromSuperview];在searchDisplayControllerWillEndSearch – MacMark 2013-12-27 17:44:37

4

工作液:

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

这一个显示第二个滞后,我可以看到重叠视图来了,并走开。有什么可以避免的? – Sategroup 2015-09-13 08:09:09

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方法崩溃证明,并将空间@”“欺骗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委托方法和不断变化的零或空字符串到空格字符串@“”防止在空搜索栏上发生的正常隐藏/调暗。如果你正在使用这第二个代码,那么你可以修改第一个比特来传递一个零而不是@“”,因为这第二个比特会为你做所需的转换到@“”。

在我自己的项目,我需要处理的情况是用户不键入一个空格,所以不是@”“上面我用了一个定义令牌:

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

,然后在内部处理它通过将它回到零字符串:

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

Enjoy! :)

+0

这对我正在尝试做的事情非常有效。 – gplocke 2014-08-03 19:12:08

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

不过,我不喜欢这样的黑客,通过我自己的实现(用的UISearchBar UITableView中)取代了searchDisplayController。

1

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

默认情况下,只要UISearchBar中没有文本,所显示的表就会是您的原始表格视图(从现在开始称为originalTableView)。根据dimsBackgroundDuringPresentation的值,这可能有也可能没有黑色透视层。

一旦用户输入任何文本到的UISearchBar,新表视图的内容将被显示(I将把这个作为searchTableView)。

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

解决方案1:复杂的实现,平滑的动画

对于平滑的动画:

  1. 贯彻UISearchControllerDelegate的willPresentSearchController和willDismissSearchController方法。
  2. 在willPresent中,更新您的originalTableView的数据以准备好显示您想要的任何零文本数据,然后致电reloadData()
  3. 在willDismiss中,恢复过程以显示原始内容并致电reloadData()

实施例:

// 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() 
    } 
} 

在这个虚构的例子中,数据被显示为a,b,c当用户没有集中在的UISearchBar,但一旦使用者轻按的UISearchBar显示为A,B,C

解决方案2:快速实施,波涛汹涌的动画

无需实现在这两个originalTableView和searchTableView搜索控制器的逻辑,你可以使用这个解决方案简单地显示searchTableView即使它被隐藏默认。

很可能,您已经实施了UISearchResultsUpdating协议。通过在该方法中简单地调用tableView.hidden = false,您应该获得您之后的行为;尽管它的动画不如恒星。

// here tableView refers to searchTableView 

extension SearchViewController: UISearchResultsUpdating { 
    func updateSearchResultsForSearchController(searchController: UISearchController) { 
     tableView.hidden = false 
     filterData(text: searchController.searchBar.text!) 
     tableView.reloadData() 
    } 
}