UISearchDisplayController.displaysSearchBarInNavigationBar позиционирует строку поиска в середине окна
Я пытаюсь использовать свойство displaysSearchBarInNavigationBar
в классе iOS7 UISearchDisplayController
для отображения строки поиска внутри панели навигации.
Используя пример AdvancedTableSearch от Apple в качестве базы, я изменил код, чтобы отключить области (которые не разрешены в панели навигации ) и установите displaysSearchBarInNavigationBar
в true, например.
- (void)viewDidLoad
{
[super viewDidLoad];
// create a mutable array to contain products for the search results table
self.searchResults = [NSMutableArray arrayWithCapacity:[self.products count]];
self.searchDisplayController.displaysSearchBarInNavigationBar = YES;
}
К сожалению, результат, который я получаю, выглядит следующим образом:
![search bar in the wrong place]()
Строка поиска отображается в середине экрана, а не в элементе navigation.txt.
Что я делаю неправильно?
PS: Я не уверен, связано ли это, но self.searchDisplayController.navigationItem
свойство nil
.
Ответы
Ответ 1
Удалите строку поиска из представления таблицы. Использование displaysSearchBarInNavigationBar
означает, что UISearchDisplayController позаботится о том, чтобы разместить в строке поиска строку поиска.
Кроме того, navigationItem
будет равно nil, пока displaysSearchBarInNavigationBar
не будет установлено значение YES. Элемент создается только при необходимости.
Ответ 2
У меня была такая же проблема, как и у вас, и потратил часы на поиск решения. В конечном итоге я пошел с созданием 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];
}
Строка поиска, отображаемая на панели навигации, не может иметь панель видимости.
ВАЖНО Система создает исключение, если вы устанавливаете showScopeBar свойство 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;
}