UISearchBar 在 UISplitviewController Master 中不会响应
UISearchBar will not respond in UISplitviewController Master
我有一个非常标准的设置 UITableview
作为 UISplitviewController
中的主控制器,通用 iOS9
应用程序。
同样,标准票价,我插入了一个UISearchBar
作为table的header。
self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
self.searchController.searchResultsUpdater = self;
self.searchController.dimsBackgroundDuringPresentation = NO;
self.searchController.hidesNavigationBarDuringPresentation = NO;
[self.searchController.searchBar sizeToFit];
self.tableView.tableHeaderView = self.searchController.searchBar;
self.definesPresentationContext = YES;
无需在 iPhone
上显示我的其余代码、搜索和所有预期工作。我的问题是,当 iPad
上的 运行 时,搜索栏永远不会获得焦点或显示键盘。没有反应,似乎没有收到触摸。甚至不响应以编程方式尝试 becomeFirstResponder
.
没有任何反应。
搜索栏可见且放置适当,没有底层或重叠问题。
它在 iPhone
上运行良好。接收触摸,呈现键盘,搜索工作。据推测,当 UISplitviewController
折叠时,呈现方式存在重大差异。经过数小时的搜索、大量的文档和我遇到的每个教程,我没有找到类似的经历,这令人惊讶。
补充说明:如果我在 iPad 上使用多任务处理将拆分视图缩小到折叠状态,搜索栏就会起作用,与在 iPhone
上一样。肯定和split view的折叠状态有关
更新:(越来越近)
经过进一步试验,我发现如果您横向启动应用程序,搜索栏可以在 iPad 上运行。在纵向模式下,我的主控制器是隐藏的。它通过选择 displayModeButtonItem
滑入,该 displayModeButtonItem
设置为细节控制器的 leftBarButtonItem
。那就是当 searchBar 中断并且不再响应触摸时。
如果我从横向开始,然后旋转到纵向,它也会停止工作。旋转回横向并不能解决问题。一旦坏了,它就会一直坏到重新启动。
我尝试将 definesPresentationContext
移动到主控制器的 viewWillAppear
方法,但是没有效果。
进一步更新:
另外一个意想不到的情况是iPhone6plus的搜索栏完全没有问题。无论方向如何,折叠或不折叠都可以工作,也不管它从哪个状态开始。我希望这与横向时的 iPad 相同。完全适用于 iPhone
.
我还是没弄明白。我最近的修复尝试是将所有搜索控制器初始化移至 viewDidLayoutSubviews
方法。没有任何变化。
此外,我注意到当搜索处于活动状态时,屏幕上的键盘,如果我旋转 iPad,键盘就会消失,但搜索栏仍然处于活动状态。一开始我没发现,然后我看到取消按钮仍然显示。它不会接收触摸并且没有键盘,但它显然仍然是第一响应者。
上传到 GitHub 的示例项目:
Github Repository
注意 - 在我将 UISplitview Delegate 方法添加到项目之前没有任何问题。我想立即将其添加到我的问题中,因此,我什至还没有尝试确切地了解这些委托方法如何影响搜索栏,但显然问题是在某处产生的。
更新:
我尝试了更多变体但没有成功。
- 将搜索栏移至 header 部分。不开心。
- 将搜索栏作为内容视图放在 UI 视图中。不开心。
- 在消失时删除搜索栏,在出现时重新插入。不开心。
- 调整搜索栏框架的大小以确保它不被剪裁。不开心。
我还查看了分析器中的视图层次结构,搜索栏位于顶层,未被其他任何内容覆盖。
最终包装:
@tomSwift 解决方法确实解决了我在 iPad 上的问题。在进一步测试中,我发现它破坏了我的 iPhone UI。据推测,这更多是我自己的设置和创建 Master/Detail 视图控制器的时间问题。似乎一些重要的 objects 不再及时创建,因为可能细节视图控制器还不存在。我通过将关键项目移动到 App Delegate 来解决问题,但这变得笨拙而且我无法轻易缩小范围,所以我破解了一个修复程序:
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModeAllVisible;
}
可能会有更优雅的解决方案,但这已经占用了我足够多的时间。现在一切正常。雷达归档- 28304096
这显然是 UISplitViewController
and/or UISearchController
中的错误。一定要用 Apple 提交一份雷达并附上你的代码示例。
我认为该错误涉及 UISplitViewController.displayMode UISplitViewControllerDisplayModeAutomatic
。当我将 preferredDisplayMode
更改为 UISplitViewControllerDisplayModeAllVisible
然后一切开始工作:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
UINavigationController *navigationController = [splitViewController.viewControllers lastObject];
navigationController.topViewController.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem;
splitViewController.delegate = self;
splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModeAllVisible;
return YES;
}
此更改的主要内容是 iPad 上纵向的默认布局,据我所知这可能并不理想。我还尝试将 preferredDisplayMode
设置为 UISplitViewControllerDisplayModeAllVisible
,然后将其设置回 UISplitViewControllerDisplayModeAutomatic
;在屏幕方向改变之前,这一直很好用——然后它又坏了。你可能会在这条路上走得更远。
我还在 AppDelegate
中添加了以下内容,以强制搜索控制器在 displayMode
更改时停用。 (我还必须在 MasterViewController 上公开公开 searchController
属性)。
- (void)splitViewController:(UISplitViewController *)svc willChangeToDisplayMode:(UISplitViewControllerDisplayMode)displayMode {
UINavigationController *navigationController = [svc.viewControllers firstObject];
MasterViewController* mvc = (MasterViewController*) navigationController.topViewController;
[mvc.searchController setActive: NO];
}
研究了您的项目,发现问题在于您的搜索控制器从未设置为活动状态。所以我将 UISplitViewController 子类化并使其成为自己的委托,这样它就可以在模式更改时通知子视图控制器,这样您就可以在正确的时间将其设置为活动状态。
使用此委托方法创建通知:
- (void)splitViewController:(UISplitViewController *)svc willChangeToDisplayMode:(UISplitViewControllerDisplayMode)displayMode {
NSLog(@"WILL CHANGE TO DISPLAY MODE: %ld", (long)displayMode);
NSNumber *displayNumber = [NSNumber numberWithInteger:displayMode];
NSDictionary *userInfo = @{ @"displayMode": displayNumber };
NSNotification *modeChangedNotif = [NSNotification notificationWithName:@"modeChanged" object:nil userInfo:userInfo];
[[NSNotificationCenter defaultCenter] postNotification:modeChangedNotif];
}
然后在您的 MasterViewController 中,您可以在 viewDidLoad
中执行此操作:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(modeChanged) name:@"modeChanged" object:nil];
在该方法中,您可以检查特定的 displayMode 枚举,但为了让它正常工作,我只是这样做了:
- (void) modeChanged {
[self.searchController setActive:YES];
}
我有一个非常标准的设置 UITableview
作为 UISplitviewController
中的主控制器,通用 iOS9
应用程序。
同样,标准票价,我插入了一个UISearchBar
作为table的header。
self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
self.searchController.searchResultsUpdater = self;
self.searchController.dimsBackgroundDuringPresentation = NO;
self.searchController.hidesNavigationBarDuringPresentation = NO;
[self.searchController.searchBar sizeToFit];
self.tableView.tableHeaderView = self.searchController.searchBar;
self.definesPresentationContext = YES;
无需在 iPhone
上显示我的其余代码、搜索和所有预期工作。我的问题是,当 iPad
上的 运行 时,搜索栏永远不会获得焦点或显示键盘。没有反应,似乎没有收到触摸。甚至不响应以编程方式尝试 becomeFirstResponder
.
没有任何反应。
搜索栏可见且放置适当,没有底层或重叠问题。
它在 iPhone
上运行良好。接收触摸,呈现键盘,搜索工作。据推测,当 UISplitviewController
折叠时,呈现方式存在重大差异。经过数小时的搜索、大量的文档和我遇到的每个教程,我没有找到类似的经历,这令人惊讶。
补充说明:如果我在 iPad 上使用多任务处理将拆分视图缩小到折叠状态,搜索栏就会起作用,与在 iPhone
上一样。肯定和split view的折叠状态有关
更新:(越来越近)
经过进一步试验,我发现如果您横向启动应用程序,搜索栏可以在 iPad 上运行。在纵向模式下,我的主控制器是隐藏的。它通过选择 displayModeButtonItem
滑入,该 displayModeButtonItem
设置为细节控制器的 leftBarButtonItem
。那就是当 searchBar 中断并且不再响应触摸时。
如果我从横向开始,然后旋转到纵向,它也会停止工作。旋转回横向并不能解决问题。一旦坏了,它就会一直坏到重新启动。
我尝试将 definesPresentationContext
移动到主控制器的 viewWillAppear
方法,但是没有效果。
进一步更新:
另外一个意想不到的情况是iPhone6plus的搜索栏完全没有问题。无论方向如何,折叠或不折叠都可以工作,也不管它从哪个状态开始。我希望这与横向时的 iPad 相同。完全适用于 iPhone
.
我还是没弄明白。我最近的修复尝试是将所有搜索控制器初始化移至 viewDidLayoutSubviews
方法。没有任何变化。
此外,我注意到当搜索处于活动状态时,屏幕上的键盘,如果我旋转 iPad,键盘就会消失,但搜索栏仍然处于活动状态。一开始我没发现,然后我看到取消按钮仍然显示。它不会接收触摸并且没有键盘,但它显然仍然是第一响应者。
上传到 GitHub 的示例项目: Github Repository
注意 - 在我将 UISplitview Delegate 方法添加到项目之前没有任何问题。我想立即将其添加到我的问题中,因此,我什至还没有尝试确切地了解这些委托方法如何影响搜索栏,但显然问题是在某处产生的。
更新:
我尝试了更多变体但没有成功。
- 将搜索栏移至 header 部分。不开心。
- 将搜索栏作为内容视图放在 UI 视图中。不开心。
- 在消失时删除搜索栏,在出现时重新插入。不开心。
- 调整搜索栏框架的大小以确保它不被剪裁。不开心。
我还查看了分析器中的视图层次结构,搜索栏位于顶层,未被其他任何内容覆盖。
最终包装:
@tomSwift 解决方法确实解决了我在 iPad 上的问题。在进一步测试中,我发现它破坏了我的 iPhone UI。据推测,这更多是我自己的设置和创建 Master/Detail 视图控制器的时间问题。似乎一些重要的 objects 不再及时创建,因为可能细节视图控制器还不存在。我通过将关键项目移动到 App Delegate 来解决问题,但这变得笨拙而且我无法轻易缩小范围,所以我破解了一个修复程序:
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModeAllVisible;
}
可能会有更优雅的解决方案,但这已经占用了我足够多的时间。现在一切正常。雷达归档- 28304096
这显然是 UISplitViewController
and/or UISearchController
中的错误。一定要用 Apple 提交一份雷达并附上你的代码示例。
我认为该错误涉及 UISplitViewController.displayMode UISplitViewControllerDisplayModeAutomatic
。当我将 preferredDisplayMode
更改为 UISplitViewControllerDisplayModeAllVisible
然后一切开始工作:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
UINavigationController *navigationController = [splitViewController.viewControllers lastObject];
navigationController.topViewController.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem;
splitViewController.delegate = self;
splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModeAllVisible;
return YES;
}
此更改的主要内容是 iPad 上纵向的默认布局,据我所知这可能并不理想。我还尝试将 preferredDisplayMode
设置为 UISplitViewControllerDisplayModeAllVisible
,然后将其设置回 UISplitViewControllerDisplayModeAutomatic
;在屏幕方向改变之前,这一直很好用——然后它又坏了。你可能会在这条路上走得更远。
我还在 AppDelegate
中添加了以下内容,以强制搜索控制器在 displayMode
更改时停用。 (我还必须在 MasterViewController 上公开公开 searchController
属性)。
- (void)splitViewController:(UISplitViewController *)svc willChangeToDisplayMode:(UISplitViewControllerDisplayMode)displayMode {
UINavigationController *navigationController = [svc.viewControllers firstObject];
MasterViewController* mvc = (MasterViewController*) navigationController.topViewController;
[mvc.searchController setActive: NO];
}
研究了您的项目,发现问题在于您的搜索控制器从未设置为活动状态。所以我将 UISplitViewController 子类化并使其成为自己的委托,这样它就可以在模式更改时通知子视图控制器,这样您就可以在正确的时间将其设置为活动状态。
使用此委托方法创建通知:
- (void)splitViewController:(UISplitViewController *)svc willChangeToDisplayMode:(UISplitViewControllerDisplayMode)displayMode {
NSLog(@"WILL CHANGE TO DISPLAY MODE: %ld", (long)displayMode);
NSNumber *displayNumber = [NSNumber numberWithInteger:displayMode];
NSDictionary *userInfo = @{ @"displayMode": displayNumber };
NSNotification *modeChangedNotif = [NSNotification notificationWithName:@"modeChanged" object:nil userInfo:userInfo];
[[NSNotificationCenter defaultCenter] postNotification:modeChangedNotif];
}
然后在您的 MasterViewController 中,您可以在 viewDidLoad
中执行此操作:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(modeChanged) name:@"modeChanged" object:nil];
在该方法中,您可以检查特定的 displayMode 枚举,但为了让它正常工作,我只是这样做了:
- (void) modeChanged {
[self.searchController setActive:YES];
}