Quick Options - Inconsistency?

I'm a little confused - I thought I understood Options and on the Apple dev Chris L forums, I mentioned working with an immutable additional problem to create a class wrapper for an optional value type. - link !

However, take this example with UIWindow (optional class type with various properties)

Properties still don't seem volatile with the possibility of 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!

+6
source share
2 answers

update for Xcode beta 5


The originally asked problem was resolved in Xcode beta5, which may lead to the invalidity of this answer.


original under


which may ask for additional explanations of why this is definitely not a contradictory behavior, but just plain wrong.

an optional value must always be to the right of the actual operand, and it cannot be on the left.

see this logic with two simple examples:

example 1

in the case of this line of code:

 self.window?.backgroundColor = UIColor.redColor() < LEFT ^ RIGHT > 

optionally located on the left side, which means that the left side can be nil , so the following operand will be displayed in runtime:

 nil = UIColor.redColor() 

which is clearly invalid at every level without any additional or complex explanation - a nil cannot be assigned to anything else, therefore the compiler does not allow it.

NOTE. you can assume that the logical behavior will be the same as in the case of self.window = nil :

 nil.backgroundColor = UIColor.redColor() 

but the documentation Optional chain emphasizes a very important behavior that explains why this does not happen at all:

Multiple requests can be linked together, and the whole chain gracefully fails if any link in the nil chain.

the emphasis is on the word "integer", so the left side will be nil = ... and not nil.backgroundColor = ... , as you would expect after Objective-C.

example 2

another answer appreciates another idea on how this can be solved:

 self.window?.setBackgroundColor(UIColor.redColor()) 

why does it work? wouldn't there be a little inconsistency here? definitely not.

the actual optional parameter is on the right side of the operand here, because this line is equal to this line, however we are not worried about getting void in practice at all.

 let result: Void! = self.window?.setBackgroundColor(UIColor.redColor()) < LEFT ^ RIGHT > 

since you see that there is no inconsistency here, because in the case of self.window = nil this line will be equal to this at runtime (see explanation above) :

 let result: Void! = nil 

and it will be a completely legal operand.

the logic is simple, optional must always be on the right side of the operand (or operator), on the left side it can be an optional value.

+5
source

An extra chain works for reading values ​​(return value or nil ), it works for calling methods (this method is called or does nothing), but it does not work for assignments.

I believe that this is by design, but I see no reason why this is so, because it is essentially the same as:

 extension UIWindow { func setBackgroundColor(color: UIColor) { self.backgroundColor = color } } self.window?.setBackgroundColor(UIColor.redColor()) 

and it works without problems. You can report a bug or ask on the dev forums. I believe the optional chain here is logically incompatible.

Your example from the dev forums has nothing to do with this problem, as this problem is related to value types.

+5
source

Source: https://habr.com/ru/post/971968/


All Articles