🌸 Powerful Codable API requests builder and manager for iOS.

Related tags

Networking CodyFire
Overview

Mihael Isaev

MIT License Swift 4.2 Swift.Stream


This lib is about network requests with blackjack, roulette and craps!

Using it you will be able to convert your massive API layer code into an awesome convenient controllers with easy and maintainable network requests!

Use Codable models for everything related to API requests:

  • json payload
  • url-encoded payload
  • multipart payload
  • plain and json response
  • url query
  • headers

Wondered? That's only little part of what you will get from this lib! 🍻

Quick examples

How to send GET request

APIRequest<ResponseModel>("endpoint").onSuccess { model in
    //here's your decoded model!
    //no need to check http.statusCode, I already did it for you! By default it's 200 OK
    //of course you can choose which statusCode is equal to success (look at the `POST` and `DELETE` examples below)
}

How to send POST request

APIRequest<ResponseModel>("endpoint", payload: payloadModel)
    .method(.post)
    .desiredStatusCode(.created) //201 CREATED
    .onSuccess { model in
    //here's your decoded model!
    //success was determined by comparing desiredStatusCode with http.statusCode
}

How to send DELETE request

APIRequest<Nothing>("endpoint")
    .method(.delete)
    .desiredStatusCode(.noContent) //204 NO CONTENT
    .onSuccess { _ in
    //here's empty successful response!
    //success was determined by comparing desiredStatusCode with http.statusCode
}

How to send several requests?

You're able to run up to 10 requests one-by-one!

API.employee.all()
    .and(API.office.all())
    .and(API.car.all())
    .and(API.event.all())
    .and(API.post.all())
    .onError { error in
        print(error.description)
    }.onSuccess { employees, offices, cars, events, posts in
   // do what you want with received results!!! 🍻
}

Or you can run unlimited amount of requests one-by-one or at the same time, if you need just a completion handler.

[API.employee.all(), API.office.all(), API.car.all()].flatten().onError {
    print(error.description)
}.onSuccess {
    print("flatten finished!")
}

to run them concurrently just add .concurrent(by: 3) to run by 3 at the same time

Of course you'll be able to send PUT and PATCH requests, send multipart codable structs with upload progress callback, catch errors, even redefine error descriptions for every endpoint. Wondered? πŸ˜ƒ Let's read the whole readme below! 🍻

How to install

CodyFire is available through CocoaPods and SPM.

To install it, simply add the following line in your Podfile:

pod 'CodyFire', '~> 1.15.4'

Or you're looking for reactive code support? I have it! 🍺

pod 'RxCodyFire', '~> 1.1.0'
# no need to install `CodyFire` cause it's in dependencies

using this pod you should always import just RxCodyFire and every APIRequest will have .observable

pod 'ReactiveCodyFire', '~> 1.1.0'
# no need to install `CodyFire` cause it's in dependencies

using this pod you should always import just ReactiveCodyFire and every APIRequest will have .signalProducer

How to setup

CodyFire automatically detects which environment you're on, so I suggest you to definitely use this awesome feature πŸ‘

import CodyFire

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        let dev = CodyFireEnvironment(baseURL: "http://localhost:8080")
        let testFlight = CodyFireEnvironment(baseURL: "https://stage.myapi.com")
        let appStore = CodyFireEnvironment(baseURL: "https://api.myapi.com")
        CodyFire.shared.configureEnvironments(dev: dev, testFlight: testFlight, appStore: appStore)
        //Also if you want to be able to switch environments manually just uncomment the line below (read more about that)
        //CodyFire.shared.setupEnvByProjectScheme()
        return true
    }
}

Isn't it cool? 😏

Or you can set different Server URL for every APIRequest

let server1 = ServerURL(base: "https://server1.com", path: "v1")
let server2 = ServerURL(base: "https://server2.com", path: "v1")
let server3 = ServerURL(base: "https://server3.com")

And then initialize your APIRequests like this πŸ”₯

APIRequest(server1, "endpoint", payload: payloadObject)
APIRequest(server2, "endpoint", payload: payloadObject)
APIRequest(server3, "endpoint", payload: payloadObject)

Or in some cases you even can do it like this 😏

APIRequest("endpoint", payload: payloadObject).serverURL(server1)

Create your API controllers

I promise that this is API code architecture from your dreams which are come true!

Create an API folder and API.swift file inside it

