我正在尝试用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'
有什么建议吗?
答案 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 true
或false
)。
所以你有三个选择:
带走将所有这些暴露给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?)
}
如果您的协议标有@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