Skip to content

Commit

Permalink
Allow to provide a custom ResponseSerializer and options for JSON and…
Browse files Browse the repository at this point in the history
… PLIST
  • Loading branch information
phimage committed Oct 22, 2015
1 parent 41bc7eb commit c61f91a
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 54 deletions.
4 changes: 4 additions & 0 deletions Alamofire-Prephirences.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
C436A1931BCF8DC100B8CAD1 /* AlamofirePrephirences.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C436A1881BCF8DC100B8CAD1 /* AlamofirePrephirences.framework */; settings = {ASSET_TAGS = (); }; };
C436A1981BCF8DC100B8CAD1 /* Alamofire_PrephirencesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C436A1971BCF8DC100B8CAD1 /* Alamofire_PrephirencesTests.swift */; };
C436A1A31BCF8F4500B8CAD1 /* MutablePreferencesType+Alamofire.swift in Sources */ = {isa = PBXBuildFile; fileRef = C436A1A21BCF8F4500B8CAD1 /* MutablePreferencesType+Alamofire.swift */; settings = {ASSET_TAGS = (); }; };
C4BDE7BE1BD8D77E00442B18 /* SerializationFormat.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BDE7BD1BD8D77E00442B18 /* SerializationFormat.swift */; settings = {ASSET_TAGS = (); }; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand All @@ -35,6 +36,7 @@
C436A1971BCF8DC100B8CAD1 /* Alamofire_PrephirencesTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Alamofire_PrephirencesTests.swift; sourceTree = "<group>"; };
C436A1991BCF8DC100B8CAD1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
C436A1A21BCF8F4500B8CAD1 /* MutablePreferencesType+Alamofire.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "MutablePreferencesType+Alamofire.swift"; sourceTree = "<group>"; };
C4BDE7BD1BD8D77E00442B18 /* SerializationFormat.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SerializationFormat.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -100,6 +102,7 @@
C436A18B1BCF8DC100B8CAD1 /* Alamofire-Prephirences.h */,
C436A18D1BCF8DC100B8CAD1 /* Info.plist */,
C436A1A21BCF8F4500B8CAD1 /* MutablePreferencesType+Alamofire.swift */,
C4BDE7BD1BD8D77E00442B18 /* SerializationFormat.swift */,
);
path = "Alamofire-Prephirences";
sourceTree = "<group>";
Expand Down Expand Up @@ -259,6 +262,7 @@
buildActionMask = 2147483647;
files = (
C436A1A31BCF8F4500B8CAD1 /* MutablePreferencesType+Alamofire.swift in Sources */,
C4BDE7BE1BD8D77E00442B18 /* SerializationFormat.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
66 changes: 23 additions & 43 deletions Alamofire-Prephirences/MutablePreferencesType+Alamofire.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,29 +25,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/


import Foundation
import Prephirences
import Alamofire

enum FileSerializationFormat {
case PropertyList(NSPropertyListReadOptions), JSON(NSJSONReadingOptions)

var errorCode: Error.Code {
switch self {
case PropertyList: return Error.Code.PropertyListSerializationFailed
case JSON: return Error.Code.JSONSerializationFailed
}
}

var responseSerializer: ResponseSerializer<AnyObject, NSError> {
switch self {
case PropertyList(let options): return Request.propertyListResponseSerializer(options: options)
case JSON(let options): return Request.JSONResponseSerializer(options: options)
}
}
}

public extension MutablePreferencesType {

public func loadPropertyListFromURL(url: URLStringConvertible, completionHandler: (Response<AnyObject, NSError> -> Void)? = nil) -> Request {
Expand All @@ -66,40 +47,39 @@ public extension MutablePreferencesType {
return loadFromURLRequest(URLRequest, format: .JSON(.AllowFragments), completionHandler: completionHandler)
}

// MARK: private load
private func loadFromURL(url: URLStringConvertible, format: FileSerializationFormat, completionHandler: (Response<AnyObject, NSError> -> Void)? = nil) -> Request {
// MARK: with format
public func loadFromURL(url: URLStringConvertible, format: SerializationFormat, completionHandler: (Response<AnyObject, NSError> -> Void)? = nil) -> Request {
return responseToRequest(Alamofire.request(.GET, url), format: format, completionHandler: completionHandler)
}

private func loadFromURLRequest(URLRequest: URLRequestConvertible, format: FileSerializationFormat, completionHandler: (Response<AnyObject, NSError> -> Void)? = nil) -> Request {
public func loadFromURLRequest(URLRequest: URLRequestConvertible, format: SerializationFormat, completionHandler: (Response<AnyObject, NSError> -> Void)? = nil) -> Request {
return responseToRequest(Alamofire.request(URLRequest), format: format, completionHandler: completionHandler)
}

// MARK: response
private func responseToRequest(request: Request, format: FileSerializationFormat, completionHandler: (Response<AnyObject, NSError> -> Void)? = nil) -> Request {
private func responseToRequest(request: Request, format: SerializationFormat, completionHandler: (Response<AnyObject, NSError> -> Void)? = nil) -> Request {
request.validate() // XXX could add here accepted content type
// XXX if no format defined, could get returned content-type from responseContentType = response.MIMEType, responseMIMEType = MIMEType(responseContentType)

return request.response(responseSerializer: format.responseSerializer){ response in
switch response.result {
case .Success(let object):
guard let dico = object as? [String : AnyObject] else {
let error = Error.errorWithCode(format.errorCode, failureReason: "Unable to convert to dictionnary")
let failureResponse = Response<AnyObject, NSError>(request: response.request,
response: response.response,
data: response.data,
result: .Failure(error))

completionHandler?(failureResponse)
break
}
self.setObjectsForKeysWithDictionary(dico)
completionHandler?(response)
case .Failure:
completionHandler?(response)
let responseSerializer = format.responseSerializer
return request.response(responseSerializer: responseSerializer){
response in
switch response.result {
case .Success(let object):
guard let dico = object as? [String : AnyObject] else {
let error = Error.errorWithCode(format.errorCode, failureReason: "Unable to convert to dictionnary")
let failureResponse = Response<AnyObject, NSError>(request: response.request,
response: response.response,
data: response.data,
result: .Failure(error))

completionHandler?(failureResponse)
break
}
self.setObjectsForKeysWithDictionary(dico)
completionHandler?(response)
case .Failure:
completionHandler?(response)
}
}

}

}
49 changes: 49 additions & 0 deletions Alamofire-Prephirences/SerializationFormat.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//
// SerializationFormat.swift
// Alamofire-Prephirences
/*
The MIT License (MIT)

Copyright (c) 2015 Eric Marchand (phimage)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

import Foundation
import Alamofire

public enum SerializationFormat {
case PropertyList(NSPropertyListReadOptions), JSON(NSJSONReadingOptions), Custom(ResponseSerializer<AnyObject, NSError>)

var errorCode: Error.Code {
switch self {
case PropertyList: return Error.Code.PropertyListSerializationFailed
case JSON: return Error.Code.JSONSerializationFailed
case Custom: return Error.Code.DataSerializationFailed
}
}

var responseSerializer: ResponseSerializer<AnyObject, NSError> {
switch self {
case PropertyList(let options): return Request.propertyListResponseSerializer(options: options)
case JSON(let options): return Request.JSONResponseSerializer(options: options)
case Custom(let responseSerializer): return responseSerializer
}
}
}
34 changes: 34 additions & 0 deletions Alamofire-PrephirencesTests/Alamofire_PrephirencesTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,40 @@ class Alamofire_PrephirencesTests: XCTestCase {
}
}

func testLoadCustomFromURL() {
let pref : MutableDictionaryPreferences = [:]

let expectation = expectationWithDescription("request should succeed")

var response : Response<AnyObject, NSError>? = nil
pref.loadFromURL("https://raw.githubusercontent.com/CocoaPods/Specs/master/Specs/Prephirences/2.0.0/Prephirences.podspec.json",
format: .Custom(Request.JSONResponseSerializer(options: .AllowFragments)),
completionHandler: { closureResponse in
response = closureResponse
expectation.fulfill()
})

waitForExpectationsWithTimeout(defaultTimeout, handler: nil)

if let response = response {
XCTAssertNotNil(response.request, "request should not be nil")
XCTAssertNotNil(response.response, "response should not be nil")
XCTAssertNotNil(response.data, "data should not be nil")

switch response.result {
case .Success:
print("\(pref.dictionary())")
break
case .Failure(let error):
XCTFail(error.localizedDescription)
}

} else {
XCTFail("response should not be nil")
}
}



}

27 changes: 16 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,22 @@
)](https://developer.apple.com/swift) [![Cocoapod](http://img.shields.io/cocoapods/v/Alamofire-Prephirences.svg?style=flat)](http://cocoadocs.org/docsets/Alamofire-Prephirences/)


[<img align="left" src="logo-128x128.png" hspace="20">](#logo) Remote preferences and configurations for your application.
[<img align="left" src="logo.png" hspace="20">](#logo) Remote preferences and configurations for your application.

By using remote preferences you can remotely control the behavior of your app, allowing you to active a feature, to make impromptu A/B tests, or to add a simple "message of the day".
By using remote preferences you can remotely control the behavior of your app, allowing you to active a feature, to make impromptu A/B tests or to add a simple "message of the day".

It's built on top of [Alamofire](https://github.com/Alamofire/Alamofire) and [Prephirences](https://github.com/phimage/Prephirences), and provides methods to load from remote `plist` or `json` files.

# Usage #
### Load with URL(Convertible)
On your `NSUserDefault` or any `MutablePreferencesType`
### Load from URL
On your `NSUserDefault` or any `MutablePreferencesType` for `plist`

```swift
mutablePref.loadPropertyListFromURL("http://example.com/pref.plist")
pref.loadPropertyListFromURL("http://example.com/pref.plist")
```
...or if you need a callbacks for success/failure
```swift
mutablePref.loadPropertyListFromURL("http://example.Com/pref.plist",
pref.loadPropertyListFromURL("http://example.Com/pref.plist",
completionHandler: { response in
switch response.result {
case .Success:
Expand All @@ -32,13 +32,18 @@ mutablePref.loadPropertyListFromURL("http://example.Com/pref.plist",
)
```

And for JSON just change `loadPropertyListFromURL` by `loadJSONFromURL`
And for `JSON`format, just change `loadPropertyListFromURL` by `loadJSONFromURL`
```swift
mutablePref.loadJSONFromURL("http://example.com/pref.json")
pref.loadJSONFromURL("http://example.com/pref.json")
```

### Load with URLRequest
For more complex request, instead of use simple URL you can create your own `NSURLRequest`
You can also use custom alamofire `ResponseSerializer`, which must provide a `Dictionary`
```swift
pref.loadFromURL("http://example.com/pref.ext", format: Custom(MyReponseSerializer))
```

### Load from URLRequest
For more complex request, instead of using simple URL, you can implement alamofire `URLRequestConvertible` or provide your own `NSURLRequest`

```swift
let url = NSURL(string: "http://example.com/pref.plist")!
Expand All @@ -62,7 +67,7 @@ If not already done :
Then :
- Add `pod 'Alamofire-Prephirences'` to your `Podfile` and run `pod install`.

*Add `use_frameworks!` to the end of the `Podfile`.*
*Don't forget to add `use_frameworks!` to the end of the `Podfile`.*

# Licence #
```
Expand Down
Binary file added logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit c61f91a

Please sign in to comment.