用 Swift 5 编写
AlamoRecord 是一个强大而简单的框架,它消除了存在于您的网络框架和您的应用之间的通常复杂网络层。AlamoRecord 使用了 Alamofire 的力量以及 ActiveRecord 模式的概念,创建了一个网络层,使得与您的 API 交互比以往任何时候都容易。
要求
- iOS 10.0+ / macOS 10.12+ / tvOS 10.0+ / watchOS 3.0+
- Xcode 10.2+
- Swift 5.1
安装
AlamoRecord 通过 CocoaPods 提供。要安装它,只需将以下行添加到您的 Podfile 中
pod 'AlamoRecord'
开始使用
AlamoRecord的强大功能体现在四个主要组件中。
AlamoRecordObject
这些是通过API获取的数据对象。所有继承自该类的数据对象都会自动接收到内置辅助器,如创建、查找、更新和删除。这被称为CRUD。
RequestManager
这是AlamoRecord的得力助手。它们包含AlamoRecord创建应用程序网络层所需的全部网络辅助器。它们负责处理您的AlamoRecordObject
提出的每个请求。它们还包含上传和下载辅助器。
AlamoRecordURL
这些存储了在RequestManager
实例上发出正确请求所需的所有信息。
AlamoRecordError
这些是API返回的错误。在请求失败时,返回的JSON将映射到已设置的预定义字段。
示例
假设我们正在开发一个应用程序,允许用户通过帖子相互交互。
第1步
首先,我们需要创建一个符合AlamoRecordURL
的类。让我们称它为ApplicationURL
ApplicationURL
class ApplicationURL: AlamoRecordURL {
var absolute: String {
return "https://jsonplaceholder.typicode.com/\(url)"
}
private var url: String
required init(url: String) {
self.url = url
}
}
注意,为什么您只需要为符合AlamoRecordURL
的每个实例传递路径而不传递域名。这是因为您已在absolute
变量中设置了每个实例的域名。
第2步
如果您的服务器不返回自定义错误消息,则可以忽略此步骤。如果是这种情况,则可以在返回时使用基AlamoRecordError
对象。
假设我们的API返回自定义错误消息。让我们创建一个继承自AlamoRecordError
的类,命名为ApplicationError
。假设我们的JSON结构在失败请求时看起来类似于此
{
"status_code": 401,
"message": "You are not authorized to make this request.",
}
我们的类结构将非常相似于此
ApplicationError
class ApplicationError: AlamoRecordError {
let statusCode: Int?
let message: String?
private enum CodingKeys: String, CodingKey {
case statusCode = "status_code"
case message
}
}
第3步
接下来,我们需要创建一个RequestManager
的实例,并将我们刚才创建的ApplicationURL
和ApplicationError
传递给继承结构,以满足泛型需求。我们可以称它为ApplicationRequestManager
。
ApplicationRequestManager
// IDType should be of type String or Int
class ApplicationRequestManager: RequestManager<ApplicationURL, ApplicationError, IDType> {
static var `default`: ApplicationRequestManager = ApplicationRequestManager()
init() {
// See the Configuration documentation for all possible options
super.init(configuration: Configuration())
}
}
第4步
最后一歩是创建从我们的API继承自AlamoRecordObject
的数据对象,这是我们的应用程序所需的。在这个示例中,我们只有一个名为Post
的对象。
Post
// IDType should be of type String or Int
class Post: AlamoRecordObject<ApplicationURL, ApplicationError, IDType> {
let userId: Int
let title: String
let body: String
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
title = try container.decode(String.self, forKey: .title)
body = try container.decode(String.self, forKey: .body)
try super.init(from: decoder)
}
override class var root: String {
return "post"
}
override class var requestManager: RequestManager<ApplicationURL, ApplicationError, IDType> {
return ApplicationRequestManager
}
private enum CodingKeys: String, CodingKey {
case userId
case title
case body
}
}
有了这个类定义,我们期望每个Post
json看起来像这样
{
"userId": 1,
"id": 1,
"title": "This is a post's title",
"body": "This is the post's body"
}
如果我们的Post
对象封装在这个对象中
{
"post": {
"userId": 1,
"id": 1,
"title": "This is a post's title",
"body": "This is the post's body"
}
}
我们只需要简单地重写类声明中的keyPath
override class var keyPath: String? {
return "post"
}
注意requestManager
类变量被覆盖,并返回步骤3中创建的ApplicationRequestManager
。同时注意root
类变量也被重写。这两个重写都是必要的,对于每个AlamoRecordObject
的直接继承实例都是如此。
就是这样!仅仅几行代码,您的应用程序的网络层就绪,可以用于下一个部分。我们将看到使用AlamoRecord所获得的所有内置帮助器。
Post
实例
获取所有GET
https://jsonplaceholder.typicode.com/posts
Post.all(success: { (posts: [Post]) in
// Do something with the posts
}) { (error) in
// Handle the error
}
Post
实例
创建一个POST
https://jsonplaceholder.typicode.com/posts
let parameters: [String: Any] = ["userId": user.id,
"title": title,
"body": body]
Post.create(parameters: parameters, success: { (post: Post) in
// Do something with the post
}) { (error) in
// Handle the error
}
Post
的一个实例
查找GET
https://jsonplaceholder.typicode.com/posts/1
Post.find(id: 1, success: { (post: Post) in
// Do something with the post
}) { (error) in
// Handle the error
}
Post
的实例
更新PUT
https://jsonplaceholder.typicode.com/posts/1
let parameters: [String: Any] = ["userId": user.id,
"title": title,
"body": body]
post.update(parameters: parameters, success: { (post: Post) in
// Do something with the post
}) { (error) in
// Handle the error
}
这也可以在类级别完成
Post.update(id: 1, parameters: parameters, success: { (post: Post) in
// Do something with the post
}) { (error) in
// Handle the error
}
Post
的实例
删除DELETE
https://jsonplaceholder.typicode.com/posts/1
post.destroy(id: 1, success: {
// The post is now destroyed
}) { (error) in
// Handle the error
}
这也可以在类级别完成
Post.destroy(id: 1, success: {
// The post is now destroyed
}) { (error) in
// Handle the error
}
上传文件
requestManager.upload(url: url,
multipartFormData: data,
multipartFormDataName: dataName,
success: { (any: Any?) in
// Upload was successful
}) { (error) in
// Handle the error
}
下载文件
requestManager.download(url: url,
destination: destination,
progress: { (progress) in
// Check the progress
}, success: { (url) in
// Do something with the url
}) { (error) in
// Handle the error
}
指定目标位置是可选的。如果没有提供目标位置,文件将保存到临时位置。如果在未提供目标位置的情况下再次发起下载请求,则该文件将被覆盖。
下载示例项目以查看在使用 AlamoRecord 创建与 API 交互的应用是多么简单!
作者
原始概念由 Rick Pernikoff 设计。AlamoRecord 实现由 Dalton Hinterscher 完成。
许可证
AlamoRecord 在 MIT 许可下可用。更多信息请参阅 LICENSE 文件。