我有 UITableViewController
一个UISearchBar
作为tableHeaderView
它的tableView
。我也有一个UISearchDisplayController
初始化为 that UISearchBar
as itssearchBar
和 that UITableViewController
as its contentsController
。到目前为止一切顺利,几乎一切正常。
问题是UITableView
具有accessoryType
设置为的单元格UITableViewCellAccessoryDetailDisclosureButton
。这是发生的事情:
- 首先,一切看起来都应该:
- 用户在
UISearchBar
. - 在主
UISearchDisplayController
表顶部创建深色覆盖,并使主表的索引(如,sectionIndexTitlesForTableView
)消失。 - 假设此时用户隐藏了键盘(通过按 iPad 标准键盘上的“隐藏键盘”按钮)
- 由于用户尚未在其中输入任何内容
UISearchBar
,我们仍然可以看到主表,尽管位于由UISearchDisplayController
. - 键盘的隐藏暴露了更多的主表,导致主表加载更多的单元格。
- 现在问题来了:由于这些单元格是在主表的索引被隐藏时加载的,所以显示按钮显示得太靠右了(至少,与其他单元格相比)。
- 此外,当用户现在取消搜索时,这些单元格可能不会重新加载,从而导致披露按钮显示在索引下方(现在再次可见)。
我不知道如何解决这个问题;我能想到的唯一选择是找到与公开按钮相对应的 UIView 并手动移动它,但这似乎令人难以置信,因为即使发现 UIView 也需要一个讨厌的 hack。任何有关如何以更好的方式解决此问题的建议将不胜感激!
最小可运行示例
下面是一个最小的例子。只需启动一个新的 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;
}
}