如何在Objective-C中表示可选的Bool(Bool?)?

时间:2015-06-09 03:19:30

标签: swift

我正在尝试用swift编写协议

@objc protocol RestAPIManagerDelegate {

      optional func credentialValidated(isValid: Bool?)
}

但我收到以下错误:

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

有什么建议吗?

5 个答案:

答案 0 :(得分:7)

问题是这种类型声明:

`isValid: Bool?`

在Swift 中完全没问题。但你不能将它暴露给Objective-C,因为Objective-C没有任何可选BOOL的概念 - Objective-C中的BOOL基本上只是一个数字,一个原始的C数据类型(我们称之为标量< / em>的)。

这是另一种看待它的方式。在与Objective-C的交换中,你可以在Objective-C可以说nil的任何地方使用Swift Optional - 事实上,在很大程度上,Swift Optional完全存在以便处理Objective-C nil或者您可能需要对Objective-C说nil。但Objective-C中的BOOL永远不会是nil - 它只能是YES或NO(Swift truefalse)。

所以你有三个选择:

  • 带走将所有这些暴露给Objective-C的@objc

  • 删除Optional并声明键入Bool

  • 使用对象类型。例如,将类型声明为AnyObject?(或NSNumber?)。这将起作用,因为Swift将Bool桥接到NSNumber(包括它传递给AnyObject),而Objective-C将使用Optional AnyObject或Optional NSNumber处理得很好,因为它们是对象类型,而不是标量。

答案 1 :(得分:3)

Object-C没有optionals的概念,试着删除“?”来自你的声明

答案 2 :(得分:1)

Swift Bool在NSNumber中转换,例如,如果Swift方法返回[Bool],并且如果在Objective-C代码中收到此数组,则它变为NSArray <NSNumber *>。如果您将此数组提供给接收[Bool]作为参数的Swift方法,则转换将自动完成。

答案 3 :(得分:0)

如果你想在Swift中做一个协议,在Swift中使用,没有选项,你可以这样做:

public protocol Note {
    var content: [ContentType] {get}

    func insertNote(note: Note) -> Bool
}

这会强制一个类实现一个返回Bool的方法,并且有一个名为ContentType的类的数组。

如果要使方法可选,则必须如上所述指定objc关键字,无论您是否与Objective-C进行互操作。那时,其他一切都应该适用于你的例子。

@objc protocol RestAPIManagerDelegate {
    optional func credentialValidated(isValid: Bool?)
}

来自Apples documentation:

  

如果您的协议标有@objc属性,则只能指定可选的协议要求。

     

此属性指示协议应该暴露给Objective-C代码,并在使用Swift with Cocoa和Objective-C中进行了描述。即使您没有与Objective-C进行互操作,如果要指定可选要求,也需要使用@objc属性标记协议。

     

另请注意,@ objc协议只能由类采用,而不能由结构或枚举采用。如果将协议标记为@objc以指定可选要求,则只能将该协议应用于类类型。

Apple给出的例子:

@objc protocol CounterDataSource {
    optional func incrementForCount(count: Int) -> Int
    optional var fixedIncrement: Int { get }
}

答案 4 :(得分:0)

可以改用NSNumber?,但是还有另一种方法。 您可以创建OptionalBool枚举并代替Bool?使用它来与Objective-C兼容。

在Swift代码中创建OptionalBool枚举:

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

@objc protocol RestAPIManagerDelegate {

    @objc optional func credentialValidated(isValid: OptionalBool)
    
}

在Objective-C代码中使用OptionalBool

@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