ImplicitlyUnwrappedOptional in init vs later - swift

I would like to understand why I don't get ImplicitlyUnwrappedOptional when I do params["bar"] = str but I get it when I declare params with the same force unwrapped variable.
See the playground below:
import UIKit
var str: String!
str = "Hello"
var params: [String: Any] = [
"foo": str
]
params["bar"] = str
print(params)
// ["bar": "Hello", "foo": Swift.ImplicitlyUnwrappedOptional<Swift.String>.some("Hello")]

In Swift 4.1, when you do:
var str: String!
str = "Hello"
var params: [String: Any] = [
"foo": str
]
The ImplicitlyUnwrappedOptional (IUO) value is coerced to Any, which is why it appears as an IUO inside your dictionary. It won't be force unwrapped, because the compiler will only force unwrap an IUO when the context demands its unwrapped type, which isn't the case with Any.
However the fact that you end up with an ImplicitlyUnwrappedOptional value is legacy behaviour. With the removal of the IUO type in Swift 4.2, you'll get an Optional value inside your dictionary instead, which will print as Optional("Hello").
There's more discussion of the above behaviour in this Q&A:
Why does implicitly unwrapped optional not unwrap in dictionary of type [String : Any]
When you do:
params["bar"] = str
You're using Dictionary's subscript(key: Key) -> Value?, which takes an Optional value – performing a removal if nil is passed, otherwise doing an insertion of the unwrapped value.
In Swift 4.1, the IUO value str will be implicitly converted to an Optional which can then be passed to the subscript.
In Swift 4.2, the IUO type has been removed, so str already is an Optional, which can be passed straight to the subscript without any intermediate conversions.
In both cases, str's unwrapped value is inserted into the dictionary, which is why you see it as being unwrapped. If str had been nil, no value for the key "bar" would have been inserted.

Related

Cannot force unwrap the value

var tuples: String! = "subash"
if let goin = tuples {
print(goin!)
}
I am receiving this error:
Cannot force unwrap the value of non-optional type String
I don't what happening constant goin is same as tuples but why it's showing me an error when I do force unwrap
Instead of the above code, this is running well:
var tuples: String! = "subash"
print(tuples!)
But kindly I need a solution to my above problem
That's something normal if you know how optionals work.
Inside the if statement, the right expression must be either Optional or Implicitly Unwrapped Optional, BUT NOT "normal" value.
This is the correct code:
let tuples: String! = "subash"
if let goin = tuples {
print(goin) // NO NEED to unwrap, because going IS NOT Optional
}
The reason this code runs fine:
var tuples: String! = "subash"
print(tuples!)
print(tuples)
... is because tuples is of type Implicitly Unwrapped Optional.
However, in general cases like this:
let myVar: String! = "some string"
if let myNewVar = myVar {
// Some code...
}
... myVar is always an Implicitly Unwrapped Optional, whereas myNewVar is of String type, because of how Optional Unwrapping works with if let statements.
Finally, if we unwrap the value this way:
let myVar: String! = "some string"
if let myVar = myVar {
// Some code...
print(myVar)
}
The printed value is the temp myVar, which is of type String and shadows the Implicitly Unwrapped myVar variable we initially declare.

Concatenating optionals strings [duplicate]

