Why is it necessary to coerce from Optional to Any? [duplicate] - swift

This question already has answers here:
Why can't you assign an Optional to a variable of type `Any` without a warning?
(5 answers)
Why do we need to explicitly cast the optional to Any?
(1 answer)
Closed 4 years ago.
I have seen several questions regarding "expression implicitly coerced from an Optional to Any"(such as this and this), but I did not find one explaining the reason why Optional is not "included" in Any, since, according to the Apple's Swift Standard Library, Optional is a generic enum type.
Any parameters are expected for the print function, so providing Optional would give the warning message. However, since Optional is an enum type, shouldn't it be an Any type as well? Why is Optional, as an enum type, not part of the Any type such that the compiler needs to convert Optional to Any?

The purpose of Optional is to prevent you from accidentally calling methods on or accessing properties of variables which are nil.
You are right that Optional can be assigned to Any. Anything can be assigned to Any. But look what happens now! I have transformed a value that can be nil into a non-optional type Any! If somehow this value is passed to somewhere else and some other programmer (or you in the future) would assume that it has a non-nil value.
Therefore, the compiler warning is there to remind you that you may have forgotten to unwrap your optionals.

Related

What is the point of using an "Implicitly Unwrapped Optional" as a function parameter type?

I go over some code written by other developers and now and then I encounter signatures like this one:
func didReceiveLogMessage(_ message: String!)
Would it be safe to convert this parameter type to String instead of String! ?
Basically never declare a custom function parameter as implicit unwrapped optional. Don't.
This is a pre Swift 3 legacy syntax only for Objective-C and Core Foundation compatibility.
It's absolutely safe and even highly recommended to remove the exclamation mark. However if you really need an optional use a regular optional (?)
This gives no value. It actually adds complexity as even an Inmplicitly unwrapped optional as such counts as an optional, meaning it can be nil (but will crash). a regular String can't be nil

Why use T! instead of T as function parameter and return type? [duplicate]

This question already has answers here:
In Swift, what does the ! symbol mean in a function signature?
(2 answers)
Closed 3 years ago.
In JavaScriptCore, I saw most of functions declared T! as parameter type and return type. Since T! assumes non-nil when pass in and return, why not just declare T as type?
e.g.
func evaluateScript(_ script: String!) -> JSValue!
why not just
func evaluateScript(_ script: String) -> JSValue
This indicates that an ObjC API has not yet been audited for nullability, and does not have nullability annotations applied. Without nullability annotations, the compiler doesn't know whether the values are optional or not. The default behavior in that case is to make them all ! types, and leave the question to the caller (the only other possible approach would be to make everything ? types, which would be extremely inconvenient to work with).
When Apple annotates the header, the ! will go away.
In the meantime, it's up to you to check the documentation to ensure the return values cannot be nil before using them directly.
In this particular case, the underlying JSEvaluateScript can in fact return nil:
#result The JSValue that results from evaluating script, or NULL if an exception is thrown.
So you do need to check it. There's just no way for the compiler to know that currently.

Swift variable declare with optional(?) or force unwrap(!) different? [duplicate]

This question already has answers here:
What is the difference between String? and String! (two ways of creating an optional variable)?
(7 answers)
Closed 4 years ago.
what is different, when we declare new variable post fix with either ? or !
ex:
class Car{
var gear : Int!
var color : String?
}
and I couldn`t find any resource regard of this problem
Foo? is an optional. Foo! is an implicitly unwrapped optional.
This section of the language guide explains what implicitly unwrapped optionals are:
Sometimes it’s clear from a program’s structure that an optional will always have a value, after that value is first set. In these cases, it’s useful to remove the need to check and unwrap the optional’s value every time it’s accessed, because it can be safely assumed to have a value all of the time.

How to get the underlying Value from a Swift KeyPath when its type is KeyPath<Root, Value!>?

Take a look at the following code:
struct Something {
var s: String! // Implicitly Unwrapped Optional
}
func bind<T, V>(keyPath: WritableKeyPath<T, V?>) {
}
bind(\Something.s)
The code above does not compile. If we change the signature of bind to bind<T, V>(keyPath: WritableKeyPath<T, V>) then it does compile, but the problem is that the type of V is String! and I need to get the underlying type, in this case String.
We can solve the problem as follows:
func bind<T, V>(keypath: WritableKeyPath<T, ImplicitlyUnwrappedOptional<V>>) {
}
Unfortunately the documentation says that ImplicitlyUnwrappedOptional is deprecated. However, it is not marked as deprecated with the #available attribute.
I'm hesitant to use a type that the docs say are deprecated, but I can find no other way to accomplish what I need.
Is there another way to get the implicitly wrapped generic Value type from a WritableKeyPath when its type is WritableKeyPath<T, V!>?
Will ImplicitlyUnwrappedOptional be removed at some point?
Is there another way to get the implicitly wrapped generic Value type from a WritableKeyPath when its type is WritableKeyPath<T, V!>?
Not that I'm aware of. Really the problem here is that \Something.s shouldn't be a WritableKeyPath<T, V!>. That should be illegal under the rules set out by SE-0054 (IUOs are attributes on declarations; they're not actual types that can satisfy generic placeholders).
Instead, \Something.s should be a WritableKeyPath<T, V?>, so really your original code ought to compile. This issue has been filed as a bug here.
Will ImplicitlyUnwrappedOptional be removed at some point?
Yes, this is set out by SE-0054:
Because IUOs are an attribute on declarations rather than on types, the ImplicitlyUnwrappedOptional type, as well as the long form ImplicitlyUnwrappedOptional<T> syntax, is removed. Types with nested IUOs are no longer allowed. This includes types such as [Int!] and (Int!, Int!).
However the type-checker implementation for this wasn't fully implemented for Swift 4, which is why you're still able to use ImplicitlyUnwrappedOptional as a type in order to work around your problem. It has been implemented for Swift 5 though, so your workaround will no longer compile on its release.
Although hopefully the IUO key path bug will have been fixed by then.

Swift unwrapping Optional value by "?" and "!" [duplicate]

This question already has an answer here:
What is the difference when change to use optional chaining replace forced unwrapping in swift?
(1 answer)
Closed 5 years ago.
What are the differences when i unwrap Optional value by ? and !
If there is Class name A and there is a property name proA
Then if i make an instance like this
var a:A? = A()
a?.proA
a!.proA
I can approach property 'proA' two ways above. I know I cannot get value if I use a.proA because a is a Optional Type.
Also, I know a!.proA can get value because it unwrap the value in force
And what is a?.proA?
What are the differences between a?.proA and a!.proA
As you stated, ! forcefully unwraps the optional.
var a: A? = A()
a!.prop
However, what happens if the optional was never assigned a value, which means it's nil?
var a: A?;
a!.pop
You get a Swift runtime error (think of it as the equivalent of a null pointer exception in other languages e.g. Java).
On the other hand, if you use ?, you can take advantage of optional chaining. This allows you to gracefully traverse optional properties without fear of causing a runtime error. If some intermediate property along the chain is nil, the whole expression will return nil.
var a: A?;
a?.pop //returns nil, no runtime error