Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

performSegue doesn't always transition, but prepare(for:sender) always called

Tags:

ios

swift

segue

My app doesn't always segue to the next view controller when performSegue is called. However, it always executes the prepare(for:sender) immediately.

  • What reasons are there for a performSegue not to work without having a hard error (and to still execute the prepareForSegue)?
  • Is there a certain state that the source view controller is supposed to be in that I need to check for?
  • If I put a 10 second delay (via 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

  1. I test on my iPad - i.e., when both the master and detail views are being shown.
  2. I test on my iPhone when I leave the app on the master view.

When I test my iPhone from the detail screen {see code below}:

  1. The detail screen disappears (per the popToRootViewController)
  2. The master view is shown, with the correct row highlighted (including the NSLog saying "Into the master")
  3. The function executes, including the 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)
    }
}
like image 824
AgRizzo Avatar asked Oct 17 '22 10:10

AgRizzo


1 Answers

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

like image 105
Dale Avatar answered Oct 20 '22 23:10

Dale