У меня UITableViewController
с UISearchBar
как tableHeaderView
его tableView
. У меня также есть UISearchDisplayController
, инициализированный тем, что UISearchBar
как его searchBar
, и UITableViewController
как его contentsController
. Пока все хорошо, все почти работает.
Проблема в том, что UITableView
имеет ячейки, у которых их accessoryType
установлен на UITableViewCellAccessoryDetailDisclosureButton
. Вот что происходит:
- Чтобы начать, все выглядит так, как должно:
- Пользователь забирает внутри
UISearchBar
. -
UISearchDisplayController
создает темную надпись поверх основной таблицы и уменьшает индекс (как вsectionIndexTitlesForTableView
) основной таблицы. - Предположим, что пользователь в этот момент скрывает клавиатуру (нажав кнопку "Скрыть клавиатуру iPad" на стандартной клавиатуре)
- Так как пользователь еще ничего не набрал в
UISearchBar
, мы все равно можем видеть основную таблицу, хотя и под темным наложением, добавленнымUISearchDisplayController
. - Скрытие клавиатуры предоставляет большую часть основной таблицы, заставляя основную таблицу загружать больше ячеек.
- Теперь вот проблема: Так как эти ячейки загружаются, когда указатель главной таблицы скрыт, кнопка раскрытия отображается слишком далеко справа (по крайней мере, по сравнению с другими ячейками).
- Кроме того, когда пользователь отменяет поиск, эти ячейки не могут быть перезагружены, что приведет к тому, что кнопка раскрытия будет показана под индексом (который теперь снова отображается).
Я не понимаю, как обойти это; единственный вариант, о котором я могу думать, - найти UIView, который соответствует кнопке раскрытия и вручную переместить его, но это кажется невероятно взломанным, хотя бы потому, что даже если найти UIView требует неприятного взлома. Любые предложения о том, как исправить это лучше, будут очень благодарны!
Минимальный пример runnable
Ниже приведен минимальный пример. Просто запустите новый проект XCode, включите только ARC, iPad и замените содержимое AppDelegate ниже. Обратите внимание, что для минимального примера я заставляю основную таблицу перезагружать свои ячейки в searchDisplayController:willShowSearchResultsTableView
, в противном случае основная таблица будет кэшировать его ячейки, и проблема не будет отображаться (в моем фактическом приложении основная таблица перезагружает свои ячейки по другим причинам, я не совсем уверен, почему, но, конечно, должно быть хорошо, если основная таблица будет перезагружать ячейки в любое время.)
Чтобы увидеть проблему, запустите код, введите что-то в поле поиска (вы увидите "Результат поиска 0.. 5" ), а затем отмените поиск. Кнопки раскрытия основной таблицы теперь отображаются ниже, а не рядом с индексом.
Ниже приведен только код:
@interface AppDelegate ()
@property (nonatomic, strong) UITableViewController* mainTableController;
@property (nonatomic, strong) UISearchDisplayController* searchDisplay;
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
UITableViewController* tableViewController = [[UITableViewController alloc] initWithStyle:UITableViewStylePlain];
UITableView* tableView = [tableViewController tableView];
[tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"Cell"];
[tableView setDataSource:self];
[self setMainTableController:tableViewController];
UISearchBar* searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 0, 44)]; // Width set automatically
[tableView setTableHeaderView:searchBar];
UISearchDisplayController* searchDisplay = [[UISearchDisplayController alloc] initWithSearchBar:searchBar
contentsController:tableViewController];
[searchDisplay setSearchResultsDataSource:self];
[searchDisplay setDelegate:self];
[self setSearchDisplay:searchDisplay];
[[self window] setRootViewController:tableViewController];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
#pragma mark Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
if (tableView != [[self searchDisplay] searchResultsTableView]) {
return 26;
} else {
return 1;
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (tableView != [[self searchDisplay] searchResultsTableView]) {
return 10;
} else {
return 5;
}
}
- (void)searchDisplayController:(UISearchDisplayController *)controller willShowSearchResultsTableView:(UITableView *)tableView {
// The problem arises only if the main table view needs to reload its data
// In this minimal example, we force this to happen
[[[self mainTableController] tableView] reloadData];
[tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"SearchCell"];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (tableView != [[self searchDisplay] searchResultsTableView]) {
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
[[cell textLabel] setText:[NSString stringWithFormat:@"%c%d", 'A' + [indexPath section], [indexPath row]]];
[cell setAccessoryType:UITableViewCellAccessoryDetailDisclosureButton];
return cell;
} else {
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:@"SearchCell" forIndexPath:indexPath];
[[cell textLabel] setText:[NSString stringWithFormat:@"Search result %d", [indexPath row]]];
[cell setAccessoryType:UITableViewCellAccessoryDetailDisclosureButton];
return cell;
}
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
if (tableView != [[self searchDisplay] searchResultsTableView]) {
return [NSArray arrayWithObjects:@"A", @"B", @"C", @"D", @"E", @"F", @"G", @"H", @"I", @"J", @"K", @"L", @"M", @"N", @"O", @"P", @"Q", @"R", @"S", @"T", @"U", @"V", @"W", @"X", @"Y", @"Z", nil];
} else {
return nil;
}
}