class API {
    typealias auth = AuthController
    typealias task = TaskController
}

Create a folder named Controllers inside API folder, and create a folder for each controller

API/Controllers/Auth/Auth.swift

class AuthController {}

API/Controllers/Task/Task.swift

class TaskController {}

Create an extension file for each controller's endpoint

Auth login as simple POST request

API/Controllers/Auth/Auth+Login.swift

import CodyFire
extension AuthController {
  struct LoginRequest: JSONPayload {
        let email, password: String
        init (email: String, password: String) {
            self.email = email
            self.password = password
        }
    }

    struct LoginResponse: Codable {
        var token: String
    }

    static func login(_ request: LoginRequest) -> APIRequest<LoginResponse> {
        return APIRequest("login", payload: request).method(.post).addCustomError(.notFound, "User not found")
    }
}
Auth login for Basic auth

API/Controllers/Auth/Auth+Login.swift

import CodyFire
extension AuthController {
    struct LoginResponse: Codable {
        var token: String
    }

    static func login(email: String, password: String) -> APIRequest<LoginResponse> {
        return APIRequest("login").method(.post).basicAuth(email: email, password: password)
            .addCustomError(.notFound, "User not found")
    }
}
Task REST endpoints
Get task by id or a list of tasks by offset and limit

API/Controllers/Task/Task+Get.swift

import CodyFire
extension TaskController {
    struct Task: Codable {
        var id: UUID
        var name: String
    }

    struct ListQuery: Codable {
        var offset, limit: Int
        init (offset: Int, limit: Int) {
            self.offset = offset
            self.limit = limit
        }
    }

    static func get(_ query: ListQuery? = nil) -> APIRequest<[Task]> {
        return APIRequest("task").query(query)
    }

    static func get(id: UUID) -> APIRequest<Task> {
        return APIRequest("task/" + id.uuidString)
    }
}
Create a task

API/Controllers/Task/Task+Create.swift

import CodyFire
extension TaskController {
    struct CreateRequest: JSONPayload {
        var name: String
        init (name: String) {
            self.name = name
        }
    }

    static func create(_ request: CreateRequest) -> APIRequest<Task> {
        return APIRequest("post", payload: request).method(.post).desiredStatusCode(.created)
    }
}
Edit a task

API/Controllers/Task/Task+Edit.swift

import CodyFire
extension TaskController {
    struct EditRequest: JSONPayload {
        var name: String
        init (name: String) {
            self.name = name
        }
    }

    static func create(id: UUID, request: EditRequest) -> APIRequest<Task> {
        return APIRequest("post/" + id.uuidString, payload: request).method(.patch)
    }
}
Delete a task

API/Controllers/Task/Task+Delete.swift

import CodyFire
extension TaskController {
    static func delete(id: UUID) -> APIRequest<Nothing> {
        return APIRequest("post/" + id.uuidString).method(.delete).desiredStatusCode(.noContent)
    }
}

Easily use your API endpoints!

Send login request
API.auth.login(email: "[email protected]", password: "qwerty").onError { error in
    switch error.code {
    case .notFound: print("User not found")
    default: print(error.description)
    }
}.onSuccess { token in
    print("Received auth token: "+ token)
}
Get a list of tasks
API.task.get().onError { error in
    print(error.description)
}.onSuccess { tasks in
    print("received \(tasks.count) tasks")
}
Create a task
API.task.create(TaskController.CreateRequest(name: "Install CodyFire")).onError { error in
    print(error.description)
}.onSuccess { task in
    print("just created new task: \(task)")
}
Delete a task
let taskId = UUID()
API.task.delete(id: taskId).onError { error in
    print(error.description)
}.onSuccess { _ in
    print("just removed task with id: \(taskId)")
}

Multipart example

//declare a PostController
class PostController()
extension PostController {
    struct CreateRequest: MultipartPayload {
        var text: String
        var tags: [String]
        var images: [Attachment]
        var video: Data
        init (text: String, tags: [String], images: [Attachment], video: Data) {
            self.text = text
            self.tags = tags
            self.images = images
            self.video = video
        }
    }

    struct PostResponse: Codable {
        let id: UUID
        let text: String
        let tags: [String]
        let linksToImages: [String]
        let linkToVideo: String
    }

    static func create(_ request: CreateRequest) -> APIRequest<PostResponse> {
        return APIRequest("post", payload: request).method(.post)
    }
}

//then somewhere send creation request!

