Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift optional variable assignment with default value (double question marks)

Tags:

swift

So I was trying to do

let foo = dict["key"] as? String ?? "empty"
var bar = some_func(string: foo!)

and XCode 6 complains that
Operand of postfix '!' should have optional type; type is 'String'
on the second line.

If I change the first line to

let foo: String? = dict["key"] as? String ?? "empty"

the error goes away.

Is this some kind of flaw or am I just doing something wrong?

like image 719
fengye87 Avatar asked Dec 12 '14 08:12

fengye87


People also ask

What does double question mark mean in Swift?

Double question mark is a nil-coalescing operator. In plain terms, it is just a shorthand for saying != nil . First it checks if the the return value is nil, if it is indeed nil, then the left value is presented, and if it is nil then the right value is presented.

How do I set optional value in Swift?

To use an optional, you "unwrap" it An optional String cannot be used in place of an actual String . To use the wrapped value inside an optional, you have to unwrap it. The simplest way to unwrap an optional is to add a ! after the optional name. This is called "force unwrapping".

What should you use to provide a default value for a variable in Swift?

However there is another data type in Swift called Optional, whose default value is a null value ( nil ). You can use optional when you want a variable or constant contain no value in it. An optional type may contain a value or absent a value (a null value).

What does the question mark do in Swift?

Question marks after a type refer to Optionals , a way in Swift which lets you indicate the possibility that a value might be absent for any type at all, without the need for special constants.


2 Answers

The nil-coalescing operator a ?? b is a shortcut for

a != nil ? a! : b

it returns either the left operand unwrapped or the right operand. So the type of foo is String and the second line should be

var bar = some_func(string: foo)

without the exclamation mark because foo is not an optional and can't be unwrapped.

(If you change the first line to

let foo: String? = dict["key"] as? String ?? "empty"

then the result of the right hand side is wrapped into an optional string again, and needs to be unwrapped in the second line. It makes the error go away, but this is probably not what you want.)

like image 171
Martin R Avatar answered Oct 11 '22 07:10

Martin R


Your foo will be a String not a String? because the nil coalescing operator ?? will either unwrap your conditional cast if it is .some (resulting in a String) or it will use "empty", which is also a String.

like image 4
Thorsten Karrer Avatar answered Oct 11 '22 09:10

Thorsten Karrer