Latest 1.0.0
Homepage https://github.com/iPrysyazhnyuk/SwiftNetworker
License MIT
Platforms ios 8.0
Authors

CI Status
Version
License
Platform

SwiftNetworker simplifies and makes HTTP requests code structured using Router abstraction.
It means you write REST API requests with enum cases for better readability and code reuse.
Received HTTP response automatically parsed into Swift objects using ObjectMapper library.

Usage

Models

Assume you want to use GitHub REST API for your project to work with Users and Repositories.
Unexpectedly, you need a User model :)

import ObjectMapper

struct User: Mappable {

    var id: Int?
    var name = ""
    var avatarUrl: String?

    init(map: Map) { /* Object Mapper requires constructor */ }

    // Parsing magic happens here, "id", "name", "avatar_url" are JSON response attribute names
    mutating func mapping(map: Map) {
        id          <- map["id"]
        name        <- map["name"]
        avatarUrl   <- map["avatar_url"]
    }
}

Above User object will be parsed from JSON response automatically using SwiftNetworker.
Do you like it ? Then let’s create one more model for Repository object owned by User:

import ObjectMapper

struct Repository: Mappable {

    var id: Int?
    var name = ""
    var owner: User?

    init(map: Map) { /* Object Mapper requires constructor */ }

    mutating func mapping(map: Map) {
        id          <- map["id"]
        name        <- map["name"]
        owner       <- map["owner"]
    }
}

Yes, owner variable will be parsed into User object without any extra code.

Router

Ok, it’s time to present to you Router. You get it by implementing NetworkerRouter protocol. Here is example of router that describes GitHub API calls we want to use to:

  • get user details
  • get repositories owned by user
  • update user info

    enum GitHubRouter: NetworkerRouter {
    
    case getUserDetails(nickname: String)
    case getUserRepositories(ownerNickname: String)
    case updateUser(name: String, email: String)
    
    var baseUrl: String { return "https://api.github.com/" }
    
    var endpoint: String {
        switch self {
        case .getUserDetails(let nickname):             return "users/(nickname)"
        case .getUserRepositories(let ownerNickname):   return "users/(ownerNickname)/repos"
        case .updateUser:                               return "user/"
        }
    }
    
    var method: HTTPMethod {
        switch self {
        case .getUserDetails,
             .getUserRepositories:
            return .get
    
        case .updateUser:
            return .patch
        }
    }
    
    var params: Parameters? {
        switch self {
        case .updateUser(let name, let email):
            return ["name": name,
                    "email": email]
    
        default: return nil
        }
    }
    
    var headers: [String : String]? {
        switch self {
        case .updateUser: return ["Authorization": "token OAUTH-TOKEN"]
        default: return nil
        }
    }
    }

    Mandatory for Router are: base API url, endpoints, HTTP methods.
    Optional are: HTTP headers, encoding type.

Make HTTP requests

Now let’s use our GitHubRouter to get user details:

GitHubRouter
    .getUserDetails(nickname: "git")
    .requestMappable(onSuccess: { (user: User) in
        print("user name: (user.name)")
    }) { (error) in
        let networkerError = error.networkerError
        if let statusCode = networkerError?.statusCode {
            print("failure status code: (statusCode)")
        }
        if let json = networkerError?.info {
            print("failure json: (json)")
        }
}

Error handling

Swift Error object can be easy converted (by Error extension) to NetworkerError with additional information: statusCode, received JSON response dictionary. Error response means any request issues (e.g. missing network connection) or response with Client(4xx) or Server(5xx) error status codes.

Different options of HTTP request, response

If you want to get response HTTP status code, JSON dictionary along with parsed Object you can use another method with NetworkerMappableResult callback which can be success or failure.

  • success case gives NetworkerMappableResponse structure with: statusCode, parsed object itself, received JSON response dictionary.
  • failure case contains Swift Error object
    GitHubRouter
    .getUserDetails(nickname: "git")
    .requestMappable { (result: NetworkerMappableResult<User>) in
        switch result {
        case .success(let response):
            print("status code: (response.statusCode)")
            print("user name: (response.object.name)")
        case .failure(let error):
            if let statusCode = error.networkerError?.statusCode {
                print("failure status code: (statusCode)")
            }
        }
    }

Get array of user’s repositories:

GitHubRouter
    .getUserRepositories(ownerNickname: "git")
    .requestMappable(onSuccess: { (repositories: ArrayResponse<Repository>) in
        let reposNames = repositories.array.map { $0.name }
        print("repositories names: (reposNames)")
    }, onError: { (error) in
        print(error.localizedDescription)
    })

