我遇到了和你一样的问题,花了几个小时寻找解决方案。最终,我以UISearchDisplayController
编程方式创建。
我在其中创建一个SearchTableViewController
,Storyboard
然后以编程方式完成其余的工作。正如您将在下面提供的代码中注意到的那样,控制器委托必须包含在标头中。现在有趣的事情发生在我创建searchBar
. 请注意我从未设置它的委托?当UISearchDisplayController
我使用searchBar
. 然后我只需要为 和 设置委托和UISearchDislpayController
源searchResults
;我在创建控制器后立即执行此操作。我无法为您提供关于“为什么”在代码中创建并设置searchBar
为时在视图中居中的答案,但我遇到了同样的问题,并发现以下是一个可行的解决方案。特别是考虑到我从来不需要调整任何大小:)Storyboard
displaysSearchBarInNavigationBar:YES
SearchTableViewController.h
#import <UIKit/UIKit.h>
@interface SearchableTableViewController : UITableViewController<UISearchDisplayDelegate>
//I only need the SearchDisplayController Delegate because it magically has all the needed child delegates. :)
@end
SearchTableViewController.m
#import "SearchDisplayController.h"
@property (strong,nonatomic) IBOutlet UITableView *acSearchTableView;
@property (retain,nonatomic) UISearchBar *acSearchBar;
@property (retain,nonatomic) UISearchDisplayController *searchDsplyCntrl;
@property (strong,nonatomic) NSArray *unfilteredResults;
@property (strong,nonatomic) NSMutableArray *filteredResults;
@implementation SearchTableViewController
- (void) viewDidLoad {
[super viewDidLoad];
_acSearchBar = [[UISearchBar alloc]init];
_acSearchBar.showsCancelButton = NO;
/* NOTE: by default the placholer is centered. It can be left aligned with spaces */
_acSearchBar.placeholder = @"Search ";
_searchDsplyCntrl = [[UISearchDisplayController alloc]initWithSearchBar:_acSearchBar contentsController:self];
_searchDsplyCntrl.delegate = self;
_searchDsplyCntrl.searchResultsDelegate = self;
_searchDsplyCntrl.searchResultsDataSource = self;
_searchDsplyCntrl.displaysSearchBarInNavigationBar = YES;
_unfilteredResults = [[NSArray alloc]initWithObjects:
[ResultObj resultWithName:@"first"],
[ResultObj resultWithName:@"second"],
[ResultObj resultWithName:@"third"],
[ResultObj resultWithName:@"forth"],
[ResultObj resultWithName:@"fifth"],
[ResultObj resultWithName:@"sixth"],
[ResultObj resultWithName:@"seventh"],
[ResultObj resultWithName:@"eigth"],nil];
_filteredResults = [NSMutableArray arrayWithCapacity:[_unfilteredResults count]];
[_acSearchTableView reloadData];
}
- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller {
[_searchDsplyCntrl setActive:YES animated:YES];
[_searchDsplyCntrl.searchBar setShowsCancelButton:YES animated:YES];
}
- (void)searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller {
[_searchDsplyCntrl setActive:NO animated:YES];
[_searchDsplyCntrl.searchBar setShowsCancelButton:NO animated:YES];
}
导航栏中显示的搜索栏不能有范围栏。
重要如果在导航栏中显示的搜索栏中将 showsScopeBar 属性设置为 YES,系统将引发异常。
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (tableView == _searchDsplyCntrl.searchResultsTableView)
{
return [_filteredResults count];
}
else
{
return [_unfilteredResults count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if ( cell == nil ) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Create a new Candy Object
ResultObj *result = nil;
// Check to see whether the normal table or search results table is being displayed and set the Candy object from the appropriate array
if (tableView == _searchDsplyCntrl.searchResultsTableView)
{
result = [_filteredResults objectAtIndex:[indexPath row]];
}
else
{
result = [_unfilteredResults objectAtIndex:[indexPath row]];
}
// Configure the cell
[[cell textLabel] setText:[result name]];
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
return cell;
}
#pragma mark Content Filtering
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
// Update the filtered array based on the search text and scope.
// Remove all objects from the filtered search array
[_filteredResults removeAllObjects];
// Filter the array using NSPredicate
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF.name contains[c] %@",searchText];
NSArray *tempArray = [_unfilteredResults filteredArrayUsingPredicate:predicate];
/*
if(![scope isEqualToString:@"All"]) {
// Further filter the array with the scope
NSPredicate *scopePredicate = [NSPredicate predicateWithFormat:@"SELF.category contains[c] %@",scope];
tempArray = [tempArray filteredArrayUsingPredicate:scopePredicate];
}
*/
_filteredResults = [NSMutableArray arrayWithArray:tempArray];
}
#pragma mark - UISearchDisplayController Delegate Methods
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
// Tells the table data source to reload when text changes
[self filterContentForSearchText:searchString scope:
[[_searchDsplyCntrl.searchBar scopeButtonTitles] objectAtIndex:[_searchDsplyCntrl.searchBar selectedScopeButtonIndex]]];
// Return YES to cause the search result table view to be reloaded.
return YES;
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption
{
// Tells the table data source to reload when scope bar selection changes
[self filterContentForSearchText:[_searchDsplyCntrl.searchBar text] scope:
[[_searchDsplyCntrl.searchBar scopeButtonTitles] objectAtIndex:searchOption]];
// Return YES to cause the search result table view to be reloaded.
return YES;
}