可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Usually, a UISearchDisplayController, when activated, dims the tableView and focuses the searchBar. As soon as you enter text into the searchBar, it creates a searchResultsTableView that displays between the searchBar and the keyboard. The searchDisplayController's delegate gets called when this second UITableView is loaded/shown/hidden/unloaded. Usually it shows live search results or autocompletion entries while typing.
In my app, I want to search a webservice and I don't want to call the webservice for each letter the user enters. Therefore, I want to entirely disable the searchResultsTableView and keep the dimmed black overlay while he enters text. I would then trigger the search (with a loading screen) once he hits the search button.
Just returning zero rows for the searchResultsTableView doesn't look nice since it displays an empty searchResultsTableView with a "no results" message. I tried to hide the table when it appears (searchDisplayController:didLoadSearchResultsTableView:
) which works, but the blacked dimmed overlay is also hidden so that the underlying tableView is completely visible again.
Any ideas besides recreating the UISearchDisplayController functionality from scratch?
回答1:
here is a little trick that i just figured out
and also you have to return 0 results while editing searchstring
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
savedSearchTerm = searchString;
[controller.searchResultsTableView setBackgroundColor:[UIColor colorWithWhite:0.0 alpha:0.8]];
[controller.searchResultsTableView setRowHeight:800];
[controller.searchResultsTableView setScrollEnabled:NO];
return NO;
}
- (void)searchDisplayController:(UISearchDisplayController *)controller didHideSearchResultsTableView:(UITableView *)tableView
{
// undo the changes above to prevent artefacts reported below by mclin
}
i think you'll figure out what to do next
回答2:
Have you tried this:
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(_lookup:) object:nil];
[self performSelector:@selector(_lookup:) withObject:txt afterDelay:0.20];
This way, if the user types another char within 1/5sec, you only make one web call.
回答3:
Nothing of the above seemed to work well in the end, so I came up with the following (you have to call removeTableHeader when you are ready to display your results):
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar {
[self setTableHeader];
}
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
[self setTableHeader];
}
- (void)setTableHeader {
UIView *headerView = [[UIView alloc] initWithFrame:self.searchDisplayController.searchResultsTableView.frame];
headerView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.8];
[self.searchDisplayController.searchResultsTableView setBackgroundColor:[UIColor clearColor]];
[self.searchDisplayController.searchResultsTableView setScrollEnabled:NO];
[self.searchDisplayController.searchResultsTableView setTableHeaderView:headerView];
[headerView release];
}
- (void)removeTableHeader {
[self.searchDisplayController.searchResultsTableView setBackgroundColor:[UIColor whiteColor]];
[self.searchDisplayController.searchResultsTableView setScrollEnabled:YES];
[self.searchDisplayController.searchResultsTableView setTableHeaderView:nil];
}
Obviously, it make the table transparent, adds a black/translucent table header with the same size as the table, and disables scrolling on the table so you cannot get above or past the header. As a bonus, you could add something to the header view ('please wait...' or an activity indicator).
回答4:
Had the same problem as you, I handled it by a) setting the alpha of the searchResultsTableView to 0 when beginning searching, and then by b) adding/removing the overlayView to the viewController's view. Works like a charm for me.
@interface MyViewController()
//...
@property(nonatomic, retain) UIView *overlayView;
//...
@end
@implementation MyViewController
@synthesize overlayView = _overlayView;
//...
- (void)viewDidLoad
{
//...
//define your overlayView
_overlayView = [[UIView alloc] initWithFrame:CGRectMake(0, 44, 320, 480)];
_overlayView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.8];
}
//hide the searchResultsTableView
- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller
{
self.searchDisplayController.searchResultsTableView.alpha = 0.0f;
}
//when ending the search, hide the overlayView
- (void) searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller
{
[_overlayView removeFromSuperview];
}
//depending on what the user has inputed, add or remove the overlayView to the view of the current viewController
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
if ([searchString length]>0)
{
[self.view addSubview:_overlayView];
}
else
{
[_overlayView removeFromSuperview];
}
return NO;
}
@end
回答5:
it should be sufficient to implement the following method in your UISearchDisplayDelegate (which usually is your custom UITableViewController subclass)
- (BOOL) searchDisplayController: (UISearchDisplayController *) controller shouldReloadTableForSearchString: (NSString *) searchString
{
[self startMyCustomWebserviceSearchAsBackgroundProcessForString: searchString]; //starts new NSThread
return NO;
}
have you tried this?
回答6:
Based on user182820's code below is my version. I hide the UISearchDisplayController's table view. When a character is entered in the search box I place a 'dimmed view' so it looks like UISearchDisplayController's 'dimmed view' never went away and then remove it when the search is finished. If you enter some characters and press cancel, the table view briefly goes all white and I don't know how to get around this.
- (void)viewDidLoad {
...
tableViewMask=[UIView new];
tableViewMask.backgroundColor = [UIColor blackColor];
tableViewMask.alpha = 0.8;
}
- (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller{
tableViewMask.frame=CGRectMake(self.tableView.frame.origin.x, self.tableView.frame.origin.y+controller.searchBar.frame.size.height, self.tableView.frame.size.width, self.tableView.frame.size.height-controller.searchBar.frame.size.height);
controller.searchResultsTableView.hidden=YES;
}
- (void)searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller{
[tableViewMask removeFromSuperview];
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString{
if (searchString.length==0)
[tableViewMask removeFromSuperview];
else
[self.tableView addSubview:tableViewMask];
[searchText autorelease];
searchText=[searchString retain];
return NO;
}
回答7:
What about just doing it as simple as this:
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
self.searchDisplayController.searchResultsTableView.hidden=YES;
return YES;
}
Works fine for me..
回答8:
I foud a better way, since there is a bug with the "best answer" - the separator and the "No Results" will be shown when scrolling the black background table.
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
controller.searchResultsTableView.backgroundColor = [UIColor blackColor];
controller.searchResultsTableView.alpha = 0.8;
controller.searchResultsTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
for(UIView *subview in tableView.subviews) {
if([subview isKindOfClass:UILabel.class]) {
subview.hidden = YES;
}
}
return NO;
}
- (void) searchBarSearchButtonClicked:(UISearchBar *)searchBar {
self.searchDisplayController.searchResultsTableView.backgroundColor = [UIColor whiteColor];
self.searchDisplayController.searchResultsTableView.alpha = 1;
self.searchDisplayController.searchResultsTableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
for(UIView *subview in tableView.subviews) {
if([subview isKindOfClass:UILabel.class]) {
subview.hidden = NO;
}
}
// search results and reload data ....
}
回答9:
All of the existing answers are overly complicated. You can get away by just hiding the results table view immediately.
-(void)searchDisplayController:(UISearchDisplayController *)controller didShowSearchResultsTableView:(UITableView *)tableView
{
tableView.hidden = YES;
}
回答10:
I think I found a better implementation for this problem. All the previous answers correctly show a dimmed view identical to what the UITableView looks like before a search, but each solution lacks the functionality to tap the area in order to cancel the search.
For that reason I think this code works better.
First of all, create a BOOL such as searchButtonTapped to indicate whether the search button was tapped. By default it is NO.
Then:
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
if (!searchButtonTapped) {
// To prevent results from being shown and to show an identical look to how the tableview looks before a search
[controller.searchResultsTableView setBackgroundColor:[UIColor clearColor]];
[controller.searchResultsTableView setRowHeight:160];
self.searchDisplayController.searchResultsTableView.scrollEnabled = NO;
} else {
// Restore original settings
[controller.searchResultsTableView setBackgroundColor:[UIColor whiteColor]];
[controller.searchResultsTableView setRowHeight:44];
self.searchDisplayController.searchResultsTableView.scrollEnabled = YES;
}
return YES;
}
This should be clear now based on the other answers. Make sure to also restore the original settings when the user taps on the Search button.
Furthermore, in the cellForIndexPath method add:
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.contentView.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.8];
In order to create the same dimmed view that is shown before text is entered. Make sure you apply these properties to the right cell, i.e., check which UITableView is active and that the user has not tapped the Search button.
Then, crucially, in didSelectRowAtIndexPath:
if (tableView == self.searchDisplayController.searchResultsTableView) {
if (searchButtonTapped) {
// Code for when the user select a row after actually having performed a search
{
else
[self.searchDisplayController setActive:NO animated:YES];
Now the user can tap the dimmed area, which will not result in a visible selection of a UITableViewCell, but instead cancels the search.