Update user info without response handling:

GitHubRouter
    .updateUser(name: "new name",
                email: "[email protected]")
    .request()

Upload photo or other Data? Easy, just create NetworkerFile and pass it as param to Router:

let photoFile = NetworkerFile(image: UIImage(),
                              key: "photo",
                              name: "photo.png",
                              imageFormat: .png)
Router
    .uploadPhoto(photo: photoFile)
    .request()

Using of Router is recommended but not required, the same for automatic JSON parsing – it’s optional, you can still receive JSON and parse manually:

Networker.requestJSON(url: "https://api.github.com/users/git",
                      method: .get,
                      onSuccess: { (json, statusCode) in
    print("success, json: (json)")
}) { (error) in
    print(error.localizedDescription)
}

RxSwift

There is also RxSwift extension:

GitHubRouter
    .getUserDetails(nickname: "git")
    .requestMappableRx()
    .subscribe(onNext: { (result: NetworkerMappableResult<User>) in
        switch result {
        case .success(let response):
            print("success, user name: (response.object.name), status code: (response.statusCode)")
        case .failure(let error):
            print(error.localizedDescription)
        }
    })
    .addDisposableTo(disposeBag)

Example

To run the example project, clone the repo, and run pod install from the Example directory first.

Requirements

  • iOS 8.0+
  • Swift 3.2+

Installation

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

pod 'SwiftNetworker', '~> 1.0'

If you use RxSwift:

pod 'SwiftNetworker/RxSwift', '~> 1.0'

Author

Igor Prysyazhnyuk, [email protected]

License

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

Latest podspec

