I have been coding in Swift for a while, and I think I had to put a ! on all my let field variables that were not defined immediately.
Now I notice today that this piece of code does not compile and I am really surprised? why is this?
class MyClass : Mapper {
var a: Bool!
required init?(_ map: Map) {
}
// Mappable
func mapping(map: Map) {
a <- map["a"]
}
}
let myClass = MyClass()
if myClass.a { // Compiler not happy
// Optional type 'Bool!' cannot be used as a boolean; test for '!= nil' instead
}
if true && myClass.a { // Compiler happy
}
if myClass.a && myClass.a { // Compiler happy
}
Apple Swift version 2.2
Edit
Some people point out why am I using a let
for a variable that will never change. I mentioned it is for field variables but I shorten the example. When using ObjectMapper (http://github.com/Hearst-DD/ObjectMapper), all the fields are not defined immediately in the init. This is why they are all either optional? or required!
You can declare let a: Bool
without a !
and without declaring true or false right then. The compiler will complain if it can't guarantee the value gets set before you use it though.
This works.
let a: Bool
a = true
if a { // Compiler happy
}
This works as well, because a
is guaranteed to be set.
let a: Bool
if thingOne < thingTwo {
a = true
} else {
a = false
}
if a { // Compiler happy
}
However, this would not work because a
is not guaranteed to be set before you try to use it.
let a: Bool
if thingOne < thingTwo {
a = true
}
if a { // Compiler NOT happy
// "Constant 'a' used before being initialized"
}
Now, if you can't guarantee that your variable will be set by the time you do the check, then you should really be using an optional var
in the first place.
var a: Bool?
if a == true { // Compiler happy
}
A bit of history...
In Swift 1.0, it was possible to check if an optional variable optVar
contained a value by just checking:
if optVar {
println("optVar has a value")
} else {
println("optVar is nil")
}
In The Swift Programming Language, the update for Swift 1.1 (dated 2014-10-16) stated:
Optionals no longer implicitly evaluate to
true
when they have a value andfalse
when they do not, to avoid confusion when working with optionalBool
values. Instead, make an explicit check againstnil
with the==
or!=
operators to find out if an optional contains a value.
So, the nonsensical error message that you are getting was put there because the Swift compiler is interpreting your:
if a {
}
to mean:
if a != nil {
}
and it is encouraging you to test against nil
to determine if the Optional a
has a value.
Perhaps the Swift authors will change it in the future, but for now you will have to explicitly unwrap a
:
if a! {
}
or check against true
:
if a == true {
}
or (to be completely safe):
if a ?? false {
print("this will not crash if a is nil")
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With