Swift Optionals - Inconsistency?
ios, swift
Solution
update for Xcode beta 5
the originally asked issue has been resolved in Xcode beta5, that may invalidate this answer.
original anwer
that may request further explanation, why it is definitely not inconsistent behaviour but is simple invalid.
the optional value has to be always of the right side of the actual operand, and it cannot be on the left side of it.
see that logic via two simple examples:
example 1
in case of this line of code:
self.window?.backgroundColor = UIColor.redColor()
< LEFT ^ RIGHT >
the optional is on the left side which would mean the left side could be `nil` therefore the following operand would appear here in runtime:
nil = UIColor.redColor()
which is clearly invalid on every level without any further or complex explanation – a `nil` cannot be assigned to something else, that is why the compiler does not allow it.
NOTE: you may assume that the logical behaviour would be like this in the case of `self.window = nil`:
nil.backgroundColor = UIColor.redColor()
but the documentation about Optional Chaining highlights a very important behaviour which explains why that is not happening at all:
Multiple queries can be chained together, and the entire chain fails gracefully if any link in the chain is `nil`.
emphasis is on the word "entire", thus that is why the left side will be `nil = ...` and not `nil.backgroundColor = ...` as you'd expect after Objective-C.
example 2
the other answer highligths another idea of how it can be solved:
self.window?.setBackgroundColor(UIColor.redColor())
why is that working? would it not be a little inconsistency here? definitely not.
the actual optional is on the right side of the operand here, because that line is equal to this line, however we are not bothered to get the `void` in practice at all.
let result: Void! = self.window?.setBackgroundColor(UIColor.redColor())
< LEFT ^ RIGHT >
as you see there is not any inconsistency at all here, because in the case of `self.window = nil` that line would be equal to this one in runtime (please see the explanation above):
let result: Void! = nil
and that would be a completely legal operand.
the logic is simple, the optional must be always at the right side of the operand (or operator), on the left side it can be non-optional value only.
Problem
I'm slightly confused - I thought I understood Optionals and on the Apple dev forums Chris L, mentioned a work around to the immutable Optional issue was to create a class wrapper for the optional value type. -link! However take this example with UIWindow (an optional class type with various properties) The properties still don't seem mutable with optional chaining! ``` var window: UIWindow? //this works (force unwrap) self.window!.backgroundColor = UIColor.greenColor() //this optional chain doesn't work... why not? Isn't this just a safer version of the above? self.window?.backgroundColor = UIColor.redColor() ``` This seems to be fixed in beta 5!