Why are implicitly unwrapped optionals not unwrapped when using string interpolation in Swift 3?
Example:
Running the following code in the playground
var str: String!
str = "Hello"
print("The following should not be printed as an optional: \(str)")
produces this output:
The following should not be printed as an optional: Optional("Hello")
Of course I can concatenate strings with the + operator but I'm using string interpolation pretty much everywhere in my app which now doesn't work anymore due to this (bug?).
Is this even a bug or did they intentionally change this behaviour with Swift 3?
As per SE-0054, ImplicitlyUnwrappedOptional<T> is no longer a distinct type; there is only Optional<T> now.
Declarations are still allowed to be annotated as implicitly unwrapped optionals T!, but doing so just adds a hidden attribute to inform the compiler that their value may be force unwrapped in contexts that demand their unwrapped type T; their actual type is now T?.
So you can think of this declaration:
var str: String!
as actually looking like this:
#_implicitlyUnwrapped // this attribute name is fictitious
var str: String?
Only the compiler sees this #_implicitlyUnwrapped attribute, but what it allows for is the implicit unwrapping of str's value in contexts that demand a String (its unwrapped type):
// `str` cannot be type-checked as a strong optional, so the compiler will
// implicitly force unwrap it (causing a crash in this case)
let x: String = str
// We're accessing a member on the unwrapped type of `str`, so it'll also be
// implicitly force unwrapped here
print(str.count)
But in all other cases where str can be type-checked as a strong optional, it will be:
// `x` is inferred to be a `String?` (because we really are assigning a `String?`)
let x = str
let y: Any = str // `str` is implicitly coerced from `String?` to `Any`
print(str) // Same as the previous example, as `print` takes an `Any` parameter.
And the compiler will always prefer treating it as such over force unwrapping.
As the proposal says (emphasis mine):
If the expression can be explicitly type checked with a strong optional type, it will be. However, the type checker will fall back to forcing the optional if necessary. The effect of this behavior is that the result of any expression that refers to a value declared as T! will either have type T or type T?.
When it comes to string interpolation, under the hood the compiler uses this initialiser from the _ExpressibleByStringInterpolation protocol in order to evaluate a string interpolation segment:
/// Creates an instance containing the appropriate representation for the
/// given value.
///
/// Do not call this initializer directly. It is used by the compiler for
/// each string interpolation segment when you use string interpolation. For
/// example:
///
/// let s = "\(5) x \(2) = \(5 * 2)"
/// print(s)
/// // Prints "5 x 2 = 10"
///
/// This initializer is called five times when processing the string literal
/// in the example above; once each for the following: the integer `5`, the
/// string `" x "`, the integer `2`, the string `" = "`, and the result of
/// the expression `5 * 2`.
///
/// - Parameter expr: The expression to represent.
init<T>(stringInterpolationSegment expr: T)
Therefore when implicitly called by your code:
var str: String!
str = "Hello"
print("The following should not be printed as an optional: \(str)")
As str's actual type is String?, by default that's what the compiler will infer the generic placeholder T to be. Therefore the value of str won't be force unwrapped, and you'll end up seeing the description for an optional.
If you wish for an IUO to be force unwrapped when used in string interpolation, you can simply use the force unwrap operator !:
var str: String!
str = "Hello"
print("The following should not be printed as an optional: \(str!)")
or you can coerce to its non-optional type (in this case String) in order to force the compiler to implicitly force unwrap it for you:
print("The following should not be printed as an optional: \(str as String)")
both of which, of course, will crash if str is nil.

Optionals in Swift. Why this behavior? [duplicate]

Why are implicitly unwrapped optionals not unwrapped when using string interpolation in Swift 3?
Example:
Running the following code in the playground
var str: String!
str = "Hello"
print("The following should not be printed as an optional: \(str)")
produces this output:
The following should not be printed as an optional: Optional("Hello")
Of course I can concatenate strings with the + operator but I'm using string interpolation pretty much everywhere in my app which now doesn't work anymore due to this (bug?).
Is this even a bug or did they intentionally change this behaviour with Swift 3?
As per SE-0054, ImplicitlyUnwrappedOptional<T> is no longer a distinct type; there is only Optional<T> now.
Declarations are still allowed to be annotated as implicitly unwrapped optionals T!, but doing so just adds a hidden attribute to inform the compiler that their value may be force unwrapped in contexts that demand their unwrapped type T; their actual type is now T?.
So you can think of this declaration:
var str: String!
as actually looking like this:
#_implicitlyUnwrapped // this attribute name is fictitious
var str: String?
Only the compiler sees this #_implicitlyUnwrapped attribute, but what it allows for is the implicit unwrapping of str's value in contexts that demand a String (its unwrapped type):
// `str` cannot be type-checked as a strong optional, so the compiler will
// implicitly force unwrap it (causing a crash in this case)
let x: String = str
// We're accessing a member on the unwrapped type of `str`, so it'll also be
// implicitly force unwrapped here
print(str.count)
But in all other cases where str can be type-checked as a strong optional, it will be:
// `x` is inferred to be a `String?` (because we really are assigning a `String?`)
let x = str
let y: Any = str // `str` is implicitly coerced from `String?` to `Any`
print(str) // Same as the previous example, as `print` takes an `Any` parameter.
And the compiler will always prefer treating it as such over force unwrapping.
As the proposal says (emphasis mine):
If the expression can be explicitly type checked with a strong optional type, it will be. However, the type checker will fall back to forcing the optional if necessary. The effect of this behavior is that the result of any expression that refers to a value declared as T! will either have type T or type T?.
When it comes to string interpolation, under the hood the compiler uses this initialiser from the _ExpressibleByStringInterpolation protocol in order to evaluate a string interpolation segment:
/// Creates an instance containing the appropriate representation for the
/// given value.
///
/// Do not call this initializer directly. It is used by the compiler for
/// each string interpolation segment when you use string interpolation. For
/// example:
///
/// let s = "\(5) x \(2) = \(5 * 2)"
/// print(s)
/// // Prints "5 x 2 = 10"
///
/// This initializer is called five times when processing the string literal
/// in the example above; once each for the following: the integer `5`, the
/// string `" x "`, the integer `2`, the string `" = "`, and the result of
/// the expression `5 * 2`.
///
/// - Parameter expr: The expression to represent.
init<T>(stringInterpolationSegment expr: T)
Therefore when implicitly called by your code:
var str: String!
str = "Hello"
print("The following should not be printed as an optional: \(str)")
As str's actual type is String?, by default that's what the compiler will infer the generic placeholder T to be. Therefore the value of str won't be force unwrapped, and you'll end up seeing the description for an optional.
If you wish for an IUO to be force unwrapped when used in string interpolation, you can simply use the force unwrap operator !:
var str: String!
str = "Hello"
print("The following should not be printed as an optional: \(str!)")
or you can coerce to its non-optional type (in this case String) in order to force the compiler to implicitly force unwrap it for you:
print("The following should not be printed as an optional: \(str as String)")
both of which, of course, will crash if str is nil.

