Implicitly unwrapped optional in Swift [duplicate] - ios

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.

Related

Swift - Why do I get an optional value from an implicitly-unwrapped optional variable even after assigning value? [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.

String concatenation and Optional(value) being printed [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.

'?'must be followed by a call, member lookup or subscript

I have defined a String type computed property:
var name : String? {
//an optional variable
var theName : String?
if SOME_CONDITION {
theName = “I have a name”
}
//ERROR: '?'must be followed by a call, member lookup or subscript
return theName?
}
I want to return whatever theName is, if it is nil, return nil. So I use return theName? , I don’t want to have runtime error. The compiler however raise an error '?'must be followed by a call, member lookup or subscript Why? How to get rid of it.
What about this? Looks more elegant to me:
var name : String? {
let condition = true // your own condition here of course
return condition ? "I have a name" : nil
}
The problem in your code:
var name : String? {
var theName : String?
let condition = true // your own condition here of course
if condition {
theName = "I have a name"
}
return theName // get rid of the ? here
}
The field theName is already optional, no need to add another ? there.
Why is my proposed solution not an alternate solution:
The construct I used is called ternary operator:
The ternary conditional operator is a special operator with three parts, which takes the form question ? answer1 : answer2. It is a shortcut for evaluating one of two expressions based on whether question is true or false. If question is true, it evaluates answer1 and returns its value; otherwise, it evaluates answer2 and returns its value.
It behaves like the if statement but is suitable here as it is shorter and thus clearer to read: Depending on the condition, the value is either theName or nil. You really don't need to assign the value to any other variable, because, afterall, you are computing it, so might as well simply return it as the condition decides, what the value is.
Adding ? to the end of a type makes it Optional.
Adding ? to the end of an optional variable invokes Optional Chaining.
You specify optional chaining by placing a question mark (?) after the
optional value on which you wish to call a property, method or
subscript if the optional is non-nil. This is very similar to placing
an exclamation mark (!) after an optional value to force the
unwrapping of its value. The main difference is that optional chaining
fails gracefully when the optional is nil, whereas forced unwrapping
triggers a runtime error when the optional is nil.
To reflect the fact that optional chaining can be called on a nil
value, the result of an optional chaining call is always an optional
value, even if the property, method, or subscript you are querying
returns a non-optional value. You can use this optional return value
to check whether the optional chaining call was successful (the
returned optional contains a value), or did not succeed due to a nil
value in the chain (the returned optional value is nil).
Specifically, the result of an optional chaining call is of the same
type as the expected return value, but wrapped in an optional. A
property that normally returns an Int will return an Int? when
accessed through optional chaining.
Example
class Foo {
var bar: Int
}
var x: Foo? // ? is attached to type Foo, it makes x an optional variable
let y: Int? = x?.bar // ? is attached to the variable x, this is optional chaining, it makes .bar return Int?

Swift: difference as String? vs. as? String [duplicate]

This question already has answers here:
Downcasting in Swift with as and as?
(3 answers)
Closed 8 years ago.
Is there a difference between as? String vs. as String? in Swift? If so, what's the difference and when should I use one vs. another?
There's a subtle but important difference:
variable as? String: variable can be any type, such as an array, an integer, etc. Cast to string if it's a string, set to nil otherwise.
variable as String?: variable is a String?, but stored in an opaque type, such as AnyObject?, or it's a non optional string. If it's something different, a runtime exception is generated.
Some examples:
var x: AnyObject? = "Test"
x as String? // OK, the result is an optional string
x as? String // OK, evaluates to an optional string
"string" as String? // OK, evaluates to optional string
x as? Int // OK, evaluates to nil, it's not an Int
x as Int? // Runtime exception, it's not castable to optional Int
So:
as? Type means: cast to this type, if possible, otherwise evaluate to nil
as Type? means: cast to an optional Type, because I know it's an optional Type. I understand that if it's not that, a runtime exception is generated
However, the real difference is between as? and as: the former is an attempt to cast, the latter is a forced cast, resulting in runtime error if not possible.
Update Dec 14, 2015 Since Swift 1.2, there are 3 variations of the as operator:
as? is an attempt to cast, evaluating to nil if cast fails
as! is a forced cast, resulting to an runtime exception if cast fails (this is what as previously did)
as is now a special type of cast to be used when casting to equivalent types, usually bridged types, such as Swift's String and NSString.
From The Swift Programming Language book,
as is a type cast operator which we use to downcast to the subclass and as? is used for an optional form, when we are not sure if the downcast will succeed. Consider the following example
for item in library {
if let movie = item as? Movie {
println("Movie: '(movie.name)', dir. (movie.director)")
} else if let song = item as? Song {
println("Song: '(song.name)', by (song.artist)")
}
}
The example starts by trying to downcast the current item as a Movie. Because item is a MediaItem instance, it’s possible that it might be a Movie; equally, it’s also possible that it might be a Song, or even just a base MediaItem.
String? An optional value either contains a value or contains nil to indicate that the value is missing.
From this,
as? String means when you don't know what you're downcasting, you are assuming that as a String, but it might me Integer or Float or Array or Dictionary
as String? means it's an Optional Value, it may either contain a String or Nil value.
Yes there is a difference.
In the first case, you are doing an optional cast to the type String. This will return a value if the object you are attempting to cast is indeed a String or nil if it is not.
In the second case, you are doing a forced cast to the type String?. If the value you are casting is not a string, it will crash your program.
YES, there is diffrence.
variable as String? downcast to optional String.If variable is not String? it will cause run-time exception.
while variable as? String will return nil if your variable is not String type or return downcast variable to String. This is conditional downcasting, if you not sure about down-casting you need to use this .

No need to unwrap optionals in Swift?

I think I'm confused about the concept of 'unwrapping' an optional value, and any guidance would be much appreciated!
According to the Swift Programming Language Guide, an optional requires unwrapping before it can be used, unless it is implicitly unwrapped using an !.
From: Apple Inc. “The Swift Programming Language.” iBooks. https://itun.es/gb/jEUH0.l:
let possibleString: String? = "An optional string."
println(possibleString!) // requires an exclamation mark to access its value
whereas
let assumedString: String! = "An implicitly unwrapped optional string."
println(assumedString) // no exclamation mark is needed to access its value
However, in Xcode, I can do the following and still print the value of an optional string:
let teamname: String? = "Liverpool!"
println("Come on \(teamname)")
What am I missing?
First of all, an optional requires unwrapping only if you are using it somewhere that does not allow an optional. (e.g. assigning a String? to a String)
var optionalString: String? = "Some string"
var absolutelyAString: String = "Another string"
// absolutelyAString = optionalString // Error. Needs to unwrap
absolutelyAString = optionalString! // OK.
"Unwrap" basically means to "guarantee that the value is not nil". Just think of it as casting to a non-nullable type.
Second, println() accepts optionals just fine but because it checks your variable for you. If the value of your variable is nil, it prints "nil"; otherwise it prints the string implemented by the Streamable, Printable, or DebugPrintable protocols.
An optional requires unwrapping, but you don't always have to do it yourself.
var teamname: String? = "Liverpool"
println("Come on \(teamname)")
In this case, the string interpolation will check the optional then unwrap it and add its value to the String. If the Optional is nil, it will add "nil" to the String instead.
In order to access the properties and methods of String you will have to explicitly unwrap it. If you don't know if it is nil or not, you should check with an if statement.
if teamname != nil {
var newName = teamname!.capitalizedString
}

Resources