let videoData = FileManager.default.contents(atPath: "/path/to/video.mp4")!
let imageAttachment = Attachment(data: UIImage(named: "cat")!.jpeg(.high)!,
                                 fileName: "cat.jpg",
                                 mimeType: .jpg)
let payload = PostController.CreateRequest(text: "CodyFire is awesome",
                                           tags: ["codyfire", "awesome"],
                                           images: [imageAttachment],
                                           video: videoData)
API.post.create(payload).onProgress { progress in
    print("tracking post uploading progress: \(progress)")
}.onError { error in
    print(error.description)
}.onSuccess { createdPost in
    print("just created post: \(createdPost)")
}

Easy right? πŸŽ‰

Details

How to put Authorization Bearer token into every request?

For that we have a global headers wrapper, which is called for every request.

You need to declare it e.g. somewhere in AppDelegate.

There are two options

  1. Use Codable model for headers (recommended)
CodyFire.shared.fillCodableHeaders = {
    struct Headers: Codable {
        var Authorization: String? //NOTE: nil values will be excluded
        var anythingElse: String
    }
    return Headers(Authorization: nil, anythingElse: "hello")
}
  1. Use [String: String] dictionary
CodyFire.shared.fillHeaders = {
    guard let apiToken = LocalAuthStorage.savedToken else { return [:] }
    return ["Authorization": "Bearer \(apiToken)"]
}

How to set a global unauthorized handler?

