My application does not always go to the next view controller when calling performSegue . However, it always does prepare(for:sender) immediately.
- What are the reasons for
performSegue not working without a tough error (and also execute prepareForSegue )? - Is there a specific state in which it is assumed that the source view controller is in what I need to check?
- If I set a 10 second delay (via
asyncAfter ), a crash will occur.
Scenario
I am trying to reassign a work segment for a new feature (integration into Spotlight search). The transition to my iPhone does not occur if the application remains in the detailed view. (The application has a UISplitViewController as its root view controller.)
However, the code works as expected when
- I am testing my iPad - that is, when both basic and detailed views are displayed.
- I test my iPhone when I leave the application on the main screen.
When I test my iPhone from the details screen {see code below}:
- The details screen disappears (behind
popToRootViewController ) - The main view is displayed with the correct line highlighted (including NSLog saying "To master")
- The function is executed, including
prepare(for:sender) , but the detailed view is never displayed.
At this point, I can click on the appropriate line, and segue will execute as expected - this is tableView(:didSelectRowAt:) calls performSegue .
In more detail
Swift 3.0 and iOS 10
The application has a UISplitViewController as its rootViewController. The main view is a tableView with a list of recipes. The detailed view is a table listing the ingredients for the selected recipe. Going segue from selecting a recipe row to an ingredient table.
I am adding a new function: we put recipes in Spotlight so that the user can search for them, and when they are selected, the recipe is selected from the main view, and its ingredients are shown in a detailed view.
Now I'm trying to implement Spotlight search integration using appDelegate application(:continue:restorationHandler) :
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Void) -> Bool { guard userActivity.activityType == CSSearchableItemActionType, let userInfo = userActivity.userInfo, let id = userInfo[CSSearchableItemActivityIdentifier] as? String else { return false } // The id is a unique identifier for recipe. if let inputRecipe = Recipe.getBy(uuid: id, moc: self.managedObjectContext) { let root = self.window?.rootViewController as! UISplitViewController let nav = root.viewControllers[0] as! UINavigationController // If this is a navigation controller, then detail is being shown if (nav.topViewController as? UINavigationController) != nil { NSLog("Should be a detail view") nav.popToRootViewController(animated: true) } if let masterVC = nav.topViewController as? RecipeMasterVC { NSLog("Into the master") masterVC.selectTableRowAt(recipe: inputRecipe) } } return true }
Inside RecipeMasterVC I added this code to highlight
func selectTableRowAt(recipe: Recipe){ let indexPath = self.fetchedResultsController.indexPath(forObject: recipe) self.tableView.selectRow(at: indexPath, animated: true, scrollPosition: .top) DispatchQueue.main.async { self.performSegue(withIdentifier: seguesEnum.RecipeDetail.rawValue, sender: recipe) } }