I am learning Swift and, as part of the process, trying to figure out what exactly is going on here. I have a custom segue where I want to place my modal view controller dismiss
The extra ?
required is due sourceViewController
returning an AnyObject
instead of a UIViewController
. This is a flaw in the API conversion from Objective-C (in which such property returns a rather meaningless id
). It's still an on-going process that started with iOS 8 beta 5, and apparently those API have not been fixed yet.
If you provide an appropriate cast, it will work as expected
(self.sourceViewController as UIViewController).presentingViewController?.dismissViewControllerAnimated(true, completion: nil)
Now, why do we need an extra ?
when dealing with AnyObject
?
AnyObject
can represent any object type, pretty much as id
does in Objective-C
. So at compile-time you can invoke any existing method on it, for example sourceViewController
.
When you do so, it triggers an implicit downcast from AnyObject
to UIViewController
and according to the official guide:
As with all downcasts in Swift, casting from
AnyObject
to a more specific object type is not guaranteed to succeed and therefore returns an optional value
So when you do
self.sourceViewController.presentingViewController??
it implicitly translates to something like
let source: UIViewController? = self.sourceViewController as? UIViewController
let presenting: UIViewController? = source?.presentingViewController
and that's why you need two ?
: one for resolving the downcast and one for the presentingViewController
.
Finally, always according to the documentation:
Of course, if you are certain of the type of the object (and know that it is not nil), you can force the invocation with the as operator.
which is exactly my proposed solution above.