欢迎使用 Netguru 网络模块。
NgNetworkModule 是一个 简单、高度可配置 的 iOS 和 MacOS 模块,用于 执行 网络 调用 和 解析 收到的 响应。
Combine
)async/await
)NgNetworkModule 可通过 Swift Package Manager 获取。
dependencies: [
.package(
url: "https://github.com/netguru/ng-ios-network-module.git",
from: "1.0.3"
)
]
1. Select File > Swift Packages > Add Package Dependency.
2. Enter the repository URL.
3. Wait until the dependencies are resolved.
该模块有 3 种变体
import NgNetworkModuleCore
Combine
) - 一个响应式 API,将响应作为事件或错误发出。需要导入 NgNetworkModuleCore
才能工作!import ReactiveNgNetworkModule
async/await
) - 一个利用现代 Swift 并发的 API。需要导入 NgNetworkModuleCore
才能工作!import ConcurrentNgNetworkModule
import NgNetworkModuleCore
(optionally) import ReactiveNgNetworkModule / ConcurrentNgNetworkModule
...
let baseURL = URL(string: "https://your.base.url")!
let requestBuilder = DefaultRequestBuilder(baseURL: baseURL)
let networkModule = DefaultNetworkModule(requestBuilder: requestBuilder)
为了正确解析,请求描述必须符合 NetworkRequest
协议
struct SampleGetNetworkRequest: NetworkRequest {
let path = "/welcome"
let method = NetworkRequestType.get
}
或
struct SamplePostNetworkRequest: NetworkRequest {
let method = NetworkRequestType.post
let path = "/welcome"
let body: Encodable? = ["foo": "bar"]
}
或
struct SamplePostNetworkRequest2: NetworkRequest {
let method = NetworkRequestType.post
let path = "/welcome2"
let bodyData: Data? = Data()
}
定义了这样的请求后,您可以使用便捷的 API 来 编码 和 调用 它,(可选地)解码 收到的响应
struct ExpectedResponse: Decodable {}
...
let request = SampleGetRequest()
...
networkModule.performAndDecode(request: request, responseType: ExpectedResponse.self)
switch result {
case let .success(response):
// Handle decoded response here
case let .failure(error):
// Handle error here
}
}
networkModule.perform(request: networkRequest) { result in
networkModule.perform(urlRequest: urlRequest) { result in
networkModule.performAndDecode(urlRequest: urlRequest, responseType: ExpectedResponse.self) { result in
networkModule.performAndDecode(request: networkRequest, responseType: ExpectedResponse.self) { result in
switch result {
case let .success(response):
// Handle response here
case let .failure(error):
// Handle error here
}
}
Combine
) - 一个响应式 API,将响应作为事件或错误发出.receive(on: DispatchQueue.main)
,因为 NgNetworkModuleCore
的设计保证了这一点。perform(request: networkRequest)
perform(urlRequest: urlRequest)
performAndDecode(request: networkRequest, responseType: ExpectedResponse.self)
performAndDecode(urlRequest: urlRequest, responseType: ExpectedResponse.self)
.sink(
receiveCompletion: { completion in
switch completion {
case .finished:
// Handle completion here (optionally)
case let .failure(error):
// Handle error here
}
},
receiveValue: { response in
// Handle response here
})
.store(in: &cancellables)
async/await
) - 一个利用现代 Swift 并发的 APIdo {
let response = try await networkModule.perform(request: networkRequest)
let response = try await networkModule.perform(urlRequest: urlRequest)
let response = try await networkModule.performAndDecode(urlRequest: urlRequest, responseType: ExpectedResponse.self)
let response = try await networkModule.performAndDecode(request: networkRequest, responseType: ExpectedResponse.self)
// Handle response here
} catch {
// Handle error here
}
let accessTokenProvider = ... // Implement AuthenticationTokenProvider or just use String
let accessTokenHeaderName = "Authorization"
addTokenAction = AddAuthenticationTokenNetworkModuleAction(
authenticationTokenProvider: accessTokenProvider,
authenticationTokenHeaderFieldName: accessTokenHeaderName
)
...
let networkModule = DefaultNetworkModule(
requestBuilder: requestBuilder,
actions: [addTokenAction] // <-- Include additional Actions here
)
...
networkModule.perform(request: networkRequest) { ... }
/// An Action extracting an updated Access Token from a received Network Response:
struct RetrieveAccessTokenAction: NetworkModuleAction {
private let accessTokenHeaderName = "Access-token"
func performBeforeExecutingNetworkRequest(request: NetworkRequest?, urlRequest: inout URLRequest) {
// Noop
}
func performAfterExecutingNetworkRequest(request: NetworkRequest?, networkResponse: NetworkResponse) {
guard let headerFields = networkResponse.networkResponse.allHeaderFields,
let accessToken = headerFields[accessTokenHeaderName] as? String else {
return
}
// Save retrieved access token
}
}
将操作添加到网络模块
let action = RetrieveAccessTokenAction()
let networkModule = DefaultNetworkModule(
requestBuilder: requestBuilder,
actions: [action] // <-- Include additional Actions here
)
NetworkError.requestParsingFailed
NetworkRequest
结构解析为 URLRequest
。parameters
、body
或 bodyData
)已正确定义。NetworkError.responseParsingFailed
NetworkModule
未能将收到的响应解码为提供的数据类型。NetworkError.noResponseData
NetworkError.serverError(code:message:)
NetworkError.notFound
NetworkError.forbidden
NetworkError.unauthorized
NetworkError.invalidRequest(code:message:)
NetworkError.cancelled
有一个示例应用程序展示了 NgNetworkModule 的多功能性。它可以在 NetworkModuleSampleApp
文件夹中找到,并使用 Xcode 项目文件打开。该应用程序使用 SwiftFormat
依赖项(从 NgNetworkModule 获取)以确保正确的代码格式。
该应用程序基于免费的 API 服务,用于 最终空间 动画系列。它允许您浏览剧集列表,查看剧集详情以及其中出现的角色。它完全使用 SwiftUI 编写,目标是 iOS 16。“兴趣点”
HomeScene
- 主应用视图,允许选择应使用 NgNetworkModule 公开的哪个 API(经典、响应式或 async/await)来从 最终空间 API 服务 获取数据。EpisodeListViewModel
- EpisodeListScene
的 视图模型,展示了获取、解析和向视图提供剧集列表数据。EpisodeViewModel
- EpisodeScene
的 视图模型,展示了获取、解析和提供渲染剧集详情视图所需的数据(主要是角色数据)。或者,在 NetworkModuleSampleApp
中,有一个 Playground
文件夹,其中包含一个 playground 文件,也展示了 NgNetworkModule API。
它使用几个内部源文件,例如 FetchCharacterRequest
和 FetchCharacterResponse
,以提高代码可读性。
如果您想帮助我们改进模块,请随时 贡献!
另请参阅参与此项目的 贡献者 列表。
本项目根据 MIT 许可证获得许可。