Skip to content

sethonyango/swift-apiclients

 
 

Repository files navigation

TingleApiClient

Swift Language

TingleApiClient is a simple class for making api calls in iOS, macOS and tvOS apps. It has specific support for parsing errors and content. This library eases working with HTTP APIs built by Tingle Software but can also work with other APIs.

Usage (Simple Client)

// Initialize
let apiClient = TingleApiClient()

// prepare request
let url = URL(string: "https://api.example.com/v2/profiles")!
var request = URLRequest(url: url)
request.httpMethod = "GET"

// make request
apiClient.send(&request) { (response: ResourceResponse<[Profile]>?, error: Error?) in

    // first check for a network error (such as no internet)
    if (error != nil) {
        // handle error here
        return
    }
    
    // if the error is nil the response should not be nil
    // but lets just check for the sake of checking
    if (response == nil) {
        // should not happen
        return
    }
    
    // check if the response was successful
    if (response!.successful && response!.resource != nil) {
        let profiles = response!.resource!
        if (!profiles.isEmpty) {
            // save the entries in the database or elsewhere
            // this is called in the background you should not access the UI thread directly without a dispatcher
        }
    }
}

Usage (Derived Client)

import Foundation
import TingleApiClient

public class ProfilesApiClient: TingleApiClient {
    private let baseUrl = "https://api.example.com"
    
    override public func setupJsonSerialization(encoder: JSONEncoder, decoder: JSONDecoder) {
        encoder.dateEncodingStrategy = .iso8601
        decoder.dateDecodingStrategy = .iso8601
    }
    
    override public func buildMiddleware() -> [TingleApiClientMiddleware] {
        [
            AppDetailsMiddleware(Bundle.main.bundleIdentifier ?? "", Bundle.main.shortBundleVersion, Bundle.main.shortBundleVersion),
            LoggingMiddleware(.BODY, .info)
        ]
    }
    
    @discardableResult
    public func getProfiles(_ completionHandler: @escaping (ResourceResponse<[Profile]>?, error: Error?) -> Void) -> URLSessionTask {
        let url = URL(string: "\(baseUrl)/v2/profiles")!
        var request = URLRequest(url: url)
        request.httpMethod = "GET"
        return send(&request, completionHandler)
    }
}
import Foundation
import RealmSwift
import TingleApiClient

public class DownloadManager {
    private static let client = ProfilesApiClient()
    
    @discardableResult
    public static func downloadProfiles() -> URLSessionTask {
        return client.getProfiles { (response: ResourceResponse<[Profile]>) in
            if (response.successful && response.resource != nil) {
                let profiles = response.resource!
                if (!profiles.isEmpty) {
                    if let realm = try? Realm() {
                        try? realm.write {
                            realm.add(profiles, update: .all)
                        }
                    }
                }
            }
        }
    }
}

See the samples project to see advanced usage

Installation

Swift Package Manager

TingleApiClient is available on SPM. Just add the following to your Package file:

import PackageDescription

let package = Package(
    dependencies: [
        .package(url: "https://github.com/tinglesoftware/swift-apiclients.git", from: 0.2.0)
    ]
)

Manual Installation

Just drag the Sources/*.swift files into your project.

TingleApiClient properties

encoder

The instance of JsonEncoder to use in creating JSON payloads from objects

decoder

The instance of JSONDecoder to use in creating objects from JSON payloads

TingleApiClient methods

init(session: URLSession? = nil, authenticationProvider: IAuthenticationProvider? = nil)
init(_ authenticationProvider: IAuthenticationProvider)

These methods create a new TingleApiClient instance that uses the session and authentication provider passed.

func buildMiddleware() -> [TingleApiClientMiddleware]

Builds the middleware that is used to process requests and responses. There are different reasons why you might want to use middleware, such as logging, setting extra headers etc. The IAuthenticationProvider is itself middleware dedicated towards authenticating the request before going out.

func func setupJsonSerialization(encoder: JSONEncoder, decoder: JSONDecoder)

Setups the instances of JSONEncoder and JSONDecoder already created. These instances are used to encode/decode requests/responses respectively in the send functions

func sendRequest<TResource, TResourceResponse>(_ request: inout URLRequest,
                                               _ resultBuilder: @escaping (Int, Any, TResource?, HttpApiResponseProblem?) -> TResourceResponse,
                                               _ completionHandler: @escaping (TResourceResponse?, Error?) -> Void) -> URLSessionTask

This method sends a HTTP request as per the details in the request parameter. The response is parsed to produce a TResource and HttpApiResponseProblem. These two are supplied to the resultBuilder closure to produce a TResourceResponse. When the network call fails such as there being no internet access or being unable to reach the server, the resultBuilder closure is not called. Instead, the completionHandler closure is called with the TResourceResponse? argument set to nil and the Error? argument not nil. When the network call succeeds, the resultBuilder closure is called to produce an instance of TResourceResponse and the result is passed to the completionHandler closure but the Error? parameter is set to nil.

func sendRequest<TResource>(_ request: inout URLRequest,
                            _ completionHandler: @escaping (AnyResourceResponse<TResource>?, Error?) -> Void) -> URLSessionTask

This is similar to calling the sendRequest method above but instead produces a AnyResourceResponse<TResource, TProblem> for the TResourceResponse

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Swift 100.0%