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

时间:2018-08-20 17:02:58

标签: swift generics observable where-clause rx-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]
}

1 个答案:

答案 0 :(得分:0)

问题

如果不指定通用值的 Model Type ,则不能将扩展约束为保存通用值的 Model Type

您只能根据协议的associatedtype约束协议,或者根据扩展名对它们的通用类型进行约束。因此T无法识别,因为没有协议或通用声明。

Ray Wenderlich Scheme

解决方案

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

  

然后我们不需要模型类型,我们需要协议

我们有两种模型类型( ApiResponse ItemsContainer ),我们需要了解其通用类型,因此每种模型都需要两种协议。

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

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 {}