也许这是一个愚蠢的问题,但我还没有找到任何解决方案。所以,我的问题是,它有一个事件发射器协议,其功能如下:
mutating func on(eventName:String, action:((Any?)->())) {
//..
}
我想用它来通知一些事件被一些信息触发时听众。 "登录"的访问令牌例如。
appSessionHadler.on("login") { (weak data: String?) in
//...
}
而且我得到一个错误,我无法调用" on"使用该参数列表的类型。当然它适用于Any:
appSessionHadler.on("login") { (weak data: Any?) in
//...
}
一切都符合任何,所以我很困惑。请有人解释一下这个!
我可以使用通用协议来解决这个问题,但它仍然让我感到沮丧,因为它不能像这样工作。
答案 0 :(得分:2)
您正在做出编译器无法保留的承诺。 on
函数可以随意使用任何类型的数据调用action
。但您传递的功能只接受String
。如果on
包含以下代码(直接或间接),系统应该做什么:
action(1)
1
不是String
,因此类型安全性会被破坏。编译器不能让你这样做。
考虑这一点的另一种方法是on
采用F
类型的函数,并且您传递F
的超类型而不是< F
的em> subtype 。 String
是Any
的子类型。但是函数参数的工作顺序相反。 (String)->Void
是(Any)->Void
的超类型。所以这与将Any
类型的变量传递给需要String
的函数相同。在形式上我们说函数的参数是逆变的,并且它们的返回值是协变的。您可以在Type Variance in Swift。
正如您所怀疑的那样,仿制药是正确的答案。 Any
几乎总是错误的工具。 Any?
是Swift中最难处理的类型之一,所以我绝对会不惜一切代价避免使用它。 (Optional
本身就是Any
的子类型,而Swift会自动升级到Optional
,所以当你Any?
开始获得双重选项时更加常见。 )