RetrofireSwift
从 RetrofireSwift 分叉而来,为何要分叉它?
这本来是一个精彩的库,但是原始版本不与 Alamofire 的 5.0 版本兼容,看起来原始作者已经停止了支持,也不再维护它。我们现在已经迁移了它,并且它与它完全兼容,这应该是任何需要为 Swift 提供 Refit (HttpClient 生成) 的官方库。
这是什么?
RetrofireSwift 是一个受 Retrofit 启发的库。由于 Retrofit 使用了 Swift 中不可用的注解和代理,因此这个库使用了一个轻微定制的 Sourcery 版本(称为 SourceryForRetrofire),基于您在协议上编写的注释/注解来生成 Alamofire 的 SessionManager 扩展。只需查看 用法
部分,即可更好地了解它 :)
示例
要运行示例项目,请先克隆仓库,然后从 Example 目录运行 pod install
要求
您需要在项目中包含 cocoapods,仅此而已。
安装
目前,安装此库的唯一官方方法是使用 CocoaPods;当然,您可以自己从 GitHub 上构建二进制文件(这应该始终是一致的),但是我无法在发生任何问题时帮助您。
- 请将以下行添加到 Podfile
pod 'RetrofireSwift', '0.3.1' # Since this pod is not stable you need to specify its version
- 运行
pod install
- 在目标的
构建阶段
选项卡中添加一个新建运行脚本阶段
- 将您新创建的脚本移动到
[CP] 检查 Pods Manifest.lock
和编译来源 (N 项)
之间 - 在下面的
Shell
箱中添加此脚本:$PODS_ROOT/RetrofireSwift/retrofire.sh
- 创建您的协议及其注释(有关更多信息,请参阅
用法
部分) - 构建您的项目
(cmd-b)
- 在项目根目录中,您将看到一个新文件,
Generated/RetrofireSourcery.generated.swift
- 将
Generated
文件夹拖放到 Xcode 中(如下面的 GIF 所示) - 取消选中
如果需要,则复制项目
(如果已选中),选择创建组
并按完成
- 您现在可以使用自动生成的代码了 :)
提示:您只需要执行这些步骤一次,然后只需构建项目,所有内容都将自动更新
用法
作为一个例子,我们将获取一个 GitHub 用户的存储库列表。我们需要请求的 URL 是 https://api.github.com/users/dcoletto/repos
,其中 dcoletto
是用户名。响应是一个 JSON 文件,因此我们需要创建一个可以存储我们数据的结构/类。注意:使用 Codable
协议,Retrofire 将自动解析您的 JSON 并实例化您的 Swift 对象
struct GithubRepo: Codable {
var name: String
var owner: GithubUser
}
struct GithubUser: Codable {
var login: String
}
如上图示例所示,可以嵌套使用遵循Codable
协议的结构体/类。
现在我们需要设置协议(https
)、基础URL(api.github.com
)和端口(https使用端口443
)。
func setupRetrofire(){
RetrofireConfig.networkProtocol = "https"
RetrofireConfig.baseUrl = "api.github.com"
RetrofireConfig.port = 443
}
最后一步,创建一个遵循Retrofire
协议的协议。
protocol Api: Retrofire {
// @GET = /users/{user}/repos
func getRepo(
/* @Path */ user: String
) -> [GithubRepo]
}
如您所见,您只需定义一个函数,并在其上方添加注释和注解来定义一个简单的HTTP调用。当前支持的HTTP方法有:@GET, @POST, @PATCH, @PUT, @DELETE
。然后添加您的端点,在编译时将自动发生魔法!如果想要了解如何使用路径、查询或请求体参数,请查看以下章节。
如果检查您的Generated/RetrofireSourcery.generated.swift
文件夹,您会看到一个SessionManager的扩展方法。这样,您可以决定是否要使用默认的Alamofire的SessionManager或创建自己的实现;下面是使用默认SessionManager的基本示例。
SessionManager.default.getRepo(user: "dcoletto") { (repoList, error) in
repoList?.forEach { repo in
print("Repo \(repo.name) from \(repo.owner.login)")
}
}
这就是全部内容了,仅用了大约11行代码就生成了一个网络调用(即使是计算闭合括号也包含在内:P)。
添加@Path参数
为了在请求中添加路径参数,您只需要在Swift函数中添加一个具有相同名字的参数,并在同一行上添加注释包含@Path
关键字。您可以将注释放在参数之前或之后:前面:/* @Path */ user: String
后面:user: String /* @Path */
内联:user: String // @Path
请记住,用花括号包围您端点中的变量:// @GET = /users/{user}/repos
RetrofireSwift会替换花括号内所有单词的发生以具有完全相同的名字的变量!如果您需要在变量和实际的路径参数之间设置不同的名字,您只需在等号后指定名字:/* @Path = different_name */ user: String
。这样您就可以有一个如/users/{different_name}/repos
这样的端点,而无需更改函数签名。
最终结果
// @GET = /users/{user}/repos
func getRepo(
/* @Path */ user: String
) -> [GithubRepo]
SessionManager.default.getRepo("dcoletto") {...}
上述函数将调用/users/dcoletto/repos
添加@Query参数
为了向请求中添加查询参数,您只需要在Swift函数中添加一个具有相同名字的参数,并在同一行上添加注释包含@Query
关键字。您可以将注释放在参数之前或之后:前面:/* @Query */ q: String
后面:q: String /* @Query */
内联:q: String // @Query
端点不需要任何修改,查询参数会自动添加到端点之后。
RetrofireSwift会添加所有与您的参数具有完全相同的名字的参数!如果您需要在变量和实际的路径参数之间设置不同的名字,您只需在等号后指定名字:/* @Query = q */ query: String
。这样,您就可以在维护函数参数具有有意义的名称的同时调用如/search/repositories?q=test
这样的端点。
最终结果
// @GET = /search/repositories
func searchRepo(
/* @Query */ q: String
) -> RepoList
SessionManager.default.searchRepo("retrofire swift") {...}
上述函数将调用/search/repositories?q=retrofire%20swift
添加@Body参数
为了向请求中添加请求体,您只需要在Swift函数中添加一个参数,并在同一行上添加注释包含@Body
关键字。您可以将注释放在参数之前或之后:前面:/* @Body */ body: CodableObject
后面:body: CodableObject /* @Body */
内联:body: CodableObject // @Body
端点不需要任何修改,查询参数会自动添加到端点之后。
RetrofireSwift会将对象生成JSON字符串,因此需要该对象遵循'Codable'协议。
var title: String
var body: String
var userId: Int
}
最终结果
// @POST = /posts
func postSample(
/* @Body */ body: PostReq
) -> PostRes
let req = PostReq(title: "Sample", body: "Full body", userId: 1)
SessionManager.default.postSample(body: req) {...}
上述函数将调用/posts
,该请求体为JSON字符串:{"title": "Sample", "body": "Full body", "userId": 1}
添加@Header参数
为了向您的请求添加一个标题参数,您只需要在Swift函数中添加一个参数,并在同一行注释中包含@Header
关键字、一个等号和标题名。您可以先将注释放在参数之前或之后:之前:/* @Header = Authorization */ token: String
之后:token: String /* @Header = Authorization */
内联:token: String // @Header = Authorization
使用@Headers添加更多标题
目前(2019年9月4日)使用@Headers添加更多标题不可行。但无论怎样,如果在同一个函数中需要更多参数,您可以使用多个@Header注解。
许可协议
Retrofire遵循MIT许可协议。更多详情请见LICENSE文件。