The returns is not conform to the method return type but it still works [duplicate]

Why are implicitly unwrapped optionals not unwrapped when using string interpolation in Swift 3?
Example:
Running the following code in the playground
var str: String!
str = "Hello"
print("The following should not be printed as an optional: \(str)")
produces this output:
The following should not be printed as an optional: Optional("Hello")
Of course I can concatenate strings with the + operator but I'm using string interpolation pretty much everywhere in my app which now doesn't work anymore due to this (bug?).
Is this even a bug or did they intentionally change this behaviour with Swift 3?
As per SE-0054, ImplicitlyUnwrappedOptional<T> is no longer a distinct type; there is only Optional<T> now.
Declarations are still allowed to be annotated as implicitly unwrapped optionals T!, but doing so just adds a hidden attribute to inform the compiler that their value may be force unwrapped in contexts that demand their unwrapped type T; their actual type is now T?.
So you can think of this declaration:
var str: String!
as actually looking like this:
#_implicitlyUnwrapped // this attribute name is fictitious
var str: String?
Only the compiler sees this #_implicitlyUnwrapped attribute, but what it allows for is the implicit unwrapping of str's value in contexts that demand a String (its unwrapped type):
// `str` cannot be type-checked as a strong optional, so the compiler will
// implicitly force unwrap it (causing a crash in this case)
let x: String = str
// We're accessing a member on the unwrapped type of `str`, so it'll also be
// implicitly force unwrapped here
print(str.count)
But in all other cases where str can be type-checked as a strong optional, it will be:
// `x` is inferred to be a `String?` (because we really are assigning a `String?`)
let x = str
let y: Any = str // `str` is implicitly coerced from `String?` to `Any`
print(str) // Same as the previous example, as `print` takes an `Any` parameter.
And the compiler will always prefer treating it as such over force unwrapping.
As the proposal says (emphasis mine):
If the expression can be explicitly type checked with a strong optional type, it will be. However, the type checker will fall back to forcing the optional if necessary. The effect of this behavior is that the result of any expression that refers to a value declared as T! will either have type T or type T?.
When it comes to string interpolation, under the hood the compiler uses this initialiser from the _ExpressibleByStringInterpolation protocol in order to evaluate a string interpolation segment:
/// Creates an instance containing the appropriate representation for the
/// given value.
///
/// Do not call this initializer directly. It is used by the compiler for
/// each string interpolation segment when you use string interpolation. For
/// example:
///
/// let s = "\(5) x \(2) = \(5 * 2)"
/// print(s)
/// // Prints "5 x 2 = 10"
///
/// This initializer is called five times when processing the string literal
/// in the example above; once each for the following: the integer `5`, the
/// string `" x "`, the integer `2`, the string `" = "`, and the result of
/// the expression `5 * 2`.
///
/// - Parameter expr: The expression to represent.
init<T>(stringInterpolationSegment expr: T)
Therefore when implicitly called by your code:
var str: String!
str = "Hello"
print("The following should not be printed as an optional: \(str)")
As str's actual type is String?, by default that's what the compiler will infer the generic placeholder T to be. Therefore the value of str won't be force unwrapped, and you'll end up seeing the description for an optional.
If you wish for an IUO to be force unwrapped when used in string interpolation, you can simply use the force unwrap operator !:
var str: String!
str = "Hello"
print("The following should not be printed as an optional: \(str!)")
or you can coerce to its non-optional type (in this case String) in order to force the compiler to implicitly force unwrap it for you:
print("The following should not be printed as an optional: \(str as String)")
both of which, of course, will crash if str is nil.

