EZNetworking

1.5.5

gomez1112/EZNetworking

What's New

v1.5.5

2024-11-03T11:08:27Z

Full Changelog: 1.5.4...1.5.5

EZNetworking

EZNetworking is a Swift package designed to simplify network requests and API interactions in your iOS and macOS applications. It provides a clean and easy-to-use abstraction over URLSession for handling HTTP requests, response decoding, and error handling.

Features

  • Protocol-Oriented Design: Leverage protocols like APIRequest and HTTPDownloader to create customizable network requests and responses.
  • Default Implementations: Simplify your network code with default headers, body data, and HTTP method handling.
  • Customizable JSON Decoding: Inject your own JSONDecoder to handle various decoding strategies.
  • Error Handling: Comprehensive error handling with detailed localized error descriptions.
  • Extensible Request Building: Create and modify API requests with flexible query items and HTTP methods.
  • Actor-Based Networking: Utilize Swift's actor model to safely manage concurrent network requests.

Installation

Swift Package Manager

To integrate EZNetworking into your project using Swift Package Manager, add the following dependency in your Package.swift file:

dependencies: [
    .package(url: "https://github.com/yourusername/EZNetworking.git", from: "1.5.1")
]

Usage

Creating a Client

The Client actor is the primary component for making network requests. You can customize it with your own HTTPDownloader and JSONDecoder if needed.

import EZNetworking

let client = Client()

Or with custom configurations

let customDecoder = JSONDecoder()
customDecoder.dateDecodingStrategy = .iso8601

let client = Client(decoder: customDecoder)

Making a Request

Create a request using GenericAPIRequest:

let url = "https://randomuser.me"
let path = "/api/"
let request = GenericAPIRequest<User>(baseURL: url, path: path)

Fetching Data

Use the Client to fetch data from the API:

Task {
    do {
        let user = try await client.fetchData(from: request)
        print(user.results.first?.name.first ?? "No name")
    } catch {
        print("Failed to fetch data: \(error.localizedDescription)")
    }
}

Using an API Key

If your API requires an API key, you can include it in the headers of your request:

let url = "https://api.example.com"
let path = "/data"
let headers = ["Authorization": "Bearer YOUR_API_KEY"]

let request = GenericAPIRequest<MyDataModel>(
    baseURL: url,
    path: path,
    headers: headers
)

Using Query Items

If you need to include query parameters in your API request, you can use the queryItems property:

let url = "https://api.example.com"
let path = "/search"
let queryItems = [
    URLQueryItem(name: "query", value: "Swift"),
    URLQueryItem(name: "limit", value: "10")
]

let request = GenericAPIRequest<MySearchResults>(
    baseURL: url,
    path: path,
    queryItems: queryItems
)

Error Handling

EZNetworking provides detailed error handling through the APIError enum:

enum APIError: Error, LocalizedError {
    case invalidURL
    case httpStatusCodeFailed(statusCode: Int, description: String)
    case decodingError(underlyingError: Error)
    case networkError
    case unknownError
    
    var errorDescription: String? {
        switch self {
        case .invalidURL:
            return "The URL provided was invalid."
        case .httpStatusCodeFailed(let statusCode, let description):
            return "HTTP request failed with status code \(statusCode): \(description)."
        case .decodingError(let underlyingError):
            return "Failed to decode the response: \(underlyingError)."
        case .networkError:
            return "There was a network error."
        case .unknownError:
            return "An unknown error has occurred."
        }
    }
}

Testing

EZNetworking includes a simple testing setup to mock network responses:

import Testing
@testable import EZNetworking

final class Downloader: HTTPDownloader {
    func httpData(from url: URL) async throws -> Data {
        try await Task.sleep(nanoseconds: UInt64.random(in: 100_000_000...500_000_000))
        return testUser
    }
    
    @Test
    func testClientDoesFetchUserData() async throws {
        let downloader = Downloader()
        let client = Client(downloader: downloader)
        let request = GenericAPIRequest<User>(baseURL: "https://randomuser.me", path: "/api/")
        let user = try await client.fetchData(from: request)
        #expect(user.results.count == 1)
    }
}

Static Badge Static Badge

Contributing

Contributions are welcome! Please feel free to submit a pull request or open an issue to help improve EZNetworking.

Description

  • Swift Tools 6.0.0
View More Packages from this Author

Dependencies

  • None
Last updated: Wed May 14 2025 11:41:56 GMT-0900 (Hawaii-Aleutian Daylight Time)