【问题标题】:UISearchBar will not respond in UISplitviewController MasterUISearchBar 在 UISplitviewController Master 中不会响应
【发布时间】:2016-09-15 03:09:49
【问题描述】:

我在UISplitviewController 和通用iOS9 应用程序中有一个非常标准的UITableview 设置作为主控制器。

同样,标准票价,我插入了UISearchBar 作为表格的标题。

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 上的一样。这肯定与拆分视图的折叠状态有关。

更新:(越来越近)

经过进一步的实验,我发现如果您在横向启动应用程序,搜索栏可以在 iPad 上运行。在纵向模式下,我的主控制器是隐藏的。它通过选择displayModeButtonItem 滑入,该leftBarButtonItem 设置为详细控制器的leftBarButtonItem。那是 searchBar 中断并且不再响应触摸的时候。

如果我从横向开始,然后旋转到纵向,它也会停止工作。旋转回横向并不能解决它。一旦坏了,它就会一直坏,直到重新启动。

我尝试将definesPresentationContext 移动到主控制器的viewWillAppear 方法,但没有效果。

进一步更新:

另外一个意想不到的情况是,iPhone 6plus 上的搜索栏完全没有问题。无论方向如何,折叠或不折叠都可以工作,并且无论它从哪个状态开始都无关紧要。我希望这与 iPad 在横向时相同。完全适用于iPhone

我还没有弄清楚这一点。我最近尝试修复,我将所有搜索控制器初始化移动到 viewDidLayoutSubviews 方法。没有任何变化。

另外,我注意到当搜索处于活动状态时,屏幕上的键盘,如果我旋转 iPad,键盘会消失,但搜索栏仍然处于活动状态。一开始我没有意识到,然后我看到取消按钮仍然显示。它不会接收触摸,也没有键盘,但它显然仍然是第一响应者。

上传到 GitHub 的示例项目: Github Repository

注意 - 在我将 UISplitview 委托方法添加到项目之前没有问题。我想立即将此添加到我的问题中,因此,我什至还没有尝试确切了解这些委托方法如何影响搜索栏,但显然问题是在某处创建的。

更新:

我尝试了更多变体,但没有成功。

  • 将搜索栏移至章节标题。不开心。
  • 将搜索栏作为内容视图放在 UIView 中。不开心。
  • 删除搜索栏消失,重新插入确实出现。不开心。
  • 调整搜索栏框架的大小以确保它不被剪裁。不开心。

我还查看了分析器中的视图层次结构,搜索栏是顶级的,没有被其他任何东西覆盖。

最终包装:

@tomSwift 解决方法确实纠正了我在 iPad 上的问题。在进一步测试中,我发现它破坏了我的 iPhone UI。据推测,这更多是我自己的设置和创建主/详细视图控制器的时间问题。似乎一些重要的对象不再及时创建,因为细节视图控制器可能还不存在。我通过将关键项目移动到 App Delegate 中进行了修复,但这变得笨拙,我无法轻松缩小范围,因此我通过以下方式破解了修复程序:

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
    splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModeAllVisible;
}

可能会有一个更优雅的解决方案,但这已经占用了我足够多的时间。现在一切正常。雷达归档- 28304096

【问题讨论】:

  • Dean,请提供一个演示项目,在此重现。
  • @LeoNatan,我确实设法重现了该问题并将示例项目上传到 github。谢谢。
  • @Dean 您的示例项目缺少文件;不会在 Xcode 中打开和构建。例如。缺少 Main.storyboard 和 LaunchScreen.storyboard
  • 我已经有一段时间没有放东西了。我会尽快检查并修复。
  • 根据this,您不应该在导航堆栈上使用 UISplitViewControllers,但您的主视图和详细视图都嵌套在导航控制器下。您可以尝试删除这些。

标签: ios uisplitviewcontroller uisearchcontroller


【解决方案1】:

这显然是UISplitViewController 和/或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];
}

【讨论】:

  • 很好,我刚刚阅读了文档 re:preferredDisplayMode 并打算自己在那里做。我将尝试您的设置、确认并查看它如何影响我的预期工作流程。希望我能忍受。
  • 在我的实际应用程序中,我按照您的建议设置了 Active:NO 但我在视图中执行此操作将在 Master 中消失。我认为这涵盖了它并将代码包含在它所属的位置。
  • 成功!这一行似乎完全解决了我的问题,并且没有严重改变我的预期 UI。非常感谢你,汤姆,看它。
  • 提交雷达:28304096
【解决方案2】:

玩弄了您的项目,发现问题在于您的搜索控制器从未设置为活动状态。因此,我将 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];
}

【讨论】:

  • 我不确定这会有什么帮助,尽管我自己没有尝试过。您是否确认在拨打电话时搜索栏已激活?无论如何,看起来您的代码会任意呈现键盘旋转,这是不可接受的。当您进行这些更改时,搜索栏是否会响应触摸?
  • 它将searchController 设置为活动状态,而不是搜索栏。是的,我实际上在模拟器中运行了代码,并尝试了两个方向
猜你喜欢
  • 1970-01-01
  • 2011-12-23
  • 1970-01-01
  • 2014-10-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多