
新增Package.swift和Package.resolved文件以支持Swift Package管理,创建API相关文件(API.swift、APICaller.swift、APIConstants.swift、APIEndpoints.swift、APIService.swift、APILogger.swift、APIModels.swift、Integration-Guide.md)以实现API请求管理和网络交互功能,增强项目的功能性和可扩展性。同时更新.gitignore以排除构建文件和临时文件。
4.9 KiB
4.9 KiB
APIClient 集成指南
🔧 在其他文件中使用 APIClient
方法一:直接实例化 (推荐用于测试)
import SwiftUI
struct ContentView: View {
@State private var isLoading = false
@State private var result = ""
var body: some View {
VStack {
Button("测试 API") {
testAPI()
}
.disabled(isLoading)
if isLoading {
ProgressView("请求中...")
}
Text(result)
}
}
private func testAPI() {
isLoading = true
Task {
do {
// 创建 API 客户端实例
let apiClient = LiveAPIClient(
baseURL: URL(string: "https://your-api.com")!
)
// 发起请求
let response: YourResponseModel = try await apiClient.get(
path: "/your/endpoint",
queryParameters: ["key": "value"]
)
await MainActor.run {
result = "成功: \(response)"
isLoading = false
}
} catch {
await MainActor.run {
result = "错误: \(error.localizedDescription)"
isLoading = false
}
}
}
}
}
方法二:使用单例模式
// 在需要使用的文件中
private func makeAPIRequest() async {
do {
let response: SomeModel = try await APIClientManager.shared.get(
path: "/endpoint"
)
// 处理响应
} catch {
// 处理错误
}
}
方法三:TCA 集成 (当 TCA 可用时)
import ComposableArchitecture
@Reducer
struct MyFeature {
@ObservableState
struct State: Equatable {
var data: [Item] = []
var isLoading = false
}
enum Action: Equatable {
case loadData
case dataLoaded([Item])
case loadingFailed(String)
}
@Dependency(\.apiClient) var apiClient
var body: some ReducerOf<Self> {
Reduce { state, action in
switch action {
case .loadData:
state.isLoading = true
return .run { send in
do {
let items: [Item] = try await apiClient.get(path: "/items")
await send(.dataLoaded(items))
} catch {
await send(.loadingFailed(error.localizedDescription))
}
}
case let .dataLoaded(items):
state.isLoading = false
state.data = items
return .none
case let .loadingFailed(error):
state.isLoading = false
// 处理错误
return .none
}
}
}
}
🚨 常见问题解决
1. "Cannot find 'APIClientManager' in scope"
原因: Swift 模块系统问题,需要确保正确导入
解决方案:
// 方案 A: 直接实例化
let apiClient = LiveAPIClient(baseURL: URL(string: "https://api.com")!)
// 方案 B: 确保文件在同一个 target 中
// 检查 Xcode 项目设置,确保 APICaller.swift 和使用文件在同一个 target
// 方案 C: 使用原生 URLSession (临时方案)
let (data, _) = try await URLSession.shared.data(for: request)
2. TCA 导入问题
原因: ComposableArchitecture 模块配置问题
解决方案:
- 检查 Package Dependencies 是否正确添加
- 确保 target 正确链接了 TCA
- Clean Build Folder (⌘+Shift+K)
- 重新构建项目
3. 网络请求失败
常见错误处理:
do {
let response = try await apiClient.get(path: "/endpoint")
// 成功处理
} catch let urlError as URLError {
switch urlError.code {
case .notConnectedToInternet:
print("网络不可用")
case .timedOut:
print("请求超时")
case .cannotFindHost:
print("无法找到服务器")
default:
print("网络错误: \(urlError.localizedDescription)")
}
} catch {
print("其他错误: \(error)")
}
📝 最佳实践
- 错误处理: 始终使用 do-catch 处理异步请求
- 主线程更新: 使用
await MainActor.run
更新 UI - 取消请求: 在适当时候取消不需要的请求
- 重试机制: 对于网络错误实现重试逻辑
- 缓存策略: 考虑实现适当的缓存机制
🔄 迁移步骤
从原生 URLSession 迁移到 APIClient:
- 保留现有代码 - 确保功能正常
- 逐步替换 - 一个接口一个接口地迁移
- 测试验证 - 每次迁移后进行测试
- 清理代码 - 移除不需要的原生实现
这样可以确保平滑的迁移过程,避免破坏现有功能。