My app doesn't always segue to the next view controller when performSegue
is called. However, it always executes the prepare(for:sender)
immediately.
performSegue
not to work without having a hard error (and to still execute the prepareForSegue
)?asyncAfter
), the segue occurs.Scenario
I am trying to re-purpose a working segue for a new feature (integration to Spotlight search.) The transition does not occur on my iPhone if the app is left on the detail view. (The app has a UISplitViewController as its root view controller.)
However, the code works as expected when
When I test my iPhone from the detail screen {see code below}:
popToRootViewController
)prepare(for:sender)
but the detail view is never shown.At this point, I can tap the appropriate row, and the segue occurs as expected - that is tableView(:didSelectRowAt:)
calls performSegue
.
Even More Detail
Swift 3.0 & iOS 10
The app has a UISplitViewController as its rootViewController. The master view is a tableView with a list of recipes. The detail view is a tableView listing the ingredients for the selected recipe. The segue transitions from the recipe row selection to its ingredient table.
I am putting in a new feature: putting the recipes into Spotlight, such that the user can search for them and when selected, the recipe is selected from the master view and its ingredients are shown in the detail view.
Now I am trying to implement the Spotlight search integration via the appDelegate's 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
}
Within the RecipeMasterVC, I added this code to segue
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)
}
}
I have a similar scenario in my own app, not using segue but still using split views. When I checked the code I see that I had to add a delay of 200ms to make it work. Never did get to the root cause, but no delay, even with a dispatch async doesn't work if the detail screen is already being displayed
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With