简体   繁体   中英

“'Application tried to present modally an active controller” when presenting a view controller via a Gesture Recognizer

I'm having this bizarre issue and I have been trying to tackle it down for the past few hours with no luck.

I have a UISearchController that shows up when the user taps a UIBarButtonItem in a navigation bar. The button was created with IB and then wired to its IBAction, which is this one:

@IBAction func searchButtonTapped(sender: UIBarButtonItem) {
    searchController.active = true
    self.presentViewController(searchController, animated: true, completion: nil)
}

It works perfectly. The view controller shows up and the user can type stuff.

Additionally to simply tapping the search bar button item, I want to give users more power by using that button. Namely, I want them to be able to long-press it and force-touch it to do different actions within my app.

After hacking and searching on SO for a while (and because UIBarButtonItem is not a view on itself...), I found a way to add some gesture recognizers the search bar button item. I added this in my viewDidLoad method.

if let searchBarButtonView = self.searchBarButtonItem.valueForKey("view") as? UIView where searchBarButtonView.respondsToSelector("addGestureRecognizer:") {

    if Settings.searchCollectionMagnifierGlassIconLongPressAction != .None {
        let longTapGr = UILongPressGestureRecognizer(target: self, action: "handleSearchBarButtonLongPressGesture:")
        longTapGr.minimumPressDuration = CFTimeInterval(Settings.searchCollectionMagnifierGlassIconLongPressActionTime)
        longTapGr.delegate = self
        searchBarButtonView.addGestureRecognizer(longTapGr)
    }

    if Settings.searchCollectionMagnifierGlassIconForceTouchAction != .None {
        let forceTouchGr = DFContinuousForceTouchGestureRecognizer()
        forceTouchGr.forceTouchDelegate = self
        forceTouchGr.triggeringForceTouchPressure = 2.0
        searchBarButtonView.addGestureRecognizer(forceTouchGr)
    }
}

You can ignore everything force-touch related for this question, as I am focusing on making long tap work first.

The gesture recognizers work fine. For the long tap gesture recognizer, this is the implementation for handleSearchBarButtonLongPressGesture: :

func handleSearchBarButtonLongPressGesture(recognizer: UILongPressGestureRecognizer) {
    self.performSearchCollectionMagnifierGlassAction(Settings.searchCollectionMagnifierGlassIconLongPressAction)
}

And this is the implementation for performSearchCollectionMagnifierGlassAction :

func performSearchCollectionMagnifierGlassAction(action: Settings.SearchCollectionMagnifierGlassIconAction) {
    let action = Settings.searchCollectionMagnifierGlassIconLongPressAction

    if action == .ClearOldQueryAndSearch {
        self.searchController.searchBar.text = ""
        self.searchButtonTapped(self.searchBarButtonItem) // This is exactly as if the user tapped the search bar button item on his own... But it crashes when it gets called as a result of a gesture recognizer!
    }
}

(I have removed other ifs here to make the code relevant. The other ifs only check for other actions and as such they don't get called).

Long-pressing my search bar button works fine. But the app crashes with:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Application tried to present modally an active controller

If I simply tap the search button, the app will not crash. I can show and hide the UISearchController as many times as I wish that way. Like you can see, long pressing the search button will do exactly what normally tapping the button would do, except it clears the text field before showing it. I tried commenting out the line that empties the searchBar, but the crash still happens. Considering that almost the same exact code gets called when long tapping and simple-tapping the search button, I am inclined to think that this is crash may be, oddly, related to the gesture recognizer.

I have also tried dismissing the searchController even when it's not present before clearing the searchBar and presenting it again. No luck.

Finally, I have copied and pasted the code from searchButtonTapped to performSearchCollectionMagnifierGlassAction . No luck there, either.

Your searchButtonTapped method is being called twice: in long tap gesture handler and directly when UIBarButtonItem's view emits touch up event.

Try to comment out your searchButtonTapped call or set cancelsTouchesInView property of longTapGr to true .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM