StrapiSwift 1.0.0

StrapiSwift 1.0.0

Ricardo Rauber Pereira 维护。



 
依赖关系
RestService= 1.0.1
KeyValueStorage= 1.0.0
 

  • 作者:
  • Ricardo Rauber Pereira

StrapiSwift - 连接到您的 Strapi 后端的 Swift 工具包

Build Status CocoaPods Version License Platform

这个项目旨在让您的应用程序更容易连接到您喜爱的开源 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
)

谢谢👍

本框架的创建要归功于这些优秀的人

欢迎反馈

如果您发现任何问题、卡住或者只是想聊聊,欢迎创建问题。我们将很高兴为您提供帮助。

许可

StrapiSwift 采用 MIT 许可证 发布。