Swift 3 incorrect string interpolation with implicitly unwrapped Optionals

Why are implicitly unwrapped optionals not unwrapped when using string interpolation in Swift 3?
Example:
Running the following code in the playground
var str: String!
str = "Hello"
print("The following should not be printed as an optional: \(str)")
produces this output:
The following should not be printed as an optional: Optional("Hello")
Of course I can concatenate strings with the + operator but I'm using string interpolation pretty much everywhere in my app which now doesn't work anymore due to this (bug?).
Is this even a bug or did they intentionally change this behaviour with Swift 3?
As per SE-0054, ImplicitlyUnwrappedOptional<T> is no longer a distinct type; there is only Optional<T> now.
Declarations are still allowed to be annotated as implicitly unwrapped optionals T!, but doing so just adds a hidden attribute to inform the compiler that their value may be force unwrapped in contexts that demand their unwrapped type T; their actual type is now T?.
So you can think of this declaration:
var str: String!
as actually looking like this:
#_implicitlyUnwrapped // this attribute name is fictitious
var str: String?
Only the compiler sees this #_implicitlyUnwrapped attribute, but what it allows for is the implicit unwrapping of str's value in contexts that demand a String (its unwrapped type):
// `str` cannot be type-checked as a strong optional, so the compiler will
// implicitly force unwrap it (causing a crash in this case)
let x: String = str
// We're accessing a member on the unwrapped type of `str`, so it'll also be
// implicitly force unwrapped here
print(str.count)
But in all other cases where str can be type-checked as a strong optional, it will be:
// `x` is inferred to be a `String?` (because we really are assigning a `String?`)
let x = str
let y: Any = str // `str` is implicitly coerced from `String?` to `Any`
print(str) // Same as the previous example, as `print` takes an `Any` parameter.
And the compiler will always prefer treating it as such over force unwrapping.
As the proposal says (emphasis mine):
If the expression can be explicitly type checked with a strong optional type, it will be. However, the type checker will fall back to forcing the optional if necessary. The effect of this behavior is that the result of any expression that refers to a value declared as T! will either have type T or type T?.
When it comes to string interpolation, under the hood the compiler uses this initialiser from the _ExpressibleByStringInterpolation protocol in order to evaluate a string interpolation segment:
/// Creates an instance containing the appropriate representation for the
/// given value.
///
/// Do not call this initializer directly. It is used by the compiler for
/// each string interpolation segment when you use string interpolation. For
/// example:
///
/// let s = "\(5) x \(2) = \(5 * 2)"
/// print(s)
/// // Prints "5 x 2 = 10"
///
/// This initializer is called five times when processing the string literal
/// in the example above; once each for the following: the integer `5`, the
/// string `" x "`, the integer `2`, the string `" = "`, and the result of
/// the expression `5 * 2`.
///
/// - Parameter expr: The expression to represent.
init<T>(stringInterpolationSegment expr: T)
Therefore when implicitly called by your code:
var str: String!
str = "Hello"
print("The following should not be printed as an optional: \(str)")
As str's actual type is String?, by default that's what the compiler will infer the generic placeholder T to be. Therefore the value of str won't be force unwrapped, and you'll end up seeing the description for an optional.
If you wish for an IUO to be force unwrapped when used in string interpolation, you can simply use the force unwrap operator !:
var str: String!
str = "Hello"
print("The following should not be printed as an optional: \(str!)")
or you can coerce to its non-optional type (in this case String) in order to force the compiler to implicitly force unwrap it for you:
print("The following should not be printed as an optional: \(str as String)")
both of which, of course, will crash if str is nil.