Is there a correct way to determine that an NSNumber is derived from a Bool using Swift?

You can ask the same question for Objective-C, and here is an answer in Objective-C – which you can call from, or translate into, Swift.

NSNumber is toll-free bridged to CFNumberRef, which is another way of saying an NSNumber object is in fact a CFNumber one (and vice-versa). Now CFNumberRef has a specific type for booleans, CFBooleanRef, and this is used when creating a boolean CFNumberRef aka NSNumber *… So all you need to do is check whether your NSNumber * is an instance of CFBooleanRef:

- (BOOL) isBoolNumber:(NSNumber *)num
{
   CFTypeID boolID = CFBooleanGetTypeID(); // the type ID of CFBoolean
   CFTypeID numID = CFGetTypeID((__bridge CFTypeRef)(num)); // the type ID of num
   return numID == boolID;
}

Note: You may notice that NSNumber/CFNumber objects created from booleans are actually pre-defined constant objects; one for YES, one for NO. You may be tempted to rely on this for identification. However, though is currently appears to be true, and is shown in Apple’s source code, to our knowledge it is not documented so should not be relied upon.

HTH

Addendum

Swift code translation (by GoodbyeStackOverflow):

func isBoolNumber(num:NSNumber) -> Bool
{
    let boolID = CFBooleanGetTypeID() // the type ID of CFBoolean
    let numID = CFGetTypeID(num) // the type ID of num
    return numID == boolID
}

Leave a Comment