Fork me on GitHub

Alex Rupérez

Link: http://j.mp/2uumkru
Published: 17 Jul 16:47
intelygenz/NetClient-iOS at GitHub.
Versatile HTTP Networking in Swift
View on GitHub


View README


Twitter Version License Platform Swift Carthage compatible Swift Package Manager Compatible Build Status Help Contribute to Open Source

Net is a versatile HTTP networking library written in Swift.

🌟 Features

  • URL / JSON / Property List Parameter Encoding
  • Upload File / Data / Stream / Multipart Form Data
  • Download File using Request or Resume Data
  • Authentication with URLCredential
  • Basic, Bearer and Custom Authorization Handling
  • Default and Custom Cache Controls
  • Default and Custom Content Types
  • Upload and Download Progress Closures with Progress (only iOS >= 11)
  • cURL Command Debug Output
  • Request and Response Interceptors
  • Asynchronous and synchronous task execution
  • Inference of response object type
  • Network reachability
  • TLS Certificate and Public Key Pinning
  • Retry requests
  • Codable / Decodable / Encodable protocols compatible (JSON / Property List)
  • Customizable acceptable status codes range
  • watchOS Compatible
  • tvOS Compatible
  • macOS Compatible
  • Alamofire Implementation
  • MoyaProvider Extension
  • Kommander Extension
  • RxSwift Extension
  • Stub Implementation

📋 Requirements

  • iOS 8.0+ / macOS 10.9+ / tvOS 9.0+ / watchOS 2.0+
  • Xcode 9.0+
  • Swift 4.0+

📲 Installation

Net is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod 'NetClient'

For Swift 3 compatibility use:

pod 'NetClient', '~> 0.2'

Or you can install it with Carthage:

github "intelygenz/NetClient-iOS"

Or install it with Swift Package Manager:

dependencies: [
    .package(url: "https://github.com/intelygenz/NetClient-iOS.git")
]

🐒 Usage

Build a NetRequest

import Net

do {
    let request = try NetRequest.builder("YOUR_URL")!
                .setAccept(.json)
                .setCache(.reloadIgnoringLocalCacheData)
                .setMethod(.PATCH)
                .setTimeout(20)
                .setJSONBody(["foo", "bar"])
                .setContentType(.json)
                .setServiceType(.background)
                .setCacheControls([.maxAge(500)])
                .setURLParameters(["foo": "bar"])
                .setAcceptEncodings([.gzip, .deflate])
                .setContentEncodings([.gzip])
                .setBasicAuthorization(user: "user", password: "password")
                .setHeaders(["foo": "bar"])
                .build()
} catch {
    print("Request error: \(error)")
}

Request asynchronously

import Net

let net = NetURLSession()

net.data(URL(string: "YOUR_URL")!).async { (response, error) in
    do {
        if let object: [AnyHashable: Any] = try response?.object() {
            print("Response dictionary: \(object)")
        } else if let error = error {
            print("Net error: \(error)")
        }
    } catch {
        print("Parse error: \(error)")
    }
}

Request synchronously

import Net

let net = NetURLSession()

do {
    let object: [AnyHashable: Any] = try net.data("YOUR_URL").sync().object()
    print("Response dictionary: \(object)")
} catch {
    print("Error: \(error)")
}

Request from cache

import Net

let net = NetURLSession()

do {
    let object: [AnyHashable: Any] = try net.data("YOUR_URL").cached().object()
    print("Response dictionary: \(object)")
} catch {
    print("Error: \(error)")
}

Track progress

import Net

let net = NetURLSession()

do {
    let task = try net.data("YOUR_URL").progress({ progress in
        print(progress)
    }).sync()
} catch {
    print("Error: \(error)")
}

Add interceptors for all requests

import Net

let net = NetURLSession()

net.addRequestInterceptor { request in
    request.addHeader("foo", value: "bar")
    request.setBearerAuthorization(token: "token")
    return request
}

Retry requests

import Net

let net = NetURLSession()

net.retryClosure = { response, _, _ in response?.statusCode == XXX }

do {
    let task = try net.data("YOUR_URL").retry({ response, error, retryCount in
        return retryCount < 2
    }).sync()
} catch {
    print("Error: \(error)")
}

🧙‍♂️ Codable

Encodable

import Net

let request = NetRequest.builder("YOUR_URL")!
            .setJSONObject(Encodable())
            .build()

Decodable

import Net

let net = NetURLSession()

do {
    let object: Decodable = try net.data("YOUR_URL").sync().decode()
    print("Response object: \(object)")
} catch {
    print("Error: \(error)")
}

🤝 Integrations

Love Alamofire?

pod 'NetClient/Alamofire'
import Net

let net = NetAlamofire()

...

Love Moya?

pod 'NetClient/Moya'
import Net
import Moya

let request = NetRequest("YOUR_URL")!
let provider = MoyaProvider<NetRequest>()
provider.request(request) { result in
    switch result {
    case let .success(response):
        print("Response: \(response)")
    case let .failure(error):
        print("Error: \(error)")
    }
}

Love Kommander?

pod 'NetClient/Kommander'
import Net
import Kommander

let net = NetURLSession()
let kommander = Kommander.default

net.data(URL(string: "YOUR_URL")!).execute(by: kommander, onSuccess: { object in
    print("Response dictionary: \(object as [AnyHashable: Any])")
}) { error in
    print("Error: \(String(describing: error?.localizedDescription))")
}

net.data(URL(string: "YOUR_URL")!).executeDecoding(by: kommander, onSuccess: { object in
	print("Response object: \(object as Decodable)")
}) { error in
    print("Error: \(String(describing: error?.localizedDescription))")
}

Love RxSwift?

pod 'NetClient/RxSwift'
import Net
import RxSwift

let request = NetRequest("YOUR_URL")!
_ = net.data(request).rx.response().observeOn(MainScheduler.instance).subscribe { print($0) }

Stub Implementation

pod 'NetClient/Stub'
import Net

let net = NetStub()

net.asyncBehavior = .delayed(.main, .seconds(10)) // If you want to delay the response.

net.nextResult = .response(NetResponse.builder()....build())

// Your test request here

net.nextResult = .error(.net(code: 500, message: "Your network error.", headers: ..., object: ..., underlying: ...))

// Your test request here

❤️ Etc.

  • Contributions are very welcome.
  • Attribution is appreciated (let's spread the word!), but not mandatory.

👨‍💻 Authors

alexruperez, alejandro.ruperez@intelygenz.com

👮‍♂️ License

Net is available under the MIT license. See the LICENSE file for more info.