Is "x? .Y" in Swift the same as "x?" and then ".y"?
I understand that in Swift if I define
var opt:String? = "Optional"
I will get an error if I try
opt.isEmpty
because it opt
has a type String?
that has no method isEmpty
. And I thought I realized that
opt?.isEmpty
does not raise an error because it opt?
unpacks (any not nil
) opt
, which results in String
which method has isEmpty
. But
opt?
by its own results in String?
, not a String
.
Is ?.
another operator from ?
followed by .
?
Try
(opt?).isEmpty
and get an impressive error.
source to share
But the opponent? on its own results in String? not a string.
Yes. According to Swift language reference, Expressions, Postfix Expressions, Optional-Expression chaining :
Postfix itself? the operator simply returns the value of its argument as optional.
Thus, placing ?
itself at the end of an optional is a complete no-op. It has no effect.
There is?. another operator? and then.?
Yes. More specifically, it ?
has the optional chaining effect when used in any "postfix expression", including when ()
(function call), .
(member access) and []
(index) follow .
source to share
Yes opt?.isEmpty
different from String?
. It's called optional chaining . From a quick programming guide:
You specify an optional string by putting a question mark (?) After the optional value on which you want to call a property, method, or index, if the optional parameter is nonzero. This is very similar to placing an exclamation mark (!) After an optional value to force the expansion of its value. The main difference is that the extra chaining fails gracefully when the optional parameter is zero, whereas the forced unwrapping triggers a runtime error when the option is zero.
This creates an optional as you think var opt: String?
Now
opt?.isEmpty //it will not crash if opt is nil
matches the exception
opt!.isEmpty //it will crash if opt is nil
if opt!
- nil
, than will not crash at runtime. The optional chaining is used to call long sequences of optional chaining without calling. Each additional chain returns an optional ie opt? returns the optional expands it, and if nil than not calling isEmpty else, calling isEmpty and reutns value. Also
(opt?).isEmpty
When you write the instruction above, it is optional (optional) and it cannot be unpacked due to curly braces. This error displays
$T2?? does not have a member named `isEmpty`
to expand it
(opt?)!.isEmpty
it will return false
Edit: More ...
var o1 = opt?
var o2 = ((opt?)?)
does nothing on its own, it just assigns a value o1
, o2
ie String ?. to expand opt
and o1
, o2
they are both optional and need one statement !
to expand it.
Also, please don't understand between String?
and opt?
they are both different, when? used after some type in a declaration that it makes optional, and when ?
used after a variable opt
it is used to unwrap in an optional chaining and return an optional return value
Additional materials:
try this to clarify
(((opt?)?)!).isEmpty //it will unwrap with single !
((((opt?)?)!)?).isEmpty //compiler will show suggestion to remove ?
the below statement makes optional optional
var opt:String??? = "Optional"
to deploy
opt!!!.isEmpty
EDIT2
opt?
always returns optional, but if opt
defined as String! it implicit optional
and opt?
will return optional(explicit)
. But if it opt
does opt?
n't necessarily do anything
From the Quick Programming Guide
In other words:
If the type you are trying to retrieve is not optional, it will become optional because of the optional chaining. If the type you are trying to retrieve is already optional, it will not become more optional because of the chaining.
Thus:
If you try to retrieve an Int value through optional chaining, an Int? is always returned, no matter how many levels of chaining are used. Similarly, if you try to retrieve an Int? value through optional chaining, an Int? is always returned, no matter how many levels of chaining are used.
source to share