Netguru 网络模块

欢迎使用 Netguru 网络模块
NgNetworkModule 是一个 简单高度可配置 的 iOS 和 MacOS 模块,用于 执行 网络 调用解析 收到的 响应

主要特性

集成

要求

将模块添加到您的应用

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.

使用 NgNetworkModule

可用的 API 变体

该模块有 3 种变体

import NgNetworkModuleCore
import ReactiveNgNetworkModule
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
    }
}

可用的 API

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
    }
}
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)
do {
    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
)

错误处理

示例内容

运行示例应用程序

有一个示例应用程序展示了 NgNetworkModule 的多功能性。它可以在 NetworkModuleSampleApp 文件夹中找到,并使用 Xcode 项目文件打开。该应用程序使用 SwiftFormat 依赖项(从 NgNetworkModule 获取)以确保正确的代码格式。
该应用程序基于免费的 API 服务,用于 最终空间 动画系列。它允许您浏览剧集列表,查看剧集详情以及其中出现的角色。它完全使用 SwiftUI 编写,目标是 iOS 16。“兴趣点”

运行示例 Playground

或者,在 NetworkModuleSampleApp 中,有一个 Playground 文件夹,其中包含一个 playground 文件,也展示了 NgNetworkModule API。
它使用几个内部源文件,例如 FetchCharacterRequestFetchCharacterResponse,以提高代码可读性。

贡献

如果您想帮助我们改进模块,请随时 贡献

作者 & 项目维护者

另请参阅参与此项目的 贡献者 列表。

许可证

本项目根据 MIT 许可证获得许可。

相关仓库