Again, somewhere in AppDelegate declare it like this CodyFire.shared.unauthorizedHandler = { //kick out user }

Handle if network isn't available (e.g. wifi/lte turned off)

.onNetworkUnavailable {
    print("unfortunately there're no internet connection!")
}

Run something right before request started (works only if network is available)

.onRequestStarted {
    print("request started normally")
}

How to avoid log error for request

.avoidLogError()

How to set desired status code and what's that means?

Usually servers response with 200 OK and CodyFire expect to receive 200 OK to call onSuccess handler by default.

You may need to specify another code, e.g. 201 CREATED for some POST requests.

.desiredStatusCode(.created)

or you even can set your custom code

.desiredStatusCode(.custom(777))

How to set some headers for a request?

.headers(["myHeader":"myValue"])
//or for basic auth
.basicAuth(email: "", password: "")

Supported HTTP methods

You may use: GET, POST, PUT, PATCH, DELETE, HEAD, TRACE, CONNECT, OPTIONS

How to switch environments through Xcode's run schemes?

It's really useful feature and I suggest to use it in every iOS project!

Create three schemes named: Development, TestFlight, AppStore like on the screenshot below 2018-10-24 5 30 30

TIP: Make sure that they're marked as Shared to have them in git

Then in every scheme in Arguments tab add Environment variable named env with one of those values: dev, testFlight, appStore.

Take a look at example below 2018-10-24 5 34 43

Then somewhere in AppDelegate.didFinishLaunchingWithOptions add

CodyFire.shared.setupEnvByProjectScheme()

All done, now you're able to easily switch environments!

How to execute request without onSuccess clojure?

Sometimes useful for DELETE or PATCH requests

APIRequest<Nothing>("endpoint").method(.delete).execute()

How to cancel request?

let request = APIRequest("").execute()
request.cancel()

and you're able to handle cancellation

.onCancellation {
    print("request was cancelled :(")
}

What does custom error means?

You may define your own custom errors, globally or for each request. onError block contains NetworkError object with StatusCode enum, an error description, and a raw response Data. Error description you could change to whatever you want for any error code. By default there are already defined some good descriptions for common errors.

Let's take a look how we can use powerful onError block

.onError { error in
    switch error.code {
    case .notFound: print("It's not found :(")
    case .internalServerError: print("Oooops... Something really went wrong...")
    case .custom(let code): print("My non-standard-custom error happened: " + error.description)
    case .unknown(let code): print("Totally unknown error happened: " + error.description)
    default:
        print("Another error happened: " + error.description)
        if let raw = error.raw, let rawResponse = String(data: raw, encoding: .utf8) {
            print("Raw response: " + rawResponse)
        }
    }
}

More than that!!! In your controller while declaring APIRequest you're able to add your own custom errors!!! πŸ™€

APIRequest("login")
    .method(.post)
    .basicAuth(email: "[email protected]", password: "qwerty")
    .addError(.notFound, "User not found")

I believe that's really awesome and useful! Finally a lot of things may be declared in one place! πŸŽ‰

How to set response timeout?

.responseTimeout(30) //request timeout set for 30 seconds

and of course you're able to catch timeout

.onTimeout {
    //timeout happened :(
}

How to add interactive additional timeout? (my favourite one πŸ˜„ )

If you want to make sure that your request will take 2 or more seconds (to not be too fast πŸ˜… ) you can do that

.additionalTimeout(2)

e.g. in case if your request will be executed in 0.5 seconds, onSuccess handler will be fired only in 1.5s after that but in case if your request will take more than 2s then onSuccess handler will be fired immediatelly

How to declare payload model for multipart request

Your struct/class just should conform to MultipartPayload protocol

struct SomePayload: MultipartPayload {
    let name: String
    let names: [String]
    let date: Date
    let dates: [Dates]
    let number: Double
    let numbers: [Int]
    let attachment: Data
    let attachments: [Data]
    let fileAttachment: Attachment
    let fileAttachments: [Attachment]
}

Supported payload types

You may conform your struct/class to: FormURLEncodedPayload, MultipartPayload, and JSONPayload

How to declare payload model for json request

Your struct/class just should conform to JSONPayload protocol

struct SomePayload: JSONPayload {
    let name: String
    let names: [String]
    let date: Date
    let dates: [Dates]
    let number: Double
    let numbers: [Int]
}

How to declare payload model for x-www-form-urlencoded request

Your struct/class just should conform to FormURLEncodedPayload protocol

struct SomePayload: FormURLEncodedPayload {
    let name: String
    let names: [String]
    let date: Date
    let dates: [Dates]
    let number: Double
    let numbers: [Int]
}

How to declare url query params model

Your struct/class just should conform to Codable protocol

struct SomePayload: Codable {
    let name: String
    let names: [String]
    let date: Date
    let dates: [Dates]
    let number: Double
    let numbers: [Int]
}

How to set date decoding/encoding strategy

Our DateCodingStrategy support

  • secondsSince1970
  • millisecondsSince1970
  • formatted(customDateFormatter: DateFormatter) By default all the dates are in yyyy-MM-dd'T'HH:mm:ss'Z' format

You have interesting options here:

  • you can set global date decoder/encoder
CodyFire.shared.dateEncodingStrategy = .secondsSince1970
let customDateFormatter = DateFormatter()
CodyFire.shared.dateDecodingStrategy = .formatted(customDateFormatter)
  • you can set date decoder/encoder for request in your controller
APIRequest().dateDecodingStrategy(.millisecondsSince1970).dateEncodingStrategy(.secondsSince1970)
  • or you even can use different date encoder/decoder for each payload type (highest priority)
struct SomePayload: JSONPayload, CustomDateEncodingStrategy, CustomDateDecodingStrategy {
   var dateEncodingStrategy: DateCodingStrategy
   var dateDecodingStrategy: DateCodingStrategy
}

How to enable/disable logging

e.g. in AppDelegate you may set logging mode

CodyFire.shared.logLevel = .debug
CodyFire.shared.logLevel = .error
CodyFire.shared.logLevel = .info
CodyFire.shared.logLevel = .off

and also you can set log handler

CodyFire.shared.logHandler = { level, text in
    print("manually printing codyfire error: " + text)
}

by default for the AppStore the log level if .off

How you're detecting current environment?

It's easy

#if DEBUG
    //DEV environment
#else
    if Bundle.main.appStoreReceiptURL?.lastPathComponent == "sandboxReceipt" {
        //TESTFLIGHT environment
    } else {
        //APPSTORE environment
    }
#endif

Chained requests

Run up to 10 requests one-by-one!

API.employee.all()
    .and(API.office.all())
    .and(API.car.all())
    .and(API.event.all())
    .and(API.post.all())
    .onError { error in
        print(error.description)
    }.onSuccess { employees, offices, cars, events, posts in
   // do what you want with received results!!! 🍻
}

onRequestStarted, onNetworkUnavailable, onCancellation, onNotAuthorized, onTimeout also available! //TBD: onProgress

I believe it is awesome! Especially for whom who not familiar or don't like reactive programming πŸ™‚

Flatten

If you want to run several requests one-by-one or at the same time but with just completion handler you can do that with .flatten()

[API.employee.all(), API.office.all(), API.car.all()].flatten().onError {
    print(error.description)
}.onSuccess {
    print("flatten finished!")
}

to run them concurrently just add .concurrent(by: 3) to run by 3 at the same time to skip errors also add .avoidCancelOnError() to get progress add .onProgress

Contribution

Please feel free to send pull requests and ask your questions in issues

Hope this lib will be really useful in your projects! Tell you friends about it! Please press STAR ⭐️ button!!!

Author

Mike Isaev, [email protected]

Comments
  • Sending a MultipartPayload always does a POST

    Sending a MultipartPayload always does a POST

    It's currently not possible to send a MultipartPayload request via PUT or PATCH, it always overrides it to a POST request. Is this expected, or a bug?

    opened by kevinrenskers 5
  • Unable to find a specification for `CodyFire`

    Unable to find a specification for `CodyFire`

    pod 'CodyFire'

    Hello, I try pod install, but it still: [!] Unable to find a specification for CodyFire

    pod search CodyFire [!] Unable to find a pod with name, author, summary, or description matching CodyFire

    Does it means still indexing?

    opened by SergeyDevUA 1
  • Is it possible to cancel all requests?

    Is it possible to cancel all requests?

    This would be extremely handy inside of the unauthorizedHandler for example, so that all other requests can be cancelled. Sadly I can't seem to access the queue or any other way to cancel all requests, only individual ones?

    opened by kevinrenskers 0
  • Customize the decoder with a keyDecodingStrategy

    Customize the decoder with a keyDecodingStrategy

    I'd like to be able to set the keyDecodingStrategy of the default JSONDecoder to .convertFromSnakeCase, but that doesn't seem possible at the moment?

    So instead I now have to give the CodingKeys by hand.

    struct Upload: Codable {
      let id: Int
      let user: User
      let mediaType: String
      let image: String
      let thumbnail: String
      let description: String
    
      enum CodingKeys: String, CodingKey {
        case id
        case user
        case mediaType = "media_type"
        case image
        case thumbnail
        case description
      }
    }
    

    This is a little bit annoying considering all of that could be automated away with setting the keyDecodingStrategy :)

    This could be done the same way that the date encoding strategy can already be customized.

    enhancement 
    opened by kevinrenskers 0
  • Custom error parsing

    Custom error parsing

    My API behaves so that when the user tries to login and it fails, the error is given as a JSON body in the response like this:

    {"non_field_errors":["Unable to log in with provided credentials."]}

    Sadly all that I get back from CodyFire is "Something went wrong..." from here, since the error response doesn't contain a message property and it's not an array.

    Would it be possible to simply give the entire JSON response back to the error? Or that I can override the error handling logic on a per-request basis?

    enhancement 
    opened by kevinrenskers 3
  • How do you add a global error handler?

    How do you add a global error handler?

    Let's say I want to catch API errors in one place, where I can do something with it, like log it somewhere, show it to the user, etc. I noticed that there is CodyFire.shared.successResponseHandler but nothing like it for errors?

    enhancement 
    opened by kevinrenskers 1
