Swift good coding practice: If statement with optional type Bool
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.
This problem exists with any optional of something that conforms to
the LogicValue protocol (e.g. nested optionals, optional of bool,
etc). We consider it serious issue that needs to be fixed for 1.0 and
have some ideas, but haven't settled on a solution yet.
So, this issue doesn't just effect optional Bools, but any optional type that conforms to the LogicValue protocol (defined as).
protocol LogicValue {
func getLogicValue() -> Bool
}
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.
if (hero.isAI == true) {
// stuff
}
In fact, after some further reading, the quote listed above continues to read:
For this common case, the simplest answer would be to produce a
warning for "if x" and require someone to explictly write "if x !=
nil" or "if x == true" to make it explicit what they want.
Swift good coding practice: If statement with optional type Bool
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.
This problem exists with any optional of something that conforms to
the LogicValue protocol (e.g. nested optionals, optional of bool,
etc). We consider it serious issue that needs to be fixed for 1.0 and
have some ideas, but haven't settled on a solution yet.
So, this issue doesn't just effect optional Bools, but any optional type that conforms to the LogicValue protocol (defined as).
protocol LogicValue {
func getLogicValue() -> Bool
}
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.
if (hero.isAI == true) {
// stuff
}
In fact, after some further reading, the quote listed above continues to read:
For this common case, the simplest answer would be to produce a
warning for "if x" and require someone to explictly write "if x !=
nil" or "if x == true" to make it explicit what they want.
optional type 'Bool' cannot be used as a boolean; Test for '!=nil' instead
You are checking if the value is different of nil and returning if it is, based un your comments and your second if you probably want to check if it is nil.
println("Checking login details")
if(userEmail.isEmpty || userPassword.isEmpty || userRepeatPassword.isEmpty){
displayMyAlertMessage("All fields are required")
println("Fail to login not all fields where fill")
return
} else if(userPassword != userRepeatPassword){
displayMyAlertMessage("Passwords do not match.")
println("Fail to login password does not match")
} else {
var uiAlert = UIAlertController(title: "Alert", message: "Registration was successful", preferredStyle: UIAlertControllerStyle.Alert)
self.presentViewController(uiAlert, animated: true, completion: nil)
uiAlert.addAction(UIAlertAction(title: "Ok", style: .Default, handler: { action in
dismissViewControllerAnimated(true, completion:nil)
}))
}
The implicit unwrapping of an optional boolean
The first test is checking whether aBoolean stores a value rather than nil, which it does:
if aBoolean {
"Hum..." // "Hum..."
else {
"Normal"
}
The second test is checking against the actual boolean value stored in aBoolean, which is false:
if aBoolean! {
"Hum..."
} else {
"Normal" // "Normal"
}
This is Illustrated in the Swift book in the "Implicitly Wrapped Optionals" section. I think the implicit unwrapping just doesn't apply with if-statements. I agree it is strange but here is the Apple example:
You can still treat an implicitly unwrapped optional like a normal optional, to check if it contains a value:
let assumedString: String! = "An implicitly unwrapped optional string."
if assumedString {
println(assumedString)
}
// prints "An implicitly unwrapped optional string."
Excerpt From: Apple Inc. “The Swift Programming Language.” iBooks. https://itun.es/us/jEUH0.l
((Any) throws - Bool) throws - OptionalAny') cannot conform to 'BinaryInteger'
With help from @Rob in the comments, I was able to unwrap the message properly and remove unnecessary guard let statements to run my delegate function. Below is the updated piece of code.
- Changed
message.values.first?
asInt
as the rate was in an integer format. - Removed guard let statements in converting the
heartRate
into the double format, as it was non-optional.
extension WatchKitConnection: WCSessionDelegate {
func session(_ session: WCSession, didReceiveMessage message: [String : Any]) {
print("didReceiveMessage from watch")
print(message)
// delegate?.updateLatestHeartRate(Double(message.values.first))
guard let heartRate = message.values.first as? Int else {
return
}
let heartRateDouble = Double(heartRate)
print("printing heartRate double from message\(heartRateDouble)")
delegate?.updateLatestHeartRate(heartRateDouble)
print("updateLatestHeartRate")
}
}
Checking the value of an Optional Bool
With optional booleans it's needed to make the check explicit:
if boolean == true {
...
}
Otherwise you can unwrap the optional:
if boolean! {
...
}
But that generates a runtime exception if boolean is nil
- to prevent that:
if boolean != nil && boolean! {
...
}
Before beta 5 it was possible, but it has been changed as reported in the release notes:
Optionals no longer implicitly evaluate to true when they have a value and false when they do not, to avoid confusion when working with optional Bool values. Instead, make an explicit check against nil with the == or != operators to find out if an optional contains a value.
Addendum: as suggested by @MartinR, a more compact variation to the 3rd option is using the coalescing operator:
if boolean ?? false {
// this code runs only if boolean == true
}
which means: if boolean is not nil, the expression evaluates to the boolean value (i.e. using the unwrapped boolean value), otherwise the expression evaluates to false
Single line if statement in Swift
In Swift the braces aren't optional like they were in Objective-C (C). The parens on the other hand are optional. Examples:
Valid Swift:
if someCondition {
// stuff
}
if (someCondition) {
// stuff
}
Invalid Swift:
if someCondition
// one liner
if (someCondition)
// one liner
This design decision eliminates an entire class of bugs that can come from improperly using an if statement without braces like the following case, where it might not always be clear that something
's value will be changed conditionally, but somethingElse
's value will change every time.
Bool something = true
Bool somethingElse = true
if (anUnrelatedCondition)
something = false
somethingElse = false
print something // outputs true
print somethingElse // outputs false
use of let in optional value along with if
Your second code snippet is functionally equivalent to the one from the book. However, the book suggests using let
to avoid multiple unwrapping of the optional value.
Since you are checking optionalName
for being empty, it is safe to assume that you plan to use it inside the conditional block. When you do so, Swift would need to unwrap the optional value from optionalName
again, because the variable remains optional.
When you do the assignment of optionalName
to name
in the let
declaration, the name
constant that you get back is not optional. This saves you the unwrap inside the if
statement.
Related Topics
Swift - Update/Refresh Label That Displays Time
How to Get Account Name from Contact Framework
How to Draw a Just the Corners of a Rectangle (Without Lines Connecting Them)
iOS Sound Not Playing in Swift
Swift - Nsdate and Last Week of Year
Pure Swiftui Login, Signup, Register Flow, Is It Possible
Nsurlsession/Nsurlconnection Http Load Failed (Kcfstreamerrordomainssl, -9802) on a Subdomain
Swift Do Subclasses Inherit Initializers
Setting Default Tab in Uitabbar in Swift
Swift Difference Between Var Arr:[String] = [] and Var Arr = [String]()
Mysterious "Cryptographic Verification Failure" Error on MACos Sierra, Xcode 8
Convert Uiview to .Png in Swift
Wkwebview Decidepolicyfornavigationaction Being Call After the Long Press Recogniser Ended
Swift Calling Setnavigationbarhidden But View Wont Move to Top
iOS Sharecontext Tapping on Suggestion Intent Property of Extensioncontext Is Nil
Ios-Charts How to Put Uiimage Beside a Point
How to Update a Swiftui View State from Outside (Uiviewcontroller for Example)
Automatically Increase/Decrease Uilabelview Height in Uitableviewcell