Generics Fetch Firestore 集合

Generics Fetch Firestore collection

我正在尝试创建一个通用函数来获取不同的集合,并根据给定的类型假设 T 将所有文档转换为 T 然后填充并 return 一个数组。

问题是在这一行 let item: T = T.init(document: document) 我收到一条错误消息说 Type 'T' has no member 'init' 即使没有 .init 它也会失败。

这是将传递给此泛型函数的类型示例。

struct Package: Identifiable {
    var id = UUID()
    let documentReference: DocumentReference

    init(document: DocumentSnapshot) {
        self.documentReference = document.reference
}

这是我的代码:

static func fetchCollection<T>(collection: String, completion: @escaping ([T]) -> Void) {
    var array: [T] = []
    db.collection(collection).getDocuments() { (querySnapshot, err) in
        if let snapshot = querySnapshot {
            guard let userID = Auth.auth().currentUser?.uid else { return }
            for document in snapshot.documents {
                let item: T = T.init(document: document)
                array.append(item)
            }
            completion(array)
        }
    }
}

函数调用:

FirebaseViewModel.fetchCollection<Package>(collection: "packages") { packages in
    self.userData.packages = packages
}

编辑

不能将顶级方法签名上的泛型限制为结构,因此需要协议抽象。

创建PackageProtocol

protocol PackageProtocol {
    init(document: DocumentSnapshot)
}

使Package符合PackageProtocol

struct Package: PackageProtocol

将您的方法签名更改为:

static func fetchCollection<T: PackageProtocol>(collection: String, completion: @escaping ([T]) -> Void)

原答案

在您的上下文中 T 根本不受任何类型的限制,因此它不会识别您的初始化程序。

我会将方法签名更改为:

static func fetchCollection<T == Package >(collection: String, completion: @escaping ([T]) -> Void)

或者如果您希望得到不同类型的 Package

static func fetchCollection<T: Package >(collection: String, completion: @escaping ([T]) -> Void)