使用闭包时无法显式专门化泛型函数

时间:2018-07-13 13:33:30

标签: swift generics

我有这样的功能:

func register<T: Routable>(_ action: Action, withCallback callback: @escaping (T?) -> Void) {
    notificationCenter.addObserver(forName: actionMap[action], object: nil, queue: .main, using: { notification in
    let routable = T(userInfo: notification.userInfo)
        callback(routable)
    })
}

Routable的定义如下:

protocol Routable {
    init?(userInfo: [AnyHashable: Any]?)
}

当我尝试使用它时,我会收到

  

不能显式专门化泛型函数

这是用法:

controller.register<Navigate>(Action.navigate) { [unowned self] navigate in
    // do something
}

有什么让编译器满意的想法吗?

2 个答案:

答案 0 :(得分:3)

我认为这纯粹是一个语法问题。您不能像这样直接传递type参数。您需要改为“填充字体孔”。为此,您需要将类型添加到Bitmap

navigate

有时候,语法令人讨厌,因为它掩埋了类型。您可以通过以下方式重写controller.register(Action.navigate) { [unowned self] (navigate: Navigate?) in ... } 的签名来改进它:

register

然后您可以这样称呼它:

func register<T: Routable>(action: Action, returning: T.type,
                           withCallback callback: @escaping (T?) -> Void)

该函数中未直接使用controller.register(action: .navigate, returning: Navigate.self) { [unowned self] navigate in // ... } 参数。它只是提供了一种更明确的方法来专门化功能。

答案 1 :(得分:0)

如果不看更完整的代码示例,很难说……但是基本上,编译器告诉您的是:“您告诉我,您希望register函数是通用的(因为它具有类型参数),但是您还试图告诉我要使用哪种类型,我不喜欢。”

当您在调用中添加特定的类型参数时,该函数将被“明确地专门化”:

controller.register<Navigate>...
# Right Here       ^^^^^^^^^^

编译器希望灵活地确定要调用的寄存器函数类型。我怀疑您想要的是:

controller.register(Action.navigate) {...

在没有显式专门化泛型函数的地方,而是让编译器确定要使用哪种专门化。