我有一个使用泛型的静态函数,但是当它被调用时我无法推断它的泛型类型。功能:
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
。如何使函数的通用部分工作?
答案 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的解决方案更方便的话,它的解决方案也很方便。