Swift networking for JSON services, using ReactiveCocoa
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
ReactiveJSON.xcodeproj
ReactiveJSONTests
Source
Tests
.gitignore
Cartfile
Cartfile.private
Cartfile.resolved
Carthage.xcconfig
Info.plist
README.md
ReactiveJSON.h

README.md

ReactiveJSON

Version Platforms Languages License Carthage compatible

ReactiveJSON is a Swift network framework for JSON services, built using ReactiveCocoa. The framework is minimally designed, yet still highly flexibile.

Features includes:

  • Easy-to-create, and highly adatable JSON clients;
  • Support for the most common HTTP methods;
  • Parameter encoding;
  • OAuth2 token support;
  • Automatic JSON parsing;

Usage

After a tiny bit of setup, requests look like this:

// Create a `SignalProducer` that will execute the network request when started.
MyJSONService
    .request(endpoint: "foo")
    .startWithResult {
        // `value` is inferred to be `Any`
        print($0.value)
    }
//------------------------------------------------------------------------------
// Bind a GET request to a `MutableProperty`
let users = MutableProperty<[[String:AnyObject]]>([])
users <~ MyJSONService
    .request(endpoint: "users")
    .ignoreError()
//------------------------------------------------------------------------------
// Send a POST request
MyJSONService
    .request(endpoint: "sprocket", method: .Post, parameters: ["foo":"bar"])
    .startWithCompleted {
        print("huzzah!")
    }

Setup

Here is an example of creating a JSON client:

/// A JSON client for the Guild Wars 2 API
struct GW2API: Singleton, ServiceHost {
    // 'Singleton'
    private(set) static var shared = Instance()
    typealias Instance = GW2API

    // 'ServiceHost'
    static var scheme: String { return "https" }
    static var host: String { return "api.guildwars2.com" }
    static var path: String? { return "v2" }
}

Any ServiceHost can make a request. Therefore, a Singleton that is also a ServiceHost can, as well:

// Prints the name of all dyes returned by the "colors" endpoint
GW2API.request(endpoint: "colors", parameters: ["ids":"all"])
    .startWithResult {
        $0.value?.forEach {
            print($0["name"])
        }
    }

Mocking Requests

Benjamin Encz sums up the philosophy behind ReactiveJSON rather well:

"One of my favorite aspects of Swift: Protocols allow you describe truths about types. Generic code can build on top of these truths."

The Singleton protocol requires its Instance alias be a ServiceHost. Without the need to overload any request functions, we can create a client that loads its responses from a fixture file. The result might look something like this:

Note: For a complete example of this concept, see Fixture.swift

class ServiceHostTests: QuickSpec {
    override func spec() {
        describe("resource json") {
            it("handles conformance on assignment") {
                var users: [[String:AnyObject]] = []
                try! Fixture.request(fixture: "users") { users = $0 }

                expect { users.first?["username"] as? String
                    }.toEventually( equal("Bret") )

                expect { users.first?["id"] as? Int
                    }.toEventually( equal(1) )
            }
        }
    }
}