So I've been developing an app in Swift, and today I spent nearly an hour debugging a problem that turned out to be completely unexpected. It all resulted from the code below.
if (hero.isAI) { //isAI is a Bool
}
The problem was that this if statement ALWAYS returned true. So I thought that maybe I was setting isAI to true somewhere but in the end I realized that I declared isAI as an optional type as shown below.
var isAI: Bool!
when it should have been
var isAI: Bool
This resulted in the if-statement not checking if isAI was true, but instead checking if it contained a value.
So to be safe now I make sure to write my if-statments like this
if (hero.isAI == true) { //isAI is a Bool
}
So my question is, what are my options to avoid this problem in the future? (this problem seems extremely dangerous, especially when working on a team on a large project). Should I always write my if-statment explicitly, should I just avoid the optional type for Bools altogether?
Note that I did not have this problem in Xcode Beta 2. This problem came about when I upgraded to Xcode beta 3. I think because in Beta 2 Apple handled implicitly unwrapped Bool in an if-statement by checking its value rather than checking if it contains a value.
Lastly, below is an example of which if-statements run given an optional Bool to better help people understand the problem.
let myBool: Bool! = false
if (myBool) {
//Runs
}
if (myBool!) {
//Won't Run
}
if (!myBool) {
//Runs
}
if (myBool == true) {
//Won't Run
}
This is a known issue that is being tracked on the SwiftInFlux repo, which includes this quote from Chris Lattner on the Apple developer forums.
So, this issue doesn't just effect optional Bools, but any optional type that conforms to the LogicValue protocol (defined as).
Anyway as far as recommendations on how to work around this go, it's hard to recommend any one specific solution considering that Apple hasn't given an indication of how they intend to solve this in the future, but I would imagine that continuing to explicitly check the value of the Bool would be the way to go.
In fact, after some further reading, the quote listed above continues to read:
my advice is to use this nice coalescing
??
If the bool is part if Core Data (aka NSNumber), you should do it like this.
Regards