Search code examples
iosswiftxcodesegueunwind-segue

Having problems with Xcode 8.1 and unwind segues


I can't get unwind segue to work with the latest Xcode 8.1 GM. I'm just wondering if I'm the only one, or someone else is experiencing the same. I have set up the view-controllers as before, it worked in Xcode 8.0, but now I'm having no luck. Tried to clean and so on, but nothing helps. I would like someone else could test it as well before I file a radar...

The view controller that first instantiated the view controller is having the following code:

@IBAction func unwindToSettingsTableViewController(_ segue: UIStoryboardSegue) {
    print("unwind")
}

I also tried without the underscore, but that did not help. When setting up this, one should be able to ctrl drag from files owner to exit, and get up the unwind segues: No unwind segue showing up here... So either am I doing it completely wrong (I dont think so, it worked perfectly fine before), or there is a bug in Xcode 8.1

I tried to do the same in a new project, and then it worked properly. So I guess there is something wrong with my project or storyboard file.

Update

Since the storyboards are holding rather small scenes, I just deleted it, and recreated it again, using the same classes for the view controllers and so on. And now it works. So having exactly the same code, but a fresh storyboard, makes me think it is some bug.


Solution

  • I found the reason for the weird behaviour. It needs a little explanation on how we build our apps to understand the hows and whys.

    First of all, instead of having big ViewControllers, we tend to split them into smaller chunks. This way, we always know where the "business logic" is, where to find the data source, outlets and actions, and so on. A typical TableViewController is made like this:

    SampleTVC.swift

    class SampleTableViewController: UITableViewController {
        @IBOutlet var someLabel: UILabel!
        @IBOutlet var someButton: UIButton!
    
        @IBAction func unwindHere(_ segue: UIStoryBoardSegue) {
            doSomething()
        }
    
    }
    

    SampleDelegate+DataSource.swift

    extension SampleTableViewController {
        override func numberOfSections(in tableView: UITableView) -> Int
        override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
        override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
    }
    

    SampleFetchedResultsController.swift

    extension SampleTableViewController: NSFetchedResultsControllerDelegate {
        var fetchedResultsController: NSFetchedResultsController<Item>
        func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>)
        func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange sectionInfo: NSFetchedResultsSectionInfo, atSectionIndex sectionIndex: Int, for type: NSFetchedResultsChangeType)
        func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?)
        func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>)
    }
    

    I tried here to connect up the code with a TVC made up of these smaller bits, and no way, no rewind segue pops up.

    So, putting all the extensions in the same file as the SampleTableViewController, it would still not work.

    The solution was to remove all the extensions, and put all functions into the class itself, then it worked as it should. It does not make much sense, it's clearly a bug.