Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to represent an optional Bool (Bool?) in Objective-C?

Tags:

swift

I am trying to write a protocol in swift

@objc protocol RestAPIManagerDelegate {

      optional func credentialValidated(isValid: Bool?)
}

But I am getting following error:

'Method cannot be marked @objc because the type of the parameter cannot be represented in Objective-C'

Any suggestion?

like image 956
Md. Najmul Hasan Avatar asked Jun 09 '15 03:06

Md. Najmul Hasan


People also ask

What is optional in Objective-C?

Objective-C Language Protocols Optional and required methods This means that any class that conforms to this protocol must implement those methods. It is also possible to declare optional methods. These method can be implemented only if needed. You mark optional methods with the @optional directive.

How do you know if Boolean is optional?

Optional binding The code let booleanValue = booleanValue returns false if booleanValue is nil and the if block does not execute. If booleanValue is not nil , this code defines a new variable named booleanValue of type Bool (instead of an optional, Bool? ).

What is Boolean in Objective-C?

Boolean, in Objective-C, is a hold over data type from the C language. Both in C, and hence in Objective-C, 0 (zero) is treated as “false” and 1 (one) as “true”. C has a Boolean data type, bool (note: the lowercase), which can take on the values of true and false.


2 Answers

It's OK to use NSNumber? instead, but there is another way. You can create OptionalBool enum and use it instead of Bool? for compatibility with Objective-C.

Creating OptionalBool enum in Swift code:

@objc enum OptionalBool: Int {
    case none
    case yes
    case no
}

@objc protocol RestAPIManagerDelegate {

    @objc optional func credentialValidated(isValid: OptionalBool)
    
}

Using OptionalBool in Objective-C code:

@interface RestAPIManagerHandler () <RestAPIManagerDelegate>
@end

@implementation RestAPIManagerHandler

- (void)credentialValidatedWithIsValid:(enum OptionalBool)isValid {
    switch (isValid) {
        case OptionalBoolYes:
            NSLog(@"TRUE");
            break;
            
        case OptionalBoolNo:
            NSLog(@"FALSE");
            break;
            
        case OptionalBoolNone:
            NSLog(@"NULL");
            break;
    }
}

@end
like image 164
Dre Sid Avatar answered Oct 16 '22 17:10

Dre Sid


The problem is this type declaration:

`isValid: Bool?`

That is perfectly fine in Swift. But you cannot expose it to Objective-C, because Objective-C does not have any notion of an Optional BOOL - a BOOL in Objective-C is basically just a number, a primitive C datatype (what we call a scalar).

Here's another way of looking at it. In an interchange with Objective-C, you can use a Swift Optional anywhere that Objective-C can say nil - indeed, to a large extent Swift Optional exists exactly in order to deal with the possibility that Objective-C will say nil or that you might need to say nil to Objective-C. But a BOOL in Objective-C can never be nil - it can only be YES or NO (Swift true or false).

So you have three choices:

  • Take away the @objc that exposes all this to Objective-C

  • Remove the Optional and just declare that type a Bool

  • Use an object type. For example, declare the type as AnyObject? (or NSNumber?). This will work because Swift will bridge a Bool to an NSNumber (including as it passes into an AnyObject), and Objective-C will deal just fine with an Optional AnyObject or Optional NSNumber because those are object types, not scalars.

like image 25
matt Avatar answered Oct 16 '22 19:10

matt