这是我的协议:
@objc public protocol EventListenerOptions {
@objc optional var capture: Bool { get set }
}
我有这个方法签名:
func addEventListener(
_ type: NSString,
_ callback: ((_ event: UIEvent) -> Void)?,
_ options: EventListenerOptions?
)
我该如何调用它?我尝试过使用静态声明的字典,但它不接受它。建议的插入as! EventListenerOptions
的修复程序会产生编译器警告(在任何情况下都会在运行时崩溃(。
view.addEventListener(
"tap",
{(event: UIEvent) -> Void in
print("Got a tap event.")
},
["capture": true] // Error: Argument type '[String : Bool]' does not conform to expected type 'EventListenerOptions'
)
需求:我想将协议公开给Obj-C,所以我想要的是在Swift中获得类型安全的方法,同时处理在Obj-C中容易构建的对象(所以据我所知,我不能使用structs(。我希望我能通过一个NSDictionary广播的as EventListenerOptions
,但它不接受。
与某些语言(如TypeScript(不同,Swift具有标称类型,而不是结构。这意味着,即使对象具有您想要的形状,除非其类明确采用协议,否则您无法将其传入
protocol EventListenerOptions {
var capture: Bool { get set }
}
class AnEventListenerOptionsType: EventListenerOptions {
var capture: Bool
}
class NotAnEventListenerOptionsType {
var capture: Bool
}
字典["capture": true]
的类型不是符合EventListenerOptions
的类:它是标准库类型Dictionary<String, Bool>
。这种类型不仅没有采用协议,甚至没有相关的属性:必须通过dict["capture"]
而不是dict.capture
访问它。这是一个重要的区别:前者调用subscript(_:)
访问器,而后者访问capture
属性。(如果你来自TypeScript,正如@Alexander所建议的,你可能已经习惯了这些等价物,但在Swift中却不是。(
据我所知,Swift没有JS、C#、Kotlin等中的匿名对象文字。
TL;DR:解决方案是创建一个符合EventListenerOptions
的类。
尝试添加
class Listener: EventListenerOptions {
var capture: Bool = true
}
...
let listener = Listener()
listener.capture = true
view.addEventListener(
"tap",
{(event: UIEvent) -> Void in
print("Got a tap event.")
},
listener
)