matsuda
6/19/2016 - 8:00 AM

Alamofire + Himotoki

Alamofire + Himotoki

{
	"status": "00",
	"messages": [],
	"results": {
		"id": 12345,
		"name": "sample name"
	}
}
    func request() {
        Manager.sharedInstance.request(.GET, path)
            .responseObject { (response: Response<APIResponse<User>, APIError>) in
//            debugPrint(response)
                switch response.result {
                case .Success(let result):
                    print(result)
                    if let URL = self.storeURL("user.json"), data = response.data {
                        if data.writeToURL(URL, atomically: true) {
                            print("save")
                        } else {
                            print("not save")
                        }
                    }
                case .Failure(let error):
                    print(error)
                }
        }
    }

    func download() {
        Alamofire
            .download(.GET, path) { [unowned self] (temporaryURL, response) -> NSURL in
                print("temporaryURL >>>", temporaryURL)
                print("suggestedFilename >>> ", response.suggestedFilename)
                if let URL = self.storeURL(response.suggestedFilename!) {
                    return URL
                }
                return temporaryURL
            }
            .responseObject { (response: Response<APIResponse<User>, APIError>) in
                print("================================================")
                print("response.response >>> ", response.response)
                print("response.data >>>", response.data)
                switch response.result {
                case .Success(let result):
                    print("result >>>", result)
                case .Failure(let error):
                    print("error >>>", error)
                }
        }
    }

    func storeURL(path: String) -> NSURL? {
        let fileManager = NSFileManager.defaultManager()
        if let directoryURL = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first {
            let URL = directoryURL.URLByAppendingPathComponent(path)

            if fileManager.fileExistsAtPath(URL.path!) {
                do {
                    try fileManager.removeItemAtURL(URL)
                } catch {
                    print("error >>>", error)
                }
            }
            return URL
        } else {
            return nil
        }
    }
//
// https://github.com/Alamofire/Alamofire#response-serialization-1
//

import Alamofire
import Himotoki

protocol ResponseObjectSerializable: Decodable {
}

enum APIError: ErrorType {
    case Network(error: NSError)
    case JSONSerialization(error: NSError)
    case ObjectDecode(error: ErrorType)
    // case ObjectSerialization(reason: String)
}

extension Request {
    func responseObject<T: ResponseObjectSerializable>(completionHandler: Response<T, APIError> -> Void) -> Self {
        let serializer = ResponseSerializer<T, APIError> { request, response, data, error in
            guard error == nil else { return .Failure(.Network(error: error!)) }
            let JSONResponseSerializer = Request.JSONResponseSerializer(options: .AllowFragments)
            let result = JSONResponseSerializer.serializeResponse(request, response, data, error)
            switch result {
            case .Success(let value):
                do {
                    return .Success(try decodeValue(value))
                } catch {
                    return .Failure(.ObjectDecode(error: error))
                    // return .Failure(.ObjectSerialization(reason: "JSON could not be serialized into response object: \(value)"))
                }
            case .Failure(let error):
                return .Failure(.JSONSerialization(error: error))
            }
        }
        return response(responseSerializer: serializer, completionHandler: completionHandler)
    }
}

///
/// MARK: - Response
///
struct APIResponse<Result: Decodable>: ResponseObjectSerializable {
    let status: Status
    let messages: [String]
    let results: Result

    static func decode(e: Extractor) throws -> APIResponse<Result> {
        return try APIResponse(
            // status: e <| "status",
            status: Status(rawValue: e <| "status")!,
            messages: e <|| "messages",
            results: e <| "results"
        )
    }
}

enum Status: String {
    case success = "00"
    case error = "01"
}

struct User: Decodable {
    let id: Int
    let name: String

    static func decode(e: Extractor) throws -> User {
        return try User(id: e <| "id", name: e <| "name")
    }
}

class ViewController: UIViewController {
    func request() {
        let path = "http://example.com/sample/user.json"
        Manager.sharedInstance.request(.GET, path)
            .responseObject { (response: Response<APIResponse<User>, APIError>) in
                // debugPrint(response)
                switch response.result {
                case .Success(let result):
                    print(result)
                case .Failure(let error):
                    print(error)
                }
        }
    }

}