Skip to content

When is a Bool not a Bool?

This is a silly question — or rather, it should be a silly question — but it’s going to bite you sometimes when you integrate Objective-C and Swift code together (*cough* UIKit).

You will try to use what you think is a Bool from an Objective-C API, and suddenly you’re getting this compile error:

Cannot convert value of type ‘ObjCBool’ to expected argument type ‘Bool’

This is a Boolean value; why can’t I use this @($^ thing as a Bool?

Normally the standard types play nice between Objective-C and Swift. But Bools are an unusual case that require a non-obvious solution.

Objective-C uses BOOL as the type for Boolean values. In earlier versions of Swift, this was properly bridged to a Bool. In Swift 3, this changed to a value of type ObjCBool. When you’re used to the standard types being automatically bridged nicely, it’s jarring when suddenly you have what you think is a Bool, but it can’t be used like a Bool anywhere. You get the aforementioned error. It also cannot be cast to a Bool; that results in a compile-time error as well.

It turns out that there is a property on ObjCBool instances called boolValue, which is responsible for producing a Swift Bool from the ObjCBool. So, in the example I was having a problem with, accessing a BOOL property on an Objective-C object:

let val = objcObject.aBool // This is of type ObjCBool
let boolVal = objcObject.aBool.boolValue // This is actually a Bool

It’s aggravating when Swift itself isn’t very Swift-like, isn’t it?

If you need to go the other direction, that is thankfully more obvious:

let objectiveCBool = ObjCBool(swiftBoolVal)

Maybe one of these days we will be able to put Objective-C behind us all together. Until then, little workarounds like this are going to be part of the game.

Comments are closed.