iOS UISearchController 崩溃:应用程序试图在自身上呈现模态视图控制器

Posted

技术标签:

【中文标题】iOS UISearchController 崩溃:应用程序试图在自身上呈现模态视图控制器【英文标题】:iOS UISearchController crash: Application tried to present modal view controller on itself 【发布时间】:2017-10-24 18:47:52 【问题描述】:

根据 crashlytics,以下崩溃正在发生(很少)。

应用程序试图在自身上呈现模态视图控制器。 呈现控制器是。

我根本无法复制这个问题。这就是我设置 UISearch 控制器的方式。

    self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
    self.searchController.dimsBackgroundDuringPresentation = NO;
    self.searchController.searchBar.delegate = self;

    self.tableView.tableHeaderView = self.searchController.searchBar;
    self.definesPresentationContext = YES;

感谢任何帮助,因为我完全没有想法。如果需要,我会发布更多代码。

【问题讨论】:

究竟是哪一行导致它崩溃?您尝试在哪里展示有问题的视图控制器? 您的设置是标准的 - 我们需要更多上下文来帮助您,例如导致错误的转换。您可以在调试器中捕获异常吗?我见过这样的错误是由 UISearchControllerDelegate 方法中的操作引起的,这些操作试图改变当前的搜索。 【参考方案1】:

我在更新到 ios 11 时遇到了这个问题。 我的场景是,我有一个 Textfield,当用户开始编辑它时,会弹出一个搜索视图,本质上是一个带有搜索栏作为标题的表格视图,一旦点击表格视图单元格,它就会关闭。

问题似乎是从 iOS 11 开始,操作系统试图恢复 firstResponder 状态。长话短说。

当我将 active = NO, 添加到我的选择方法时,它会有所帮助,就像这样

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
   self.searchController.active = NO; // Add this !
   ...

   [self dismissViewControllerAnimated:YES completion:nil];

【讨论】:

奇怪的是,active = NO 是导致我崩溃的原因。删除这条线,我的应用程序不再崩溃。写这篇文章的时间是 2017 年 12 月 19 日。也许苹果用最新的更新修复了它。 是的。奇怪的是我的代码仍然有效:-/ 所以我在 iOS 11.4、11.4.1 中也遇到了这个问题(至少在现场的崩溃日志中)。我能够重现并修复它。就我而言,我有两个 VC。 VC1 显示搜索控制器并以模态方式显示 VC2。用户点击 VC2 中的一个按钮,它就会消失(通过dismiss()),然后VC1 消失(通过dismiss())。如果 searchController 在 VC1 上处于活动状态,则此断言失败发生在 VC1 调用 dismiss() 之后。我在dismiss()之前通过searchController.isActive = false修复了它。 我为这个问题苦苦挣扎了三天!!非常感谢! 这个问题在 iOS 13.4.1 中依然存在。我的应用程序在现场报告了这个问题,我使用 Kastor 建议的修复程序修复了它。谢谢你..【参考方案2】:

如果您像我一样需要 searchController 在模态显示另一个控制器时保持活动,那么请执行以下操作以获得与模态显示相同的效果而不直接这样做:

快速说明:对 Obj-C 不够熟悉,无法给出答案,但这是 Swift 4 中的答案。如有必要,有人可以随意编辑和添加 Obj-C,但我认为这里很清楚如何解决手头的问题,即使它是在 Swift 中。

假设我有一个要弹出的菜单:

let info = the info you need to pass
let currVC = self.getTopMostViewController()
let menuVC = currVC.storyboard?.instantiateViewController(withIdentifier: "myStringIdentifierSetInStoryboard") as? EventMenuViewController
guard menuVC != nil else  return 
menuVC!.info = info // Pass info necessary (i.e. what you would normally pass in prepare(for segue: ...). menuVC.info is a global variable from your class
currVC.present(menuVC!, animated: true, completion: nil)

getTopMostViewController() 的实现可能会有所不同。我的在下面,改编自here。

func getTopMostViewController() -> UIViewController 
    let anyVC = UIViewController()
    if var topController = UIApplication.shared.keyWindow?.rootViewController 
        while let presentedViewController = topController.presentedViewController 
            topController = presentedViewController
        
        return topController
    
    return anyVC

希望这会有所帮助!这并没有给你描述为 iOS 12 和 Swift 4 描述的错误,尽管我在尝试使用活动搜索控制器以模态方式呈现时确实遇到了那个确切的错误,这就是导致我来到这里的原因。

【讨论】:

【参考方案3】:

确保你使用

self.searchController = UISearchController()

而不是

self.searchController = UISearchController(searchResultsController: self)

【讨论】:

以上是关于iOS UISearchController 崩溃:应用程序试图在自身上呈现模态视图控制器的主要内容,如果未能解决你的问题,请参考以下文章

为啥 iOS viewPager 与 UISearchController 崩溃?

iOS UISearchController 崩溃:应用程序试图在自身上呈现模态视图控制器

搜索结果为空时 UITableView 中的 UISearchController 崩溃

带有大标题的 UISearchController 在选项卡栏中崩溃,“只有一个带有顶部边界的调色板可以在过渡之外处于活动状态”

UISearchController 与 UITableView?

iOS UISearchController:等到 UISearchController 在取消搜索后被解除