Swift 扩展到具有通用类型约束的 Observable

Swift Extension to Observable with Generic Type Constraint

我正在尝试为 Observable 添加一个扩展。 代码如下所示:

extension Observable where Element == ApiResponse<ItemsContainer<T>>, T:Codable

我收到以下异常:Use of undeclared type T

显然这行不通。 唯一缺少的是约束 ItemsContainer 内的泛型以符合 Codable。 可能像句法问题一样简单,或者我可能只是对泛型不够好。感谢您的帮助!

编辑:给出想法 - ApiResponse 和 ItemsContainer 看起来像这样

public struct ApiResponse<ApiModel> {  
  public let data: ApiModel?  
}  

struct ItemsContainer<Items>: Codable  where Items: Codable {  
   let items: [Items]
}

问题

您不能在不指定通用值的 模型类型 的情况下将扩展约束到包含通用值的 模型类型

您只能根据 associatedtype 限制协议,或根据扩展签名的泛型限制泛型。因此 T 不被识别,因为 none 的协议或通用声明它。

解决方案

因此,请记住我上面所说的,模型类型 需要在扩展上下文中完全定义。 但是不满足我们的要求等等,我们希望它是通用的!

Then we do not need a Model Type, we need a protocol!

我们有两个模型类型(ApiResponseItemsContainer),我们需要知道它们的通用类型,因此我们需要两个协议他们每个人。

ApiResponse

让我们创建一个名为 ApiResponseProtocol

public protocol ApiResponseProtocol {
    associatedtype Model
    var data: Model? { get }
}

太棒了,associatedtype Model 将扮演我们的角色,作为对象上 ApiModel 的通用值。让我们让 ApiResponse 符合 ApiResponseProtocol

public struct ApiResponse<ApiModel>: ApiResponseProtocol {
    public let data: ApiModel?
}

Generic ApiModel 这里可以从协议定义为 Model

物品容器

后续步骤与 ItemsContainer

相同
public protocol ItemsContainerProtocol {
    associatedtype Item
    var items: [Item] { get }
}

public struct ItemsContainer<Items>: Codable, ItemsContainerProtocol where Items: Codable {
    public let items: [Items]
}

分机

现在,由于我们可以从协议访问每个泛型类型 (associatedtypes),输出将变成如下所示:

// This would be for example ApiResponse<ItemsContainer<Model>> where Model is a Model Type conforming to Codable
extension Observable where Element: ApiResponseProtocol, Element.Model: ItemsContainerProtocol, Element.Model.Item: Codable {}