eds*_*sko 10 uitableview uisearchbar ipad ios
我有 UITableViewController一个UISearchBar作为tableHeaderView它的tableView.我也UISearchDisplayController初始化了它UISearchBar作为它searchBar和UITableViewController它的contentsController.到目前为止一切都很好,一切都近乎有效
问题是UITableView具有accessoryType设置的单元格UITableViewCellAccessoryDetailDisclosureButton.这是发生的事情:

UISearchBar.UISearchDisplayController创建主表顶部的黑色覆盖,并使得指数(如,sectionIndexTitlesForTableView)主表中消失的.UISearchBar,我们仍然可以看到主表,尽管在黑暗叠加层下面添加了UISearchDisplayController.

我对如何解决这个问题感到茫然; 我能想到的唯一选择是找到与披露按钮相对应的UIView并手动移动它,但这看起来非常难看,只是因为即使发现UIView 需要一个讨厌的黑客.如何以更好的方式解决这个问题的任何建议将不胜感激!
最小的可运行示例
以下是一个最小的例子.只需启动一个新的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;
}
}
Run Code Online (Sandbox Code Playgroud)
如果您想模仿苹果自己的应用程序在这些情况下的行为方式,那么正确的做法是导致详细信息披露按钮在开始搜索时全部移至右侧,然后再次全部移回搜索完成。
我在您的示例中通过使用添加到代码reloadData中的两种方法调用主表视图,自己实现了这一点:UISearchDisplayDelegate
- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller
{
[[[self mainTableController] tableView] reloadData];
}
- (void)searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller
{
[[[self mainTableController] tableView] reloadData];
}
Run Code Online (Sandbox Code Playgroud)
这将迫使您的详细披露视图重新定位,以考虑表格视图索引的可见性,从而使所有披露指示符的位置无论是否处于搜索模式下都保持一致。
更新
我尝试过用其他UISearchDisplayDelegate方法重新加载表视图,包括:
- (void)searchDisplayController:(UISearchDisplayController *)controller didLoadSearchResultsTableView:(UITableView *)tableView
- (void)searchDisplayController:(UISearchDisplayController *)controller willUnloadSearchResultsTableView:(UITableView *)tableView
Run Code Online (Sandbox Code Playgroud)
但是,这些会产生相当不和谐的效果,详细信息披露按钮的位置会突然跳跃,因此我建议使用前面所述的willBeginSearch和willEndSearch方法。