Treating a forced downcast as optional will never produce 'nil'
You can solve this warning from two angles. 1. The value you return 2. The type that you are expected to return. The other answer speaks about the 1st angle. I'm speaking about the 2nd angle
This is because you are returning a forced unwrapped and casted value for an optional. The compiler is like, "If you really want to just force cast all optionals then why not just make the expected return parameter to be a non-optional"
For example if you wrote
func returnSomething<T> -> T?{ // I'm an optional, I can handle nils SAFELY and won't crash.
return UIViewController as! T // will never return a safe nil, will just CRASH
}
Basically you told yourself (and the compiler) I want to handle nil
s safely but then in the very next line, you said nah, I don't!!!
The compiler would give a warning:
Treating a forced downcast to 'T' as optional will never produce 'nil'
An alternative is to remove the ?
func returnSomething<T>() -> T{ // I can't handle nils
return UIViewController() as! T // I will crash on nils
}
Having that said, likely the best way is to not use force cast and just do:
func returnSomething<T>() -> T?{ // I can handle nils
return UIViewController() as? T // I won't crash on nils
}
Let's take a closer look at your last line, and explode it to see what's happening:
let temporaryAnyObject = test()
let temporaryString = temporaryAnyObject as String
dict["test"] = temporaryString
The error is on the second line, where you are telling the compiler to enforce that temporaryAnyObject
is definitely a String
. The code will still compile (assuming you don't treat warnings as errors), but will crash if temporaryAnyObject
is not actually a String
.
The way as
works, with no ?
, is basically saying "from now on, treat the result of this expression as that type IF the result is actually of that type, otherwise we've become inconsistent and can no longer run.
The way as?
works (with the ?
) is saying "from now on, treat the result of this expression as that type IF the result is actually of that type, otherwise the result of this expression is nil
.
So in my exploded example above, if test()
does return a String
, then the as
downcast succeeds, and temporaryString
is now a String
. If test()
doesn't return a String
, but say an Int
or anything else not subclassed from String, then the as
fails and the code can no longer continue to run.
This is because, as the developer in complete control, you told the system to behave this way by not putting the optional ?
indicator. The as
command specifically means that you do not tolerate optional behavior and you require that downcast to work.
If you had put the ?
, then temporaryString
would be nil
, and the third line would simple remove the "test" key/value pair from the dictionary.
This might seem strange, but that's only because this is the opposite default behavior of many languages, like Obj-C, which treat everything as optional by default, and rely on you to place your own checks and asserts.
Edit - Swift 2 Update
Since Swift 2, the forced, failable downcast operator as
has been removed, and is replaced with as!
, which is much Swiftier. The behavior is the same.