Releases(1.11.1)
  • 1.11.1(Jun 19, 2019)

  • 1.11.0(Jun 13, 2019)

    • switched to Swift version of Reachability
    • implemented SPM support
    • desiredStatusCode deprecated (but still works), use successStatusCode instead
    • custom errors improvements

    Now you could set more than one successStatusCode as well as set more than one statusCode for custom errors.

    Source code(tar.gz)
    Source code(zip)
  • 1.8.0(Nov 7, 2018)

    Use DictionaryEncoder for headers, so now you could define your custom coding keys e.g. like this

    struct Headers: Codable {
            var platform: String?
            var sdk: String?
            var version: String?
            var id: String?
            
            enum CodingKeys: String, CodingKey {
                case platform = "X-Mobile-Platform"
                case sdk = "X-Mobile-SDK"
                case version = "X-Mobile-A"
                case id = "X-Mobile-ID"
            }
        }
    

    Use DictionaryEncoder for multipart Implement FormURLEncodedPayload protocol and sendFormURLEncoded method Conform PayloadProtocol to just Encodable Conform ResultType to just Decodable Rename buildQuery(_) into buildURLEncodedString(from:) Improve error messages printing, now use Logger instead of just printing Update Example project to demonstrate custom coding keys for headers Update readme, add info

    Source code(tar.gz)
    Source code(zip)
  • 1.7.3(Nov 5, 2018)

    So now you're also able to parse error response data if needed

    .onError { error in
        switch error.code {
        case .notFound: print("It's not found :(")
        default:
            print("Another error happened: " + error.description)
            if let raw = error.raw, let rawResponse = String(data: raw, encoding: .utf8) {
                print("Raw response: " + rawResponse)
            }
        }
    }
    
    Source code(tar.gz)
    Source code(zip)
  • 1.7.0(Nov 5, 2018)

    Now you can set custom server url for each request πŸ™€

    let server1 = ServerURL(base: "https://server1.com", path: "v1")
    let server2 = ServerURL(base: "https://server2.com", path: "v1")
    let server3 = ServerURL(base: "https://server3.com")
    

    APIRequests with custom server url will look like this πŸ”₯

    APIRequest(server1, "endpoint", payload: payloadObject)
    APIRequest(server2, "endpoint", payload: payloadObject)
    APIRequest(server3, "endpoint", payload: payloadObject)
    

    And in some cases you even can do it like this 😏

    APIRequest("endpoint", payload: payloadObject).serverURL(server1)
    
    Source code(tar.gz)
    Source code(zip)
  • 1.6.0(Oct 29, 2018)

    Chained requests

    Now you're able to run up to 10 requests one-by-one!

    API.employee.all()
        .and(API.office.all())
        .and(API.car.all())
        .and(API.event.all())
        .and(API.post.all())
        .onError { error in
            print(error.description)
        }.onSuccess { employees, offices, cars, events, posts in
       // do what you want with received results!!! 🍻
    }
    

    onRequestStarted, onNetworkUnavailable, onCancellation, onNotAuthorized, onTimeout also available! //TBD: onProgress

    It is awesome! Especially for whom who not familiar or don't like reactive programming πŸ™‚

    Flatten

    And if you want to run several requests one-by-one or concurrently but with just completion handler you also can do that with .flatten()

    [API.employee.all(), API.office.all(), API.car.all()].flatten().onError {
        print(error.description)
    }.onSuccess {
        print("flatten finished!")
    }
    

    to run them concurrently just add .concurrent(by: 3) to run by 3 at the same time to skip errors also add .avoidCancelOnError() to get progress add .onProgress

    Hope it's cool! 😎 Please let me know in issues if you need any improvements or bug fixes.

    Source code(tar.gz)
    Source code(zip)
  • 1.5.0(Oct 29, 2018)

    Removed Int error handlers. Use NetworkError everywhere instead. HTTPStatusCode is deprecated, renamed to StatusCode instead KnownNetworkError is deprecated, renamed to NetworkError onKnownError is deprecated, use just OnError CodyFire.shared.knownErrors now has internal protection, use setters instead

    Source code(tar.gz)
    Source code(zip)
  • 1.4.1(Oct 26, 2018)

  • 1.4.0(Oct 26, 2018)

    Now it's less wordy πŸ™‚

    What changed:

    • APIRequestWithoutPayload<T> replaced with just APIRequest<T>
    • APIRequestWithoutAnything replaced with APIRequestWithoutResult
    Source code(tar.gz)
    Source code(zip)
  • 1.3.0(Oct 26, 2018)

