I have a swift struct containing an array:
struct S { let a: [Int] }
and an optional value of S
var s: S? = ...
I thought I could use optional chaining for determining the size of the array a with a fallback of 0 like this
let count = s?.a?.count ?? 0
However, the compiler complains with a
"Cannot use optional chaining on non-optional value of type [Int]"
I could add a computed property to S that delegates to a.count but I don't see why optional chaining with direct access to the array doesn't work. Is this a known issue? Will this be fixed?
(XCode 7.0 beta 4)
All the examples suggest to use ?. on every following property access.
I see. The part you referred is really misleading. But for this example snippet:
if let johnsStreet = john.residence?.address?.street {
This description is added:
The value of
john.residence
currently contains a valid Residence
instance. However, the value of john.residence.address
is currently nil
.The description suggests residence is Optional, address is also Optional. So, adding ? for each Optional property.
In general, expr?.methodChain is equivalent to (expr !=nil) ? expr!.methodChain : nil .
So, this code:
let count = s?.a.count ?? 0
is equivalent to:
let count = ( (s != nil) ? s!.a.count : nil ) ?? 0
And your code:
let count = (s?.a)?.count ?? 0
is equivalent:
let count = ( (s != nil) ? s!.a : nil )?.count ?? 0
When you terminate method chaining, the principle "If the type you are trying to retrieve is not optional, it will become optional because of the optional chaining." work. The result of s?.a may be nil, in other words, is Optional.
Your first code:
let count = s?.a?.count ?? 0
is equivalent to:
let count = ( (s != nil) ? s!.a?.count : nil) ?? 0
As you see s!.a is not Optional, it's non-optional [Int], so you get "Cannot use optional chaining on non-optional value of type [Int]" .
Actually I've forgotton how confusing these behaviors are, and I apologize I wrote "I don't see why you don't write".
But knowing a simple rule will always apply:
In a (continuous) method-chaining, you put `?` after properties or method calls which types are actually Optional.
(EDIT: added required spaces.)