2
votes

I have a main view controller that has been setup in Interface Builder to open a table view controller via popover segue connected to a button. I want to be able to dismiss the popover when an item inside of my popover table view is selected in didSelectRowAtIndexPath. In Objective-c I can just typecast the the segue in the prepareForSegue delegate to a UIStoryboardPopoverSegueand pass along its UIPopoverController to the table view controller. However, in Swift my downcast fails because it sees the segue as type UIStorybaordPopoverPresentationSegue (when stepping through with the debugger) which doesn't appear to be a public API.

Here's my code:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
    if segue.identifier == "ShowCollectionsSegue" {
        if let collController:CollectionsTableViewController! = segue.destinationViewController as? CollectionsTableViewController {
            if let popoverSegue = segue as? UIStoryboardPopoverSegue { // <-- This fails
                collController.popover = popoverSegue.popoverController
            }
        }
    }
}

How do I coerce the segue to a UIStoryboardPopoverSegue in order to access its popoverController property?

I'm open to solving the problem of dismissing the popover in response to a table view cell tap a different way, but it seems that when using a segue from the storyboard, the only way to dismiss the popover is by holding onto a reference to the popover controller somehow and the only way to do that as far as I can tell is to cast the segue to a popover segue which Swift doesn't want to let me do. Any ideas?

1

1 Answers

1
votes

A strange problem, indeed. I noticed in the documentation, that UIStoryboardPopoverSegue does not inherit from any class. That explains why the cast does not work - UIStoryboardSegue is not its superclass. So I just tried to create a new object - it looks weird but works:

let popoverSegue = UIStoryboardPopoverSegue(
   identifier: segue.identifier, 
   source: self, 
   destination: segue.destinationViewController as UIViewController)
println("Is there a controller? \(popoverSegue.popoverController.description)")
// YES !!

EDIT

But this controller will not dismiss the popover :(

The fix is to specify the segue in Interface Builder as "Deprecated Segues : Popover". Then the code would be as expected

let popoverSegue = segue as  UIStoryboardPopoverSegue
if let destination = segue.destinationViewController as? TableViewController {
   destination.delegate = self
   self.popoverController = popoverSegue.popoverController
}