Owner
CodyFire
Awesome networking library for multiple platforms
CodyFire
A frida tool that capture GET/POST HTTP requests of iOS Swift library 'Alamofire' and disable SSL Pinning.

FridaHookSwiftAlamofire A frida tool that capture GET/POST HTTP requests of iOS Swift library 'Alamofire' and disable SSL Pinning. δΈ­ζ–‡ζ–‡ζ‘£εŠθΏ‡η¨‹ Features Ca

neilwu 69 Dec 16, 2022
Easy to use CFNetwork wrapper for HTTP requests, Objective-C, Mac OS X and iPhone

ASIHTTPRequest is an easy to use wrapper around the CFNetwork API that makes some of the more tedious aspects of communicating with web servers easier

Ben Copsey 5.8k Dec 14, 2022
Synchronous requests for AFNetworking 1.x, 2.x, and 3.x

AFNetworking-Synchronous A minimal category which extends AFNetworking to support synchronous requests. Usage 3.x pod 'AFNetworking', '~> 3.0' pod

Paul Melnikow 160 Dec 7, 2022
Easy and lightweight network layer for creating different set of network requests like GET, POST, PUT, DELETE customizable with coders conforming to TopLevelDecoder, TopLevelEncoder

Easy and lightweight network layer for creating different set of network requests like GET, POST, PUT, DELETE customizable with coders conforming to TopLevelDecoder, TopLevelEncoder

