HTTPKit is a highly versatile toolkit for managing all sorts of HTTP requests directly within SwiftUI or UIKit. This package was designed to make network calls easier and to make them require less code.
To integrate using Apple's Swift Package Manager, navigate to your Xcode project, select Package Dependencies and click the + icon to search for https://github.com/xAstralMars/HTTPKit.
Alternatively, add the following as a dependency to your Package.swift:
dependencies: [
.package(url: "https://github.com/xAstralMars/HTTPKit", from: "0.1.0")
]If you prefer not to use any of the aforementioned dependency managers, you can integrate HTTPKit into your project manually. Simply drag the Sources Folder into your Xcode project.
HTTPKit has a relatively simple syntax, supporting async/await, and errors are very easy to handle. You can easily decode responses using Codable syntax in Swift.
Here's how to send a GET request, using the NetworkClient object:
- First, define your URL:
let getUrl = URL(string: "https://example.com/api/resource")!- Next, define your
Decodableobject, this makes it easier to convert JSON data into a Swift structure:
struct GetResponse: Decodable {
let id: Int
let message: String
}- Create your
NetworkCallobject instance, this defines the options for the final network request:
let networkCall = NetworkCall(
method: .GET,
body: nil,
url: getUrl,
headers: nil,
retry: false,
timeout: nil
)- Finally, send the network request:
Task {
do {
let response: GetResponse = try await NetworkClient.shared.request(networkCall)
print("Success: \(response)")
} catch {
print("Error: \(error.localizedDescription)")
}
}HTTPKit also makes it easier to directly integrate with SwiftUI. With NetworkView, you can show views with 3 states: loaded, error, and loading, with a simple closure syntax. Here's an example with a GET request (without any coding/decoding):
var body: some View {
let networkCall = NetworkCall(
method: .GET,
url: URL(string: "https://example.com/v1/resource")
)
NetworkView(networkCall: networkCall) { data in
Text("Data loaded: \(String(describing: data))")
} loading: {
ProgressView("Loading...")
} failure: { error in
Text("Error: \(error.localizedDescription)")
}
}The NetworkClient struct provides a singleton-based client for handling network requests. It supports JSON-based HTTP requests with customizable headers, body, and timeout configurations. This client also has a retry mechanism for handling failed requests.
| Property | Type | Description |
|---|---|---|
shared |
NetworkClient |
The singleton instance of NetworkClient for shared access throughout your project. |
| Initializer | Description |
|---|---|
private init() |
Private initializer to enforce singleton usage. |
Asynchronously executes a network call based on the provided configuration in NetworkCall.
public func request<T: Decodable>(_ networkCall: NetworkCall) async throws -> TParameters:
| Name | Type | Note |
|---|---|---|
networkCall |
NetworkCall |
Encapsulates details of the network request, including URL, HTTP method, headers, timeout, request body, and retry policy. |
Throws:
NSErrorwith domain"com.httpkit.invalidURL"and localized description "Invalid URL" if the provided URL isnil.- Errors from
makeRequestif there are issues during the request execution.
Returns:
- A decoded response of type
T, whereTconforms toDecodable.
A private helper method to execute a URLRequest with retry functionality.
private func makeRequest<T: Decodable>(_ request: URLRequest, retry: Bool, maxRetries: Int = 3) async throws -> TParameters:
| Name | Type | Note |
|---|---|---|
request |
URLRequest |
The configured URLRequest instance. |
retry |
Bool |
Determines whether the request should be retried on failure. |
maxRetries |
Int (default 3) |
The maximum number of retry attempts, applicable if retry is true. |
Throws:
NSErrorwith domain"com.httpkit.invalidResponse"if the response status code is not within the 200–299 range.- The last error encountered during retries if all retry attempts fail.
Returns:
- A decoded response of type
T, whereTconforms toDecodable.
let networkCall = NetworkCall(url: URL(string: "https://api.example.com/data"),
method: .get,
headers: ["Authorization": "Bearer token"],
timeout: 10,
retry: true)
do {
let response: SomeDecodableType = try await NetworkClient.shared.request(networkCall)
// Handle successful response
} catch {
// Handle error
}The NetworkView struct is a generic SwiftUI view that handles different states of a network request, including loading, success, and failure. It uses a NetworkCall configuration to make requests and allows custom views for loading, content, and failure states.
| Property | Type | Description |
|---|---|---|
networkState |
NetworkState |
The current state of the network request, initialized to .loading. |
networkCall |
NetworkCall |
The network call configuration, containing URL, HTTP method, headers, and other request parameters. |
content |
(Data) -> Content |
A view builder closure for rendering the view in the loaded state, receiving the loaded data. |
loading |
() -> LoadingView |
A view builder closure for rendering the view in the loading state. |
failure |
(Error) -> FailureView |
A view builder closure for rendering the view in the failure state, receiving an error. |
| Initializer | Description |
|---|---|
init(networkCall: NetworkCall, content: @escaping (Data) -> Content, loading: @escaping () -> LoadingView, failure: @escaping (Error) -> FailureView) |
Initializes the NetworkView with a NetworkCall and view builders for the loading, success, and failure states. |
Defines the main view body of NetworkView, which displays different views depending on the network state.
var body: some ViewThe body displays:
- loading: When
networkStateis.loading. - content: When
networkStateis.loaded, using the provided data. - failure: When
networkStateis.failure, using the provided error.
Triggers a network request, updates the networkState to .loading, and handles success or failure.
private func loadData()Behavior:
- Sets
networkStateto.loadinginitially. - Asynchronously calls
NetworkClient.shared.requestwithnetworkCallto fetch data. - Updates
networkStateto.loaded(data)on success, or.failure(error)on failure.
struct MockNetworkView: View {
var body: some View {
let networkCall = NetworkCall(
method: .GET,
url: URL(string: "https://example.com/v1/data")
)
NetworkView(networkCall: networkCall) { data in
Text("Data loaded: \(String(describing: data))")
} loading: {
ProgressView("Loading...")
} failure: { error in
Text("Error: \(error.localizedDescription)")
}
}
}#Preview {
MockNetworkView()
}The NetworkCall struct encapsulates the configuration required to make a network request, including HTTP method, URL, headers, request body, retry settings, and timeout interval.
| Property | Type | Description |
|---|---|---|
method |
HTTPMethod |
Specifies the HTTP method for the network request, such as GET or POST. |
body |
Encodable? |
The request body to be sent with the network call, which must conform to Encodable. |
url |
URL? |
The URL to which the network request is made. |
headers |
[String: String]? |
A dictionary of HTTP headers to include in the request, where each key-value pair represents a header field. |
retry |
Bool? |
A Boolean that determines whether the request should retry upon failure. Default is false. |
timeout |
TimeInterval? |
The timeout interval for the request, measured in seconds. |
| Initializer | Description |
|---|---|
public init(method: HTTPMethod, body: Encodable? = nil, url: URL? = nil, headers: [String: String]? = nil, retry: Bool? = false, timeout: TimeInterval? = nil) |
Initializes a NetworkCall with the specified HTTP method, body, URL, headers, retry option, and timeout interval. |
let networkCall = NetworkCall(
method: .POST,
body: MyEncodableBody(data: "example"),
url: URL(string: "https://api.example.com/data"),
headers: ["Authorization": "Bearer token"],
retry: true,
timeout: 30
)This project is licensed under the MIT license.
See LICENSE for more information.