SwiftApiAdapter 是一个 Swift 包,旨在简化 Swift 应用程序中检索远程内容(如文本和图像)的过程。它提供了一个强大的框架来管理 API 连接器、异步处理请求和处理响应,重点是效率和有效性。此包尤其适用于调用生成式 AI API 和加载网页内容。
User-Agent
。extraData
字段存储有关 API 的其他必要信息。为了符合标准 HTTP 用法,如果 HTTP 方法是 GET
,SwiftApiAdapter 不会附加任何请求体。如果您的配置指定了 GET
以及非空的主体,则该主体将被忽略。如果您需要发送有效负载,请切换到 POST
或 PUT
等方法。
通过 Swift Package Manager 将 SwiftApiAdapter 添加到您的项目中,方法是在您的 Package.swift
中包含它。
dependencies: [
.package(url: "https://github.com/RayKitajima/SwiftApiAdapter.git", from: "1.0.0")
]
确保存储库 URL 与您的 Swift 包的位置匹配。
在需要 API 处理的 Swift 文件中导入 SwiftApiAdapter
import SwiftApiAdapter
let apiConnector = ApiConnectorManager.shared.getConnector(for: "ExampleAPI")
User-Agent
let endpoint = URL(string: "https://example.com/api")!
let headers = [
"User-Agent": "Your Custom User-Agent",
"Content-Type": "application/json"
]
let response = await apiConnector.requester.processJsonApi(
endpoint: endpoint,
method: "GET",
headers: headers,
body: "" // Empty body for GET request; otherwise body is ignored
)
此示例演示如何使用 ApiContentLoader
将特定数据从 API 响应加载到您的应用程序中。该示例获取嵌套在 "data"
JSON 对象中的键为 "result"
的值。
定义 ApiContent:
通过指定端点、HTTP 方法、头部以及从 API 响应中提取特定数据所需的任何参数来配置您的 API 内容。您还可以使用 extraData
字段添加管理 API 所需的任何额外数据。
let apiContent = ApiContent(
id: UUID(),
name: "Example API Content",
endpoint: "https://exampleapi.com/data",
method: .get,
headers: ["Authorization": "Bearer your_access_token"],
body: "", // No body needed for GET request
arguments: ["result": "[\"data\"][\"result\"]"], // Path to extract `result` from the JSON response
extraData: ["info": "additional info"] // Additional data
)
使用 ApiContentLoader 加载内容:
使用 ApiContentLoader.load
方法进行 API 调用并处理响应,根据提供的路径提取 result
值。
do {
let apiContentRack = try await ApiContentLoader.load(
contextId: UUID(), // Context ID to uniquely identify this load operation
apiContent: apiContent
)
if let apiContentRack = apiContentRack {
let resultValue = apiContentRack.arguments["result"] ?? "No result found"
print("API Data Loaded: \(resultValue)")
if let extraInfo = apiContent.extraData?["info"] as? String {
print("Extra Info: \(extraInfo)")
}
} else {
print("Failed to load API data.")
}
} catch {
print("An error occurred: \(error)")
}
您还可以使用 ApiContentLoader
使用相同的接口加载和处理网页内容。
let apiContentPage = ApiContent(
id: UUID(),
name: "Web Page Content",
endpoint: "https://example.com/page",
method: .get,
headers: ["Authorization": "Bearer your_access_token"],
body: "", // No body needed for GET request
contentType: .page
)
使用 ApiContentLoader 加载网页内容:
使用 ApiContentLoader.load
方法发出请求并处理网页内容。content
、url
、ogimage
和 finalUrl
字段会自动提取并设置为 ApiContentRack
。
do {
let apiContentRack = try await ApiContentLoader.load(
contextId: UUID(), // Context ID to uniquely identify this load operation
apiContent: apiContentPage
)
if let apiContentRack = apiContentRack {
let content = apiContentRack.arguments["content"] ?? "No content found"
let url = apiContentRack.arguments["url"] ?? "No URL found"
let ogimage = apiContentRack.arguments["ogimage"] ?? "No image found"
let finalUrl = apiContentRack.arguments["finalUrl"] ?? "Actual endpoint"
print("Web Page Content Loaded: \(content)")
print("URL: \(url)")
print("OpenGraph Image: \(ogimage)")
print("Actual endpoint: \(finalUrl)")
} else {
print("Failed to load web page content.")
}
} catch {
print("An error occurred: \(error)")
}
以下示例演示了如何将 SwiftApiAdapter
与 SwiftUI 集成,从而使您能够根据 API 请求计数和其他动态数据反应式地更新 UI。
创建一个控制器,用于管理 API 交互并更新可观察属性
import SwiftUI
class ApiController: NSObject, ObservableObject {
@Published var cumulativeRequested: Int = 0
@Published var cumulativeExecuted: Int = 0
var apiConnector: ApiConnector?
func generate() async throws {
let connector = ApiConnectorManager.shared.getConnector(for: "ExampleAPI")
self.apiConnector = connector
connector.initTransaction()
DispatchQueue.main.async {
self.apiConnector?.executor.$cumulativeRequested.assign(to: &self.$cumulativeRequested)
self.apiConnector?.executor.$cumulativeExecuted.assign(to: &self.$cumulativeExecuted)
}
connector.executor.start()
}
}
利用 SwiftUI 视图来反映 API 操作的状态
import SwiftUI
struct ApiView: View {
@ObservedObject var apiController: ApiController
var body: some View {
HStack(spacing: 5) {
Text("Generating")
Text("(\(apiController.cumulativeExecuted)/\(apiController.cumulativeRequested))")
.foregroundColor(.secondary)
Image(systemName: "ellipsis")
.animation(.easeInOut, value: apiController.cumulativeExecuted)
}
}
}
SwiftUI 可以根据从 API 获取的数据动态更新视图。下面,我们将演示如何在 SwiftUI 视图中使用 ApiContentLoader
来加载和显示 base64 编码的图像和文本内容。
let apiContentImage = ApiContent(
id: UUID(),
name: "Image API Content",
endpoint: "https://exampleapi.com/image",
method: .get,
headers: ["Authorization": "Bearer your_access_token"],
body: "",
arguments: ["image": "[\"data\"][0][\"message\"][\"content\"]"],
contentType: .base64image,
extraData: ["info": "additional image info"]
)
import SwiftUI
struct ImageView: View {
@ObservedObject var apiController: ApiController
var body: some View {
VStack {
if let imageData = apiController.imageData {
Image(uiImage: UIImage(data: imageData)!)
.resizable()
.aspectRatio(contentMode: .fit)
} else {
Text("Loading Image...")
}
}
.onAppear {
Task {
await apiController.loadImageContent()
}
}
}
}
import Combine
class ApiController: ObservableObject {
@Published var imageData: Data?
func loadImageContent() async {
let apiContentImage = ApiContent(
id: UUID(),
name: "Image API Content",
endpoint: "https://exampleapi.com/image",
method: .get,
headers: ["Authorization": "Bearer your_access_token"],
body: "",
arguments: ["image": "[\"data\"][0][\"message\"][\"content\"]"],
contentType: .base64image
)
do {
let apiContentRack = try await ApiContentLoader.load(
contextId: UUID(),
apiContent: apiContentImage
)
if let apiContentRack = apiContentRack,
let base64String = apiContentRack.arguments["image"],
let imageData = Data(base64Encoded: base64String) {
DispatchQueue.main.async {
self.imageData = imageData
}
}
} catch {
print("Error loading image: \(error)")
}
}
}
let apiContentText = ApiContent(
id: UUID(),
name: "Text API Content",
endpoint: "https://exampleapi.com/text",
method: .get,
headers: ["Authorization": "Bearer your_access_token"],
body: "",
arguments: ["text": "[\"choices\"][0][\"message\"][\"content\"]"],
contentType: .text,
extraData: ["info": "additional text info"]
)
import SwiftUI
struct TextView: View {
@ObservedObject var apiController: ApiController
var body: some View {
Text(apiController.textData ?? "Loading Text...")
.onAppear {
Task {
await apiController.loadTextContent()
}
}
}
}
import Combine
class ApiController: ObservableObject {
@Published var textData: String?
func loadTextContent() async {
let apiContentText = ApiContent(
id: UUID(),
name: "Text API Content",
endpoint: "https://exampleapi.com/text",
method: .get,
headers: ["Authorization": "Bearer your_access_token"],
body: "",
arguments: ["text": "[\"choices\"][0][\"message\"][\"content\"]"],
contentType: .text
)
do {
let apiContentRack = try await ApiContentLoader.load(
contextId: UUID(),
apiContent: apiContentText
)
if let apiContentRack = apiContentRack,
let text = apiContentRack.arguments["text"] {
DispatchQueue.main.async {
self.textData = text
}
}
} catch {
print("Error loading text: \(error)")
}
}
}
这些示例说明了如何在 SwiftUI 应用程序中反应式地获取和显示 API 内容。它们展示了一种在视图出现时启动 API 请求并根据结果更新视图状态的模式,从而将网络操作无缝集成到 SwiftUI 生命周期中。
let connector = ApiConnectorManager.shared.getConnector(for: "Tag")
ApiConnectorManager.shared.clearConnector(for: "Tag")
ApiConnectorManager.shared.clearAllConnectors()
您可以自定义每个 API 请求的头部,从而可以根据端点要求设置 User-Agent
和其他必要的头部。但是,请记住,对于 GET 请求,任何提供的主体数据都将被忽略。
我们鼓励贡献!请随时提交拉取请求或打开问题以建议功能、改进或错误修复。