{
    "name": "SwiftNetworker",
    "version": "1.0.0",
    "summary": "HTTP Networking library built on top of Alamofire and ObjectMapper to provide simple and structured way to make requests.",
    "description": "SwiftNetworker simplifies and makes HTTP requests code structured using Router abstraction.nIt means you write REST API requests with enum cases for better readability and code reuse.nReceived HTTP response automatically parsed into Swift objects using [ObjectMapper](https://github.com/Hearst-DD/ObjectMapper) library.nn## Usagenn### ModelsnnAssume you want to use GitHub REST API for your project to work with Users and Repositories.nUnexpectedly, you need a User model :)n```swiftnimport ObjectMappernnstruct User: Mappable {nnvar id: Int?nvar name = ""nvar avatarUrl: String?nninit(map: Map) { /* Object Mapper requires constructor */ }nn// Parsing magic happens here, "id", "name", "avatar_url" are JSON response attribute namesnmutating func mapping(map: Map) {nid          <- map["id"]nname        <- map["name"]navatarUrl   <- map["avatar_url"]n}n}n```nnAbove User object will be parsed from JSON response automatically using SwiftNetworker.nDo you like it ? Then let's create one more model for Repository object owned by User:nn```swiftnimport ObjectMappernnstruct Repository: Mappable {nnvar id: Int?nvar name = ""nvar owner: User?nninit(map: Map) { /* Object Mapper requires constructor */ }nnmutating func mapping(map: Map) {nid          <- map["id"]nname        <- map["name"]nowner       <- map["owner"]n}n}n```nYes, `owner` variable will be parsed into User object without any extra code.nn### RouternnOk, it's time to present to you Router that describes GitHub API calls we want to use to:n- get user detailsn- get repositories owned by usern- update user infon```swiftnenum GitHubRouter: NetworkerRouter {nncase getUserDetails(nickname: String)ncase getUserRepositories(ownerNickname: String)ncase updateUser(name: String, email: String)nnvar baseUrl: String { return "https://api.github.com/" }nnvar endpoint: String {nswitch self {ncase .getUserDetails(let nickname):             return "users/(nickname)"ncase .getUserRepositories(let ownerNickname):   return "users/(ownerNickname)/repos"ncase .updateUser:                               return "user/"n}n}nnvar method: HTTPMethod {nswitch self {ncase .getUserDetails,n.getUserRepositories:nreturn .getnncase .updateUser:nreturn .patchn}n}nnvar params: Parameters? {nswitch self {ncase .updateUser(let name, let email):nreturn ["name": name,n"email": email]nndefault: return niln}n}nnvar headers: [String : String]? {nswitch self {ncase .updateUser: return ["Authorization": "token OAUTH-TOKEN"]ndefault: return niln}n}n}n```nMandatory for Router are: base API url, endpoints, HTTP methods.nOptional are: HTTP headers, encoding type.nn### Make HTTP requestsnnNow let's use our GitHubRouter to get user details:n```swiftnGitHubRoutern.getUserDetails(nickname: "git")n.requestMappable(onSuccess: { (user: User) innprint("user name: (user.name)")n}) { (error) innlet networkerError = error.networkerErrornif let statusCode = networkerError?.statusCode {nprint("failure status code: (statusCode)")n}nif let json = networkerError?.info {nprint("failure json: (json)")n}n}n```nn### Error handlingnnSwift Error object can be easy converted (by Error extension) to `NetworkerError` with additional information: statusCode, received JSON response dictionary. Error response means any request issues (e.g. missing network connection) or response with Client(4xx) or Server(5xx) error status codes.nn### Different options of HTTP request, responsennIf you want to get response HTTP status code, JSON dictionary along with parsed Object you can use another method with `NetworkerMappableResult` callback which can be success or failure.n- success case gives `NetworkerMappableResponse` structure with: statusCode, parsed object itself, received JSON response dictionary.n- failure case contains Swift Error objectn```swiftnGitHubRoutern.getUserDetails(nickname: "git")n.requestMappable { (result: NetworkerMappableResult) innswitch result {ncase .success(let response):nprint("status code: (response.statusCode)")nprint("user name: (response.object.name)")ncase .failure(let error):nif let statusCode = error.networkerError?.statusCode {nprint("failure status code: (statusCode)")n}n}n}n```nnGet array of user's repositories:n```swiftnGitHubRoutern.getUserRepositories(ownerNickname: "git")n.requestMappable(onSuccess: { (repositories: ArrayResponse) innlet reposNames = repositories.array.map { $0.name }nprint("repositories names: (reposNames)")n}, onError: { (error) innprint(error.localizedDescription)n})n```nnUpdate user info without response handling:n```swiftnGitHubRoutern.updateUser(name: "new name",nemail: "[email protected]")n.request()n```nnUpload photo or other Data? Easy, just create `NetworkerFile` and pass it as param to Router:n```swiftnlet photoFile = NetworkerFile(image: UIImage(),nkey: "photo",nname: "photo.png",nimageFormat: .png)nRoutern.uploadPhoto(photo: photoFile)n.request()n```nnUsing of Router is recommended but not required, the same for automatic JSON parsing - it's optional, you can still receive JSON and parse manually:n```swiftnNetworker.requestJSON(url: "https://api.github.com/users/git",nmethod: .get,nonSuccess: { (json, statusCode) innprint("success, json: (json)")n}) { (error) innprint(error.localizedDescription)n}n```nn### RxSwiftnnThere is also RxSwift extension:n```swiftnGitHubRoutern.getUserDetails(nickname: "git")n.requestMappableRx()n.subscribe(onNext: { (result: NetworkerMappableResult) innswitch result {ncase .success(let response):nprint("success, user name: (response.object.name), status code: (response.statusCode)")ncase .failure(let error):nprint(error.localizedDescription)n}n})n.addDisposableTo(disposeBag)n```nn## ExamplennTo run the example project, clone the repo, and run `pod install` from the Example directory first.nn## Requirementsnn* iOS 8.0+n* Swift 3.2+nn## InstallationnnSwiftNetworker is available through [CocoaPods](http://cocoapods.org). To installnit, simply add the following line to your Podfile:nn```rubynpod 'SwiftNetworker'n```nnIf you use RxSwift:n```rubynpod 'SwiftNetworker/RxSwift'n```nn## AuthornnIgor Prysyazhnyuk, i.pr[email protected]## LicensennSwiftNetworker is available under the MIT license. See the LICENSE file for more info.",
    "homepage": "https://github.com/iPrysyazhnyuk/SwiftNetworker",
    "license": {
        "type": "MIT",
        "file": "LICENSE"
    },
    "authors": {
        "Igor Prysyazhnyuk": "[email protected]"
    },
    "source": {
        "git": "https://github.com/iPrysyazhnyuk/SwiftNetworker.git",
        "tag": "1.0.0"
    },
    "platforms": {
        "ios": "8.0"
    },
    "default_subspecs": "Core",
    "subspecs": [
        {
            "name": "Core",
            "source_files": "SwiftNetworker/Classes/SwiftNetworker/**/*",
            "dependencies": {
                "Alamofire": [
                    "~> 4.4.0"
                ],
                "ObjectMapper": [
                    "~> 2.2.7"
                ]
            }
        },
        {
            "name": "RxSwift",
            "source_files": "SwiftNetworker/Classes/SwiftNetworkerRx/**/*",
            "dependencies": {
                "SwiftNetworker/Core": [],
                "RxSwift": [
                    "~> 3.0"
                ]
            }
        }
    ]
}

Pin It on Pinterest

Share This