我有一个字典,其中包含函数调用以及用于向该字典添加函数的通用方法。我转发该泛型函数以便将其添加到字典中的那一刻,编译器崩溃了。
当您将以下代码放在游乐场时,您可以看到:
import Cocoa
class Email:NSObject {
var Subject:String = ""
}
class SMS:NSObject {
var Message:String = ""
}
var allfunc = Dictionary<String, (item: NSObject) -> Void>()
func test<T:NSObject>(type:T, myfunc:(item: T) -> Void) {
allfunc[NSStringFromClass(type.dynamicType)] = myfunc as? (item:NSObject) -> Void
}
test(Email(), {item in NSLog("\(item.Subject)")})
test(SMS(), {item in NSLog("\(item.Message)")})
for (key: String, value: (item: NSObject) -> Void) in allfunc {
if key == NSStringFromClass(Email().dynamicType) {
var mail = Email()
mail.Subject = "testing mail"
value(item: mail)
} else {
var sms = SMS()
sms.Message = "testing SMS"
value(item: sms)
}
}
当我将测试功能更改为此时,我不会崩溃,但我将失去自动完成功能:
func test<T:NSObject>(type:T, myfunc:(item: NSObject) -> Void) {
allfunc[NSStringFromClass(type.dynamicType)] = myfunc
}
这是一个编译器错误,你不能低估功能,或者不应该是可能的吗? 有没有可以用来创建类似功能的替代方案?
也许操场上的代码看起来有点奇怪。它是我项目的修改后的摘录。如果您想查看具有相同崩溃的完整项目,请查看https://github.com/evermeer/EVCloudKitDao
答案 0 :(得分:0)
你不能施放功能。在当前的Xcode版本6.2中,您将获得以下运行时异常:Swift动态转换失败
然而,我在https://github.com/evermeer/EVCloudKitDao的连接函数中实现了这个问题的解决方法。解决方案是包装函数而不是强制转换它。代码如下所示:
public var insertedHandlers = Dictionary<String, (item: EVCloudKitDataObject) -> Void>()
public var updateHandlers = Dictionary<String, (item: EVCloudKitDataObject, dataIndex:Int) -> Void>()
public func connect<T:EVCloudKitDataObject>(
type:T,
completionHandler: (results: [T]) -> Void,
insertedHandler:(item: T) -> Void,
updatedHandler:(item: T, dataIndex:Int) -> Void,
deletedHandler:(recordId: String, dataIndex:Int) -> Void,
errorHandler:(error: NSError) -> Void
) -> Void {
func insertedHandlerWrapper(item:EVCloudKitDataObject) -> Void {
insertedHandler(item: item as T)
}
func updatedHandlerWrapper(item:EVCloudKitDataObject, dataIndex:Int) -> Void {
updatedHandler(item: item as T, dataIndex: dataIndex)
}
self.insertedHandlers[filterId] = insertedHandlerWrapper
self.updateHandlers[filterId] = updatedHandlerWrapper
...
现在updateHandler仍然使用T而不是EVCloudKitDataObject,并且在处理程序本身中你可以使用原始类型而不需要强制转换它。