【问题标题】:Generics Fetch Firestore collection泛型获取 Firestore 集合
【发布时间】:2020-03-07 04:11:01
【问题描述】:

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

问题是,在这一行 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
}

【问题讨论】:

  • 我看到你不会在任何地方使用你的结构吗?
  • 正确。当我将函数调用为Package 类型时,我正在考虑使用它
  • 你能用函数调用进行编辑吗?我认为你应该fetchCollection&lt;T:Package&gt;。将 T 声明为 Package。

标签: ios swift firebase generics swift5


【解决方案1】:

编辑

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

创建PackageProtocol

protocol PackageProtocol {
    init(document: DocumentSnapshot)
}

使Package 符合PackageProtocol

struct Package: PackageProtocol

将您的方法签名更改为:

static func fetchCollection&lt;T: PackageProtocol&gt;(collection: String, completion: @escaping ([T]) -&gt; Void)

原答案

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

我会将方法签名更改为:

static func fetchCollection&lt;T == Package &gt;(collection: String, completion: @escaping ([T]) -&gt; Void)

或者如果您期望不同类型的Package

static func fetchCollection&lt;T: Package &gt;(collection: String, completion: @escaping ([T]) -&gt; Void)

【讨论】:

  • 现在我得到一个错误 `Type 'T' constrained to non-protocol, non-class type 'Package'
  • 哦,是的,当然,由于结构的原因,您将需要一个协议!请让我更新我的答案!
  • 一个小问题。在方法中运行for循环更好还是在协议中更好?
  • 如果你想创建一个方便的方法来帮助你,我想你可以创建一个扩展,但这是代码风格的问题。但是我会做一个改变,那就是使用高阶函数(map、flatMap 或 compactMap),而不是在那里创建一个新数组。
猜你喜欢
  • 1970-01-01
  • 2019-02-17
  • 1970-01-01
  • 2018-04-09
  • 2019-07-06
  • 2021-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多