Igor 2 Sep 16, 2022
NSURLSession network abstraction layer, using Codable and Decodable for response and Encodable for request. βš™οΈπŸš€

SONetworking NSURLSession network abstraction layer, using Codable and Decodable for response and Encodable for request. Project Folder and File Struc

Ahmad AlSofi 4 Jan 28, 2022
Thin wrapper around NSURLSession in swift. Simplifies HTTP requests.

SwiftHTTP SwiftHTTP is a thin wrapper around NSURLSession in Swift to simplify HTTP requests. Features Convenient Closure APIs Simple Queue Support Pa

Dalton 1.9k Dec 7, 2022
a NSURLCache subclass for handling all web requests that use NSURLRequest

EVURLCache What is this? This is a NSURLCache subclass for handeling all web requests that use NSURLRequest. (This includes UIWebView) The EVURLCache

Edwin Vermeer 296 Dec 18, 2022
Request adapter for URL requests from "MovieLister" demo app (Swift for Good book, a chapter by Ben Scheirman)

RequestAdapter Request adapter for URL requests from "MovieLister" demo app (Swift for Good book, a chapter by Ben Scheirman) The code is taken from:

Mihaela Mihaljevic Jakic 0 Nov 22, 2021
CoreNetwork module with the basic functionality of requests to the network

CoreNetwork module with the basic functionality of requests to the network

Moscow Metro 4 Apr 27, 2022
Menet is a TCP network middleware that can be dynamically modified through HTTP requests.

Menet Menet is a TCP network middleware that can be dynamically modified through HTTP requests. This is an experimental project, do NOT use it in prod

Nik 2 May 19, 2022
VFNetwork is a protocol-oriented network layer that will help you assemble your requests in just a few steps.

Simple, Fast and Easy. Introduction VFNetwork is a protocol-oriented network layer that will help you assemble your requests in just a few steps. How

Victor Freitas 4 Aug 22, 2022
A Codable extension to decode arrays and to catch & log all decoding failures

SafeDecoder A Codable extension to decode arrays and to catch & log all decoding failures Features SafeDecoder makes two improvements for Codable mode

Idle Hands Apps 5 May 29, 2022
Setup your class structure in Xcode Interface Builder and save() in Parse Server.

ISParseBind With ISParseBind you can save, update and query PFObjects using the power of Xcode Interface Builder resources. https://www.youtube.com/wa

Weni 10 Mar 28, 2022
Socket framework for Swift using the Swift Package Manager. Works on iOS, macOS, and Linux.

BlueSocket Socket framework for Swift using the Swift Package Manager. Works on iOS, macOS, and Linux. Prerequisites Swift Swift Open Source swift-5.1

Kitura 1.3k Dec 26, 2022
A little and powerful iOS framework for intercepting HTTP/HTTPS Traffic.

A little and powerful iOS framework for intercepting HTTP/HTTPS Traffic.

Proxyman 867 Dec 29, 2022
A modern download manager based on NSURLSession to deal with asynchronous downloading, management and persistence of multiple files.

TWRDownloadManager TWRDownloadManager A modern download manager for iOS (Objective C) based on NSURLSession to deal with asynchronous downloading, man

Michelangelo Chasseur 407 Nov 19, 2022
SwiftyReachability is a simple and lightweight network interface manager written in Swift.

SwiftyReachability is a simple and lightweight network interface manager written in Swift. Freely inspired by https://github.com/tonymillion/Reachabil

Antonio Guerra 5 Nov 4, 2022
iOS Project Manager Client

08-iOS-Project-Manager-Client ν”„λ‘œμ νŠΈ λ§€λ‹ˆμ € STEP 1 ν”„λ‘œμ νŠΈ 할일 리슀트 κΈ°λŠ₯κ΅¬ν˜„ UIκ΅¬ν˜„λ°©μ‹ : μ½”λ“œ 아킀텍쳐 : ProjectManagerViewController : NavigationViewControllerμœ„μ— StackView(

Kioding87 1 Nov 19, 2021
Switch viewcontroller like ios task manager

Kaeru Kaeru can switch ViewController in NavigationController like iOS task manager UI (after iOS 9). Movie Usage You can use HistoryNavigationControl

bannzai 508 Dec 7, 2022