StrapiSwift - 连接到您的 Strapi 后端的 Swift 工具包
这个项目旨在让您的应用程序更容易连接到您喜爱的开源 Headless CMS — Strapi
的后端,更多信息请参阅 https://strapi.io/
配置
此项目具有依赖关系
CocoaPods
如果您正在使用 CocoaPods,请在 Podfile 添加以下内容并运行 pod install
。
target 'Your target name' do
pod 'StrapiSwift', '~> 1.0'
end
手动安装
如果您想手动将其添加到您的项目中(不使用包管理器),只需将 Classes
文件夹中的所有文件复制到您的项目中即可。
您还需要安装依赖项。请遵循其说明。
使用方法
导入 StrapiSwift
要使用 StrapiSwift
,只需要导入这个包。
import StrapiSwift
启动服务
要启动服务,您需要在 Strapi 实例中指定您的 Strapi
主机。
let strapi = Strapi(scheme: .http, host: "localhost", port: 1337)
但您也可以使用共享实例。
let strapi = Strapi.shared
strapi.scheme = .http
strapi.host = "localhost"
strapi.port = 1337
内容类型的默认路由
当您在 Strapi
中创建内容类型时,它将自动为该内容类型生成许多路由(例如,创建记录、读取记录、更新记录和删除记录)(REST API
)。这听起来很熟悉?是的,它直接提供了完整的 CRUD
功能!这是 Strapi
能够做到的令人惊叹的事情之一。因此,StrapiSwift
涵盖了所有的这些请求,请参见下文。
假设我们有一个名为 restaurant
的内容类型,其中包含 name
(名称)和 price
(价格)字段。这里有几种将它集成到其中的示例。
CreateRequest (POST)
为了启动或扩展我们的数据库,我们可以添加一些记录。
let request = CreateRequest(
contentType: "restaurant",
parameters: [
"name": "Super Pizza",
"price": 3
]
)
strapi.exec(request: request) { response in
guard let record = response.dictionaryValue(),
let id = record["id"] as? Int
else {
return
}
print("Created record with id: \(id)")
}
CountRequest (GET)
假设我们想知道这个内容类型中有多少记录,我们可以对其进行计数。
let request = CountRequest(contentType: "restaurant")
strapi.exec(request: request) { response in
guard let count = response.intValue() else {
return
}
print("Total records: \(count)")
}
QueryRequest (GET)
现在你需要做到的是通过一些筛选条件和排序搜索所有餐厅
let request = QueryRequest(contentType: "restaurant")
request.filter(by: "name", contains: "pizza")
request.filter(by: "price", greaterThanOrEqualTo: 3)
request.sort(by: "price")
strapi.exec(request: request) { response in
guard let list = response.decodableValue(of: [Restaurant].self) else {
return
}
print("Records found: \(list)")
}
FetchRequest (GET)
有时我们只知道一个记录的 id
,我们需要获取它的所有信息。为此,我们可以通过id获取记录
let request = FetchRequest(
contentType: "restaurant",
id: 10
)
strapi.exec(request: request) { response in
guard let record = response.decodableValue(of: Restaurant.self) else {
return
}
print("Data retrieved: \(record)")
}
UpdateRequest (PUT)
价格区间不对?没问题,我们可以更新记录
let request = UpdateRequest(
contentType: "restaurant",
id: 10,
parameters: [
"price": 5
]
)
strapi.exec(request: request) { response in
guard let record = response.decodableValue(of: Restaurant.self) else {
return
}
print("Updated record: \(record)")
}
DestroyRequest (DELETE)
哎呀,我真的很喜欢那家餐厅!很抱歉你想删除它,但这是你可以这样做的
let request = DestroyRequest(
contentType: "restaurant",
id: 10
)
strapi.exec(request: request) { response in
guard let record = response.dictionaryValue() else {
return
}
print("Destroyed record: \(record)")
}
Custom Request (?)
所以你想创建自己的请求,因为你有自定义路由或者只是想自己做,这里有你可以这样做的方法
let request = StrapiRequest(
method: .get,
contentType: "restaurants", // You can use any route here
parameters: [
"price_eq": 3
]
)
strapi.exec(request: request) { response in
guard let list = response.decodableValue(of: [Restaurant].self) else {
return
}
print("Data retrieved: \(list)")
}
用户 - 权限
Strapi
带有一些令人惊叹的插件,其中之一就是管理用户和权限。这里有一些我们用于此目的的酷方法。
用户注册
目前,StrapiSwift
只与本地提供者兼容用户注册。为此,您可以从 Strapi
实例直接调用它。
strapi.register(
username: "My name",
email: "[email protected]",
password: "VeryStrongPassword@2020") { response in
guard let record = response.decodableValue(of: User.self) else {
return
}
print("New user: \(record)")
}
登录
确认用户后,您可以轻松登录。
strapi.login(
identifier: "[email protected]",
password: "VeryStrongPassword@2020") { response in
guard let record = response.decodableValue(of: User.self) else {
return
}
print("Logged in user: \(record)")
}
忘记密码
如果您忘记了密码,这里是如何请求发送一个重置密码的电子邮件。
strapi.forgotPassword(email: "[email protected]") { response in
guard let record = response.dictionaryValue() else {
return
}
print("Some data: \(record)")
}
重置密码
收到重置密码的代码电子邮件后,您可以按此方法重置密码。
strapi.resetPassword(
code: "somerandomcode",
password: "EvenStrongerPassword@2020",
passwordConfirmation: "EvenStrongerPassword@2020") { response in
guard let record = response.dictionaryValue() else {
return
}
print("Some data: \(record)")
}
发送电子邮件确认
嗯,没有收到电子邮件确认?您可以使用这个再次请求。
strapi.sendEmailConfirmation(email: "[email protected]") { response in
guard let record = response.dictionaryValue() else {
return
}
print("Some data: \(record)")
}
我
现在您只想检索自己的数据(User
),这也很简单。
strapi.me { response in
guard let record = response.decodableValue(of: User.self) else {
return
}
print("My data: \(record)")
}
用户会话
当您使用login
方法时,它将自动保存检索到的令牌。如果您没有更改storage
属性,它将把令牌保存在您的Keychain
中。
如果您需要在请求中设置此令牌,您可以在strapi.exec(...)
方法上设置带有StrapiAuthorizationInterceptor
实例的interceptor
参数。
let request = StrapiRequest(
method: .get,
contentType: "restaurants", // You can use any route here
parameters: [
"price_eq": 3
]
)
let interceptor = StrapiAuthorizationInterceptor(storage: strapi.storage)
strapi.exec(request: request, interceptor: interceptor) { response in
guard let list = response.decodableValue(of: [Restaurant].self) else {
return
}
print("Data retrieved: \(list)")
}
您可以根据RestService
框架上的说明创建自己的interceptor
。
上传
另一个非常棒的插件是Upload
,您可以使用它将文件上传到您的Strapi
服务器,并与您的记录创建关联。例如,在一个聊天应用中发送音频非常简单。
数据上传
让我们上传一个文本文件到一个记录中
let text = "..."
strapi.upload(
contentType: "about",
id: 1,
field: "terms",
filename: "terms.txt",
mimeType: "text/plain",
fileData: text.data(using: .utf8)!) { response in
guard let record = response.dictionaryValue() else {
return
}
print("Some data: \(record)")
}
图片上传
由于我们通常需要进行大量图片上传,比如更新您的个人资料图片,所以我们为此提供了一个方便的方法。
let image = UIImage(...)
strapi.upload(
contentType: "about",
id: 1,
field: "terms",
image: image,
compressionQuality: 90) { response in
guard let record = response.dictionaryValue() else {
return
}
print("Some data: \(record)")
}
错误处理
是的,不幸的是,错误可能会发生,但我们可以处理其中的一些。当发生一些非内容错误时,如服务器返回的500状态码
,response
对象将设置一个error
属性。此外,您的Strapi
后端可能会在响应体中发送一些自定义错误消息,对于这种情况,您可以检查strapiError()
方法。您需要做的事情如下:
strapi.exec(request: request) { response in
if let error = response.error {
// There was a connection failure
print(error)
return
if let error = response.strapiError() {
// Oh no, something went wrong with your data :(
print(error)
return
}
// Cool, no errors!
}
strapiError()
方法将返回一个StrapiError
模型的实例。这个对象有几个有用的属性
- statusCode: (
Int
) 响应体中给出的状态码 - error: (
String
) 响应体中给出的错误文本 - response: (
Data?
) 服务器原始响应 - message: (
String?
) 当响应体中的message
字段为String
类型时的文本消息 - messages: (
[StrapiMessage]
) 当响应体中的message
字段为Array
类型时,消息列表 - data: (
Any?
) 响应体中data
字段的内容
ContentType
此外还有一个特殊的对象叫做 ContentType
。正如您所见,它非常简单
struct ContentType: RawRepresentable, Equatable, Hashable {
typealias RawValue = String
let rawValue: String
init(rawValue: String) {
self.rawValue = rawValue
}
}
使用 ContentType
可以创建 static
属性来避免在调用中使用字符串。您可以使用这些属性进行请求
extension ContentType {
static let restaurant = RestPath(rawValue: "restaurant")
}
let request = FetchRequest(
contentType: .restaurant,
id: 10
)
👍
谢谢本框架的创建要归功于这些优秀的人
- Gray 公司:https://www.graycompany.com.br/
- Strapi:https://strapi.io/
- Swift by Sundell:https://www.swiftbysundell.com/
- Hacking with Swift:https://www.hackingwithswift.com/
- Ricardo Rauber:http://ricardorauber.com/
欢迎反馈
如果您发现任何问题、卡住或者只是想聊聊,欢迎创建问题。我们将很高兴为您提供帮助。
许可
StrapiSwift 采用 MIT 许可证 发布。