iOS UISearchController crash: Application tried to present modal view controller on itself
Asked Answered
T

3

12

According to crashlytics the following crash is occurring (rarely).

Application tried to present modal view controller on itself. Presenting controller is .

I can't replicate this issue at all. This is how I setup my UISearch Controller.

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

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

Any help is appreciated because I am all out of ideas. I will post more code if needed.

Temperamental answered 24/10, 2017 at 18:47 Comment(2)
what line is actually crashing it? Where do you try to present the view controller in question?Gosney
Your setup is standard - we need some more context to help you, such as the transition that causes the error. Can you trap the exception in the debugger? I have seen errors like this caused by actions in UISearchControllerDelegate methods which attempt to alter the current search.Stride
D
25

I had that issue when I updated to iOS 11. My scenario was, that I had a Textfield, and when the user started to edit that, a search-view, essentially a tableview with a searchbar as header popped up and once a tableview cell was tapped it should close.

The problem seems to be that since iOS 11, the OS tries to restore the firstResponder state. Long story short.

It helped when I added active = NO, to my did select method, like so

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

   [self dismissViewControllerAnimated:YES completion:nil];
}
Declarative answered 26/10, 2017 at 7:50 Comment(5)
Strangely enough this active = NO was what caused the crash for me. Removing the line, my app no longer crashed. Time of writing this was 19th December 2017. Maybe Apple fixed it with latest update.Fates
yeah could be. Strangely enough my code still works :-/Declarative
So I've run into this as well (at least in crashlogs from the field) in iOS 11.4, 11.4.1. I was able to reproduce it and fix it. In my case I have two VCs. VC1 shows the searchcontroller and shows modally VC2. The user taps a button in VC2 and it goes away (by dismiss()) and then VC1 goes away (by dismiss()). In the case where the searchController is active on VC1 this assertion failure occurs after VC1 calls dismiss(). I fixed it by searchController.isActive = false just before dismiss().Tillis
I was struggling with this problem for three days!! Thank you very much!Solita
This problem still exists in iOS 13.4.1. My app reported this issue in the field and I fixed it using the fix suggested by Kastor. Thank you..Terminator
W
1

If you're like me and needed the searchController to remain active while presenting modally another controller, then do the following to get the same effect of presenting modally without doing so directly:

Quick note: Not familiar enough with Obj-C to give an answer in that, but here's an answer in Swift 4. Someone feel free to edit and add Obj-C if necessary, but I think it's clear here how to solve the issue at-hand, even if it is in Swift.

Let's say I have a menu that I want to pop-up:

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)

The implementation of getTopMostViewController() may vary. Mine is below and is adapted from 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
}

Hope this helps! This does not give you the error described for iOS 12 and Swift 4, although I did get that exact error when trying to present modally with an active search controller, which is what led me here.

Wagtail answered 29/1, 2019 at 5:23 Comment(0)
S
1

Make sure you use

self.searchController = UISearchController()

instead of

self.searchController = UISearchController(searchResultsController: self)
Sharisharia answered 9/12, 2019 at 11:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.