首页 > 解决方案 > 使用泛型类型约束对 Observable 进行 Swift 扩展

问题描述

我正在尝试向 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]
}

标签: swiftgenericsobservablewhere-clauserx-swift

解决方案


问题

如果不指定泛型值的模型类型,则不能限制对包含泛型值的模型类型的扩展。

associatedtype您仅在扩展签名上基于它们的 s 或基于泛型类型的泛型来约束协议。因此T无法识别,因为没有任何协议或泛型声明它。

雷文德利希方案

解决方案

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

那么我们不需要模型类型,我们需要一个协议

我们有两个模型类型(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?
}

这里的泛型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 {}

推荐阅读