无法使用完成块推断静态函数的泛型类型

时间:2018-01-28 23:14:04

标签: swift generics

我有一个使用泛型的静态函数,但是当它被调用时我无法推断它的泛型类型。功能:

static func getDocument<T: JSONDecodable>(_ document: String, fromCollection collection: FirebaseStorage.FirestoreCollections, completion: @escaping (_ decodedDoc: T?, _ error: Error?) -> ()) {
    let docRef = firestore.collection(collection.rawValue).document(document)
    docRef.getDocument { documentSnapshot, error in
        guard error == nil,
            let docData = documentSnapshot?.data(),
            let decodedDoc = T(json: docData) else {
            completion(nil, error)
            return
        }
        completion(decodedDoc, nil)
    }
}

使用:

调用
FirebaseClient.getDocument(
    id,
    fromCollection: FirebaseStorage.FirestoreCollections.users) { (profile, error) in

}

这会产生错误:Generic parameter 'T' could not be inferred。如何使函数的通用部分工作?

2 个答案:

答案 0 :(得分:1)

FirebaseClient.getDocument(
    id,
    fromCollection: FirebaseStorage.FirestoreCollections.users) { (profile: ProfileType?, error) in

}

您需要让Swift知道我添加profile的类型ProfileType。应该这样做!

答案 1 :(得分:1)

Kane的答案很好,但更灵活的方法是直接传递类型。例如,这使得可以使用可选的完成处理程序,或者如果您不关心它,则忽略_的参数。 (也就是说,这种方法输入的时间要长一些,所以有时凯恩的方式会更好。)

static func getDocument<T: JSONDecodable>(_ document: String,
                                          ofType: T.Type,
                                          completion: @escaping (_ decodedDoc: T?, _ error: Error?) -> ())

这使一切都明确。你这么称呼它:

FirebaseClient.getDocument(id, ofType: ProfileType.self) { (profile, error) in ... }

请注意,不需要使用ofType参数。它只是专门用于通用。

这与Decodable的工作方式非常接近,适用于很多问题。但是,如果Kane的解决方案更方便的话,它的解决方案也很方便。