【发布时间】:2018-06-20 09:59:30
【问题描述】:
我正在开发一个需要查询多个 API 的应用。我已经为每个 API 提供者提供了类(在更极端的情况下,每个特定 API 端点都有一个类)。这是因为每个 API 查询都应该返回一个非常严格类型的响应,所以如果一个 API 可以,例如,返回用户个人资料和个人资料图片,我只想要一个特定于其中任何一个的响应。
我大致是这样实现的:
protocol MicroserviceProvider {
associatedtype Response
}
protocol ProfilePictureMicroserviceProvider: MicroserviceProvider {
func getPicture(by email: String, _ completion: (Response) -> Void)
}
class SomeProfilePictureAPI: ProfilePictureMicroserviceProvider {
struct Response {
let error: Error?
let picture: UIImage?
}
func getPicture(by email: String, _ completion: (Response) -> Void) {
// some HTTP magic
// will eventually call completion(_:) with a Response object
// which either holds an error or a UIImage.
}
}
因为我希望能够对依赖此 API 的类进行单元测试,所以我需要能够动态注入该个人资料图片依赖项。默认情况下,它将使用SomeProfilePictureAPI,但在运行测试时,我可以将其替换为MockProfilePictureAPI,它仍将遵循ProfilePictureMicroserviceProvider。
因为我使用的是关联类型,所以我需要创建依赖于ProfilePictureMicroserviceProvider 的类泛型。
起初,我天真地尝试像这样编写我的视图控制器
class SomeClass {
var profilePicProvider: ProfilePictureMicroserviceProvider
}
但这只是导致了令人沮丧的著名'Protocol ProfilePictureMicroserviceProvider 只能用作通用约束,因为它具有 Self 或关联的类型要求'编译时错误。
现在我在过去几天一直在阅读这个问题,试图围绕具有关联类型的协议 (PATS),并认为我会采取通用的路线像这样的类:
class SomeClass<T: ProfilePictureMicroserviceProvider> {
var profilePicProfider: T = SomeProfilePictureAPI()
}
但即使这样我也会收到以下错误:
Cannot convert value of type 'SomeProfilePictureAPI' to specified type 'T'
即使 T 被限制为 ProfilePictureMicroserviceProvider 协议,并且 SomeProfilePictureAPI 遵守它...
基本上,主要思想是达到 2 个目标:强制执行具有强制响应类型的微服务结构,并使每个微服务可模拟以进行依赖类的单元测试。
我现在只能选择两者之一,因为我似乎无法让它发挥作用。非常欢迎任何帮助告诉我我做错了什么。
我也看过类型擦除。但在我看来,这似乎很古怪,而且对于在许多方面看起来都错了的事情付出了很大的努力。
所以基本上我的问题有两个:如何强制我的微服务定义自己的响应类型?以及如何在依赖它们的类中通过模拟微服务轻松替换它们?
【问题讨论】:
-
这里有个问题,你找到解决方法了吗?
-
@TuanDo 我做了,并最终用它写了一个 Cocoapod / SPM,看看:github.com/MrSkwiggs/Netswift。我会尝试根据这个写一个答案
-
谢谢。期待您的回答
-
@TuanDo 已发布答案。看看,如果你需要什么,请随时告诉我:)
标签: swift swift-protocols associated-types