ReactiveCocoa and Swift

Last November I started converting the Videoland project into a Swift only project. I planned to totally redesign the application and implement a new way of networking.

In Objective-C I was mainly using block based methods in combination with our own network library TIFNetworking, based on AFNetworking. It was a combination of AFNetworking, linking together with Mantle. It gave me methods like this:

TIFRequestOperation *operation = [TIFHTTPClient HTTPRequestOperationWithRequest:request 
modelClass:[PTDVersionInfo class] 
success:^(TIFRequestOperation *operation, PTDVersionInfo *responseObject) {
    if(success){
         success(responseObject);
    }
} failure:failure];

[TIFHTTPClient addRequestOperation:operation];

After investigating the available possibilities in Swift I’ve used the open source application of Artsy as my main inspiration. The combination of Alamofire, Moya and SwiftJSON resulted in the following setup:

enum ExampleAPI : TIFAPI {
    case GetCall
    case DelayCall(delayInSeconds:Int)
    case NoResponseObjectCall
    case ArrayResponseCall
    case ResponseWithStatusCode(statusCode:Int)

    var apiMethod : APIMethod {
        switch self {
        case .GetCall:
            return APIMethod(path: "get", method: .GET, defaultParameters: ["arg":"argone"], jsonClass: GetResponse.self)
        case .DelayCall(var delayInSeconds):
            return APIMethod(path: "delay/\(delayInSeconds)", method: .GET, jsonClass: GetResponse.self)
        case .NoResponseObjectCall:
            return APIMethod(path: "status/200", method: .GET)
        case .ArrayResponseCall:
            return APIMethod(path: "levels", method: .GET, jsonClass: PTDLevel.self)
        case ResponseWithStatusCode(var statusCode):
            return APIMethod(path: "status/\(statusCode)", method: .GET)
        }
    }

    var parameterEncoding: Moya.ParameterEncoding {
        return .URL
    }
}

With Moya it’s possible to use ReactiveCocoa in combination with network calls. Using SwiftJSON I was able to return model objects parsed with the JSON response. An example call looks as followed:

var signal = ExampleAPI.DelayCall(delayInSeconds: delay).signalValue.initially { () -> Void in
    UIApplication.sharedApplication().networkActivityIndicatorVisible = true
}.doError { (error) -> Void in
    println("Error! \(error)")
}.doNextAs { (response:GetResponse) -> () in
    println("Success! \(response.origin)")
}.doCompleted { () -> Void in
    UIApplication.sharedApplication().networkActivityIndicatorVisible = false
}

signal.execute()

In the beginning it was quite hard to use, but after a few days I got used to it. I’m very happy with the final result and the readability, as the above code should speak for it self.

If you’re looking for a good way to setup a networking layer in Swift, think about combining these libraries!

 

Antoine van der Lee

Dutch iOS developer at Triple. Developed apps like Buienradar, Videoland and Pop the Dots.

 
Follow on Feedly