├── .swift-version
├── .gitignore
├── raccoon.xcodeproj
├── project.xcworkspace
│ └── contents.xcworkspacedata
├── xcshareddata
│ └── xcschemes
│ │ └── Raccoon.xcscheme
└── project.pbxproj
├── raccoon.xcworkspace
├── contents.xcworkspacedata
└── xcshareddata
│ ├── IDEWorkspaceChecks.plist
│ └── raccoon.xcscmblueprint
├── Podfile
├── raccoon
├── Raccoon.h
├── Info.plist
└── source
│ ├── Endpoint.swift
│ └── Client.swift
├── raccoonTests
└── Info.plist
├── Raccoon.podspec
├── CHANGELOG.md
├── LICENSE
├── Podfile.lock
└── README.md
/.swift-version:
--------------------------------------------------------------------------------
1 | 4.2
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | Pods
2 | raccoon.xcodeproj/xcuserdata
3 | raccoon.xcworkspace/xcuserdata
4 |
--------------------------------------------------------------------------------
/raccoon.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/raccoon.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/raccoon.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Podfile:
--------------------------------------------------------------------------------
1 | platform :ios, '9.0'
2 | use_frameworks!
3 |
4 | abstract_target 'abstract_target' do
5 |
6 | pod 'AlamofireCoreData', '~> 2.0'
7 | pod 'PromiseKit/CorePromise', '~> 4.4'
8 |
9 | target 'Raccoon'
10 |
11 | target 'RaccoonTests' do
12 | pod 'OHHTTPStubs', '~> 5.2'
13 | pod 'OHHTTPStubs/Swift', '~> 5.2'
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/raccoon/Raccoon.h:
--------------------------------------------------------------------------------
1 | //
2 | // Raccoon.h
3 | // Raccoon
4 | //
5 | // Created by Manu on 26/4/16.
6 | // Copyright © 2016 manuege. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | //! Project version number for Raccoon.
12 | FOUNDATION_EXPORT double RaccoonVersionNumber;
13 |
14 | //! Project version string for Raccoon.
15 | FOUNDATION_EXPORT const unsigned char RaccoonVersionString[];
16 |
17 | // In this header, you should import all the public headers of your framework using statements like #import
18 |
19 |
20 |
--------------------------------------------------------------------------------
/raccoonTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/raccoon/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(CURRENT_PROJECT_VERSION)
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Raccoon.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |spec|
2 |
3 | spec.name = "Raccoon"
4 | spec.version = "1.3.0"
5 | spec.summary = "Puts together Alamofire, CoreData and PromiseKit"
6 | spec.description = <<-DESC
7 | A nice set of protocols and tools that puts together Alamofire, PromiseKit and CoreData.
8 | DESC
9 | spec.homepage = "https://github.com/ManueGE/Raccoon/"
10 | spec.license = "MIT"
11 |
12 |
13 | spec.author = "Manuel García-Estañ"
14 | spec.social_media_url = "http://twitter.com/ManueGE"
15 |
16 | spec.platform = :ios, "9.0"
17 | spec.source = { :git => "https://github.com/ManueGE/Raccoon.git", :tag => "#{spec.version}" }
18 |
19 | spec.requires_arc = true
20 | spec.dependency "Alamofire", "~> 4.7"
21 | spec.dependency "PromiseKit/CorePromise", "~> 4.4"
22 | spec.dependency "AlamofireCoreData", "~> 2.0"
23 |
24 | spec.source_files = "Raccoon/source/**/*.{swift}"
25 |
26 | spec.framework = "CoreData"
27 |
28 | end
29 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | ### 1.3.0 (25 September 2018)
4 | - Swift 4.2, Alamofire 4.7
5 |
6 | ### 1.2.0 (10 October 2017)
7 | - Swift 4, Alamofire 4.5, PromiseKit 4.4
8 |
9 | ## 1.1.1 (30 June 2017)
10 | - Fix build problem with `void` promises in swift 4.
11 |
12 | ## 1.1.0 (30 June 2017)
13 | - Add `cancellableEnqueue` methods to allow cancel requests manually.
14 | - Swift 3, Alamofire 4.5, PromiseKit 4.2, Groot 2.0.
15 |
16 | ## 1.0.0 (13 October 2016)
17 | - First stable version
18 | - Remove Realm support
19 | - Remove all serliaziation code. It is now in a separate pod ([AlamofireCoreData](http://github.com/manueGE/AlamofireCoreData))
20 | - Swift 3, Alamofire 4.0, PromiseKit 4.0, Groot 2.0.
21 |
22 | ## Betas 0.x.x
23 |
24 | ### 0.2.0
25 | #### Enhacements
26 | - Support serializing as an array of `Wrapper` instances.
27 |
28 | #### Breaking changes
29 | - New `ReponseConverter` input and output parameters.
30 |
31 | ### 0.1.1
32 | - Supports `PromiseKit` latest version (3.2)
33 |
34 | ### 0.1.0
35 | - Initial version
36 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Manuel García-Estañ
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/raccoon/source/Endpoint.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Endpoint.swift
3 | // raccoon
4 | //
5 | // Created by Manuel García-Estañ on 8/10/16.
6 | // Copyright © 2016 manuege. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import Alamofire
11 |
12 | /**
13 | Helper extension to build URLS from base URL string and path
14 | */
15 | public extension URL {
16 |
17 | /**
18 | Creates a new URL with the given base and path.
19 | Internally it make use of `init(string: String, relativeTo: URL)` so same rules applies here.
20 | */
21 | init?(base: String, path: String) {
22 | guard let baseURL = URL(string: base) else {
23 | return nil
24 | }
25 |
26 | self.init(string: path, relativeTo: baseURL)
27 | }
28 | }
29 |
30 | /* An Endpoint is just an instance that can build a `DataRequest` from a base url.
31 | Use it to enqueue request in a client
32 | */
33 | public protocol Endpoint {
34 |
35 | /**
36 | Returns a request built with the given base url
37 |
38 | - parameter baseURL: The base url to build the request
39 |
40 | - returns: The request ready to be sent.
41 | */
42 | func request(withBaseURL baseURL: String) -> DataRequest
43 | }
44 |
--------------------------------------------------------------------------------
/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - Alamofire (4.7.3)
3 | - AlamofireCoreData (2.0.0):
4 | - Alamofire (~> 4.7)
5 | - Groot (~> 3.0)
6 | - Groot (3.0.1):
7 | - Groot/Swift (= 3.0.1)
8 | - Groot/Swift (3.0.1)
9 | - OHHTTPStubs (5.2.1):
10 | - OHHTTPStubs/Default (= 5.2.1)
11 | - OHHTTPStubs/Core (5.2.1)
12 | - OHHTTPStubs/Default (5.2.1):
13 | - OHHTTPStubs/Core
14 | - OHHTTPStubs/JSON
15 | - OHHTTPStubs/NSURLSession
16 | - OHHTTPStubs/OHPathHelpers
17 | - OHHTTPStubs/JSON (5.2.1):
18 | - OHHTTPStubs/Core
19 | - OHHTTPStubs/NSURLSession (5.2.1):
20 | - OHHTTPStubs/Core
21 | - OHHTTPStubs/OHPathHelpers (5.2.1)
22 | - OHHTTPStubs/Swift (5.2.1):
23 | - OHHTTPStubs/Core
24 | - PromiseKit/CorePromise (4.4.0)
25 |
26 | DEPENDENCIES:
27 | - AlamofireCoreData (~> 2.0)
28 | - OHHTTPStubs (~> 5.2)
29 | - OHHTTPStubs/Swift (~> 5.2)
30 | - PromiseKit/CorePromise (~> 4.4)
31 |
32 | SPEC REPOS:
33 | https://github.com/cocoapods/specs.git:
34 | - Alamofire
35 | - AlamofireCoreData
36 | - Groot
37 | - OHHTTPStubs
38 | - PromiseKit
39 |
40 | SPEC CHECKSUMS:
41 | Alamofire: c7287b6e5d7da964a70935e5db17046b7fde6568
42 | AlamofireCoreData: 3205949bd789c2aa5e1cd8f4d703631c9d7ba09c
43 | Groot: a668afbcf0be88d76c0a26c714cfa4638ceaca66
44 | OHHTTPStubs: 3a42f25c00563b71355ac73112ba2324e9e6cef4
45 | PromiseKit: ecf5fe92275d57ee77c9ede858af47a162e9b97e
46 |
47 | PODFILE CHECKSUM: 5b5606354902ff60b7df1b19866ff037d347e788
48 |
49 | COCOAPODS: 1.5.3
50 |
--------------------------------------------------------------------------------
/raccoon.xcworkspace/xcshareddata/raccoon.xcscmblueprint:
--------------------------------------------------------------------------------
1 | {
2 | "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "281CF20BD3701CFD2C39EA9F59F9FFC7E4BC3EFD",
3 | "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : {
4 |
5 | },
6 | "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : {
7 | "281CF20BD3701CFD2C39EA9F59F9FFC7E4BC3EFD" : 9223372036854775807,
8 | "619A3FBBE13EC7937545FB26C1C97E17658B1AE8" : 9223372036854775807
9 | },
10 | "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "877C6854-1300-4599-8397-824BA41E7380",
11 | "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : {
12 | "281CF20BD3701CFD2C39EA9F59F9FFC7E4BC3EFD" : "raccoon\/",
13 | "619A3FBBE13EC7937545FB26C1C97E17658B1AE8" : "..\/AlamofireCoreData"
14 | },
15 | "DVTSourceControlWorkspaceBlueprintNameKey" : "raccoon",
16 | "DVTSourceControlWorkspaceBlueprintVersion" : 204,
17 | "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "raccoon.xcworkspace",
18 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [
19 | {
20 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/ManueGE\/Raccoon.git",
21 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
22 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "281CF20BD3701CFD2C39EA9F59F9FFC7E4BC3EFD"
23 | },
24 | {
25 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/ManueGE\/AlamofireCoreData.git",
26 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
27 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "619A3FBBE13EC7937545FB26C1C97E17658B1AE8"
28 | }
29 | ]
30 | }
--------------------------------------------------------------------------------
/raccoon.xcodeproj/xcshareddata/xcschemes/Raccoon.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
31 |
32 |
34 |
40 |
41 |
42 |
43 |
44 |
50 |
51 |
52 |
53 |
54 |
55 |
65 |
66 |
72 |
73 |
74 |
75 |
76 |
77 |
83 |
84 |
90 |
91 |
92 |
93 |
95 |
96 |
99 |
100 |
101 |
--------------------------------------------------------------------------------
/raccoon/source/Client.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Client.swift
3 | // raccoon
4 | //
5 | // Created by Manuel García-Estañ on 8/10/16.
6 | // Copyright © 2016 manuege. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import CoreData
11 | import AlamofireCoreData
12 | import PromiseKit
13 | import Alamofire
14 |
15 | /**
16 | An object which encapsulate a promise that can be cancelled at any time.
17 | */
18 | public struct Cancellable {
19 | /// The promise of the cancellable object
20 | public let promise: Promise
21 |
22 | /// The method to call if the request must be cancelled
23 | public let cancel: () -> Void
24 | }
25 |
26 | /**
27 | Clients are instances that can send network requests. The requests are built using `Endpoints`.
28 | The responses of this endpoints will be inserted in the given managed object context.
29 | */
30 | public protocol Client {
31 |
32 | // MARK: Required
33 |
34 | /// The base url which will be used to build the reqeusts
35 | var baseURL: String { get }
36 |
37 | /// The managed object context where all the responses will be inserted.
38 | var context: NSManagedObjectContext { get }
39 |
40 | // MARK: Optionals
41 | /**
42 | The DataResponseSerializer which will transform the original response to the JSON which will be used to insert the responses.
43 | By default it is `DataRequest.jsonResponseSerializer()`
44 | */
45 | var jsonSerializer: DataResponseSerializer { get }
46 |
47 | /**
48 | Use this method to perform any last minute changes on the DataRequest to send.
49 | Here you can add some validations, log the requests, or whatever thing you need.
50 | By default, it returns the request itself, without any addition
51 |
52 | - parameter request: The request that will be sent
53 | - parameter endpoint: The endpoint which launched the reqeust
54 |
55 | - returns: the modified request
56 | */
57 | func prepare(_ request: DataRequest, for endpoint: Endpoint) -> DataRequest
58 |
59 | /**
60 | Use this method to perform any last minute changes on the Promise created when a request is sent.
61 | Here you can add some common `recover` or `then` to all the promise
62 | By default, it returns the promise itself, without any addition
63 |
64 | - parameter request: The `Promise`
65 | - parameter endpoint: The `Endpoint` that launched the request
66 |
67 | - returns: the modified request
68 | */
69 | func process(_ promise: Promise, for endpoint: Endpoint) -> Promise
70 | }
71 |
72 | public extension Client {
73 |
74 | // MARK: - Default methods
75 | public var jsonSerializer: DataResponseSerializer {
76 | return DataRequest.jsonResponseSerializer()
77 | }
78 |
79 | public func prepare(_ request: DataRequest, for endpoint: Endpoint) -> DataRequest {
80 | return request
81 | }
82 |
83 | func process(_ promise: Promise, for endpoint: Endpoint) -> Promise {
84 | return promise
85 | }
86 | }
87 |
88 | public extension Client {
89 |
90 | /**
91 | Enqueues the request generated by the endpoint and insert it using the generic type.
92 | It returns a Cancellable to inform if the request has finished succesfully or not.
93 |
94 | The request can be cancelled at any time by calling `cancel()` in the cancellable object.
95 |
96 | - parameter endpoint: The endpoint
97 |
98 | - returns: The Cancellable object
99 | */
100 | public func cancellableEnqueue(_ endpoint: Endpoint) -> Cancellable {
101 | let request = endpoint.request(withBaseURL: baseURL)
102 | let promise = Promise { fulfill, reject in
103 | prepare(request, for: endpoint)
104 | .responseInsert(
105 | queue: nil,
106 | jsonSerializer: jsonSerializer,
107 | context: context,
108 | type: T.self) { response in
109 |
110 | switch response.result {
111 | case let .success(value):
112 | fulfill(value)
113 | case let .failure(error):
114 | reject(error)
115 | }
116 | }
117 | }
118 |
119 | let finalPromise = process(promise, for: endpoint)
120 | let cancel = request.cancel
121 | return Cancellable(promise: finalPromise, cancel: cancel)
122 | }
123 |
124 | /**
125 | Enqueues the request generated by the endpoint and insert it using the generic type.
126 | It returns a Promise to inform if the request has finished succesfully or not
127 |
128 | - parameter endpoint: The endpoint
129 |
130 | - returns: The promise
131 | */
132 | public func enqueue(_ endpoint: Endpoint) -> Promise {
133 | return cancellableEnqueue(endpoint).promise
134 | }
135 |
136 | /**
137 | Enqueues the request generated by the endpoint.
138 | It returns a Cancellable to inform if the request has finished succesfully or not
139 |
140 | The request can be cancelled at any time by calling `cancel()` in the cancellable object.
141 |
142 | - parameter endpoint: The endpoint
143 |
144 | - returns: The cancellable object
145 | */
146 | public func cancellableEnqueue(_ endpoint: Endpoint) -> Cancellable {
147 | let request = endpoint.request(withBaseURL: baseURL)
148 | let promise = Promise { fulfill, reject in
149 | prepare(request, for: endpoint)
150 | .responseInsert(
151 | jsonSerializer: jsonSerializer,
152 | context: context,
153 | type: Empty.self) { response in
154 |
155 | switch response.result {
156 | case .success:
157 | fulfill(())
158 | case let .failure(error):
159 | reject(error)
160 | }
161 | }
162 | }
163 |
164 | let finalPromise = process(promise, for: endpoint)
165 | let cancel = request.cancel
166 | return Cancellable(promise: finalPromise, cancel: cancel)
167 | }
168 |
169 | /**
170 | Enqueues the request generated by the endpoint.
171 | It returns an empty promise to inform if the request has finished succesfully or not
172 |
173 | - parameter endpoint: The endpoint
174 |
175 | - returns: The promise
176 | */
177 | public func enqueue(_ endpoint: Endpoint) -> Promise {
178 | return cancellableEnqueue(endpoint).promise
179 | }
180 | }
181 |
182 | private struct Empty {}
183 | extension Empty: Insertable {
184 | public static func insert(from json: Any, in context: NSManagedObjectContext) throws -> Empty {
185 | return Empty()
186 | }
187 | }
188 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Raccoon
2 |
3 | **Raccoon** is a set of protocols and tools that puts together [**Alamofire**](https://github.com/Alamofire/Alamofire), [**PromiseKit**](https://github.com/mxcl/PromiseKit) and **CoreData**.
4 |
5 | Internally, Raccoon uses [**Groot**](https://github.com/gonzalezreal/Groot) and [**AlamofireCoreData**](https://github.com/ManueGE/AlamofireCoreData) to serialize JSON into the CoreData objects, so you will need to be familiar with these libraries.
6 |
7 | Raccoon is built around:
8 |
9 | - **Alamofire 4.0.x**
10 | - **PromiseKit 4.0.x**
11 | - **Groot 2.0.x**
12 | - **AlamofireCoreData 1.0.x**
13 |
14 | With Raccoon you'll be able to perform HTTP request as easy as this:
15 |
16 | ````swift
17 | let client = Client(context: context)
18 | client.enqueue(userEndpoint)
19 | .then { (user: User) in
20 | print(user) // At this point, your user is already inserted in your context
21 | }
22 | .catch { error in
23 | print(error)
24 | }
25 | ````
26 |
27 | ## Installing Raccoon
28 |
29 | ### Using CocoaPods
30 |
31 | Add the following line to your `Podfile`:
32 |
33 | ````ruby
34 | pod 'Raccoon'
35 | ````
36 |
37 | Then run `$ pod install`.
38 |
39 | And finally, in the files where you need **Raccoon**:
40 |
41 | ````swift
42 | import Raccoon
43 | ````
44 |
45 | If you don’t have CocoaPods installed or integrated into your project, you can learn how to do so [here](http://cocoapods.org).
46 |
47 | -
48 |
49 | # Usage
50 |
51 | ## Intro
52 |
53 | Raccoon basically consist in two protocols, `Client` and `Endpoint`.
54 |
55 | - `Client` instances are responsible to enqueue http request and return them in the shape of promises. Clients need, at least, a base url (to build the requests) and a `NSManagedObjectContext` where the responses will be inserted.
56 | - `Endpoint` instances are objects that provides information to build the request that will be sent by the clients. Endpoints just must implement one method, `request(withBaseURL:)` which will return the full request built with the given base url.
57 |
58 | Before being ready to work with Raccoon, you should be familiar with:
59 |
60 | - [**PromiseKit**](https://github.com/mxcl/PromiseKit): At least, you should be familiar with basic `Promise` handling: `then`, `catch`, `recover`
61 | - [**Groot**](https://github.com/gonzalezreal/Groot): It is used to serialize JSON into CoreData, so your entities must fullfill its requirements.
62 | - [**AlamofireCoreData**](https://github.com/ManueGE/AlamofireCoreData): At least, you should read about `Wrapper` (to serialize `NSManagedObject` instances from bigger JSONs) and `Many` (to serialize an array of objects).
63 |
64 |
65 |
66 | ## Getting started
67 |
68 | To explain how use Raccoon, we are going to build a simple example.
69 |
70 | Let's suppose we have an API with 2 methods:
71 |
72 | - `GET http://sampleapi.com/users/`: Get a list of users.
73 | - `GET http://sampleapi.com/users//`: Get the detail of the given user.
74 |
75 | We also have to add an api key as a header in the requests.
76 |
77 | To modelize the response, we have our `NSManagedObject` subclass called `User` which has been prepared to being serialized using [**Groot**](https://github.com/gonzalezreal/Groot).
78 |
79 | ### Creating the client
80 |
81 | The `Client` protocol has two required fields:
82 |
83 | - `context: NSManagedObjectContext`: The context used to insert the responses.
84 | - `baseURL: String`: The base url of the api.
85 |
86 | So, we will create our own `Client` class conforming this protocol:
87 |
88 | ````swift
89 |
90 | import Raccoon
91 |
92 | final class Client: Raccoon.Client {
93 |
94 | let baseURL: String = "http://sampleapi.com/"
95 | let context: NSManagedObjectContext
96 |
97 | init(context: NSManagedObjectContext) {
98 | self.context = context
99 | }
100 | }
101 | ````
102 |
103 | That's all, now we can create a client by doing:
104 |
105 | ````swift
106 | let client = Client(context: aContext)
107 | ````
108 |
109 | ### Creating the endpoint
110 |
111 | The `Endpoint` protocol just have one method:
112 |
113 | ````swift
114 | func request(withBaseURL baseURL: String) -> DataRequest
115 | ````
116 |
117 | which is called from the client to build the request.
118 |
119 | In our example, we will create a `Endpoint` subprotocol to helping us to build the actual endpoints:
120 |
121 | ````swift
122 | protocol AppEndpoint: Endpoint {
123 | var path: String { get }
124 | var method: Alamofire.HTTPMethod { get }
125 | var params: Parameters? { get }
126 | var encoding: Alamofire.ParameterEncoding { get }
127 | }
128 |
129 | extension AppEndpoint {
130 | func request(withBaseURL baseURL: String) -> DataRequest {
131 | let url = URL(base: baseURL, path: path)!
132 |
133 | let headers: HTTPHeaders = ["APIKEY": "MY API KEY"]
134 |
135 | return Alamofire.request(url,
136 | method: method,
137 | parameters: params,
138 | encoding: encoding,
139 | headers: headers)
140 | }
141 | }
142 | ````
143 |
144 | Some notes:
145 |
146 | - First we build the URL from the baseURL and the endpoint path. To build the URL we use a Raccoon extension for `URL`.
147 | - Next we add the api key to the headers.
148 | - We build the request using the info provided by the endpoint and return it.
149 |
150 | After we have our protocol, we can create the endpoints.
151 |
152 | ````swift
153 | enum UserEndpoint: AppEndpoint {
154 | case list
155 | case detail(id: Int)
156 |
157 | // MARK: AppEndpoint
158 | var method: Alamofire.HTTPMethod { return .get }
159 | var encoding: Alamofire.ParameterEncoding { return JSONEncoding() }
160 | var params: Parameters? { return nil }
161 |
162 | var path: String {
163 | switch self {
164 | case .list:
165 | return "users"
166 | case let .detail(id):
167 | return "users/\(id)/"
168 | }
169 | }
170 | }
171 | ````
172 |
173 | Now, we are ready to send the requests.
174 |
175 | ### Enqueueing requests
176 |
177 | Once we have the `Client` and the `Endpoint`, enqueue the request is very easy:
178 |
179 |
180 | ````swift
181 | let client = Client(context: context)
182 |
183 | client.enqueue(UserEndpoint.list)
184 | .then { (users: Many) in
185 | print(users)
186 | }
187 | .catch { error in
188 | print(error)
189 | }
190 |
191 | client.enqueue(UserEndpoint.detail(id: 1))
192 | .then { (user: User) in
193 | print(user)
194 | }
195 | .catch { error in
196 | print(error)
197 | }
198 | ````
199 |
200 | #### Cancellable enqueue.
201 |
202 | If you want to cancel a request manually, you can use the `cancellableEnqueue` methods. They return an instance of `Cancellable`, which contains a `Promise` and a `cancel()` method:
203 |
204 | ````swift
205 | let client = Client(context: context)
206 |
207 | let cancellable: Cancellable> = client.cancellableEnqueue(UserEndpoint.list)
208 |
209 | cancellable.promise
210 | .then { (users: Many) in
211 | print(users)
212 | }
213 | .catch { error in
214 | print(error)
215 | }
216 |
217 |
218 | // ... later on
219 |
220 | cancellable.cancel()
221 |
222 | ````
223 |
224 | ## Advanced usage
225 |
226 | In the previous example, we used Raccoon in its simplest stage. It allows some additional configuration to adapt itself to your REST API design.
227 |
228 | ### Wrapper responses
229 | Let's think we have another call to our api where we perform a login:
230 |
231 | ````
232 | POST http://sampleapi.com/login/
233 | ````
234 |
235 | The response of this requests is this json:
236 |
237 | ````json
238 | {
239 | "token": "authtoken",
240 | "user": {"id": 1, "name": "manue"}
241 | }
242 | ````
243 |
244 | In this response, we have two parts, one object to be stored "as is" (the token) and a object to be inserted in the context (the user).
245 |
246 | To handle with this, we create a new object that conforms with [AlamofireCoreData Wrapper protocol](https://github.com/ManueGE/AlamofireCoreData#using-wrapper):
247 |
248 | ````swift
249 | struct LoginResponse: Wrapper {
250 | var token: String!
251 | var user: User!
252 |
253 | init() {}
254 |
255 | mutating func map(_ map: Map) {
256 | token <- map["token"]
257 | user <- map["user"]
258 | }
259 | }
260 | ````
261 |
262 | Now, we can create a new endpoint:
263 |
264 | ````swift
265 | struct LoginEndpoint: RestEndpoint {
266 | let username: String
267 | let password: String
268 |
269 | init(username: String, password: String) {
270 | self.username = username
271 | self.password = password
272 | }
273 |
274 | // MARK: AppEndpoint
275 | var path = "login/"
276 | var method: Alamofire.HTTPMethod = .post
277 | var encoding: Alamofire.ParameterEncoding = JSONEncoding()
278 | var params: Parameters? {
279 | return ["username": username, "password": password]
280 | }
281 | }
282 | ````
283 |
284 | And then enqueueing it:
285 |
286 | ````swift
287 | let client = Client(context: context)
288 |
289 | client.enqueue(LoginEndpoint(username: "username", password: "password")
290 | .then { (response: LoginResponse) in
291 | print(response.token) // Here you can save your token in the defaults if needed
292 | print(response.user) // User already inserted in the context
293 | }
294 | .catch { error in
295 | print(error)
296 | }
297 | ````
298 |
299 | ### Custom json serialization
300 | In some cases, the data we get from the server is not in the right format. It could even happens that we have a XML where one of its fields is the JSON we have to parse (yes, I've found things like those 😅). In order to solve this issues, the `Client` protocol has an additional optional var that you can use to transform the response into the JSON you need:
301 |
302 | ````swift
303 | var jsonSerializer: DataResponseSerializer
304 | ````
305 |
306 | `jsonSerializer ` is just a `Alamofire.DataResponseSerializer`. You can build your serializer as you want; the only condition is that it must return the JSON which you expect and which can be serialized by **Groot**.
307 |
308 | For getting more info about how to build this serializer, please read this section of the [AlamofireCoreData documentation](https://github.com/ManueGE/AlamofireCoreData#transforming-your-json)
309 |
310 | ### Customising the requests
311 |
312 | The `Request` provided by the `Endpoint` can be improved in the client side by using the following `Client` optional method:
313 |
314 | ````swift
315 | func prepare(_ request: DataRequest, for endpoint: Endpoint) -> DataRequest
316 | ````
317 |
318 | For example, we can add a validator and [a logger for your requests](http://github.com/ManueGE/AlamofireActivityLogger):
319 |
320 | ````swift
321 | func prepare(_ request: DataRequest, for endpoint: Endpoint) -> DataRequest {
322 | return request
323 | .validate()
324 | .log()
325 | }
326 | ````
327 |
328 |
329 | ### Processing the promise
330 |
331 | Let's suppose we want to save the managed object context every time a request finish successfully. We could add this to every request:
332 |
333 | ````swift
334 | client.enqueue(endpoint)
335 | .then { object: User in
336 | try client.context.save()
337 | }
338 | ````
339 |
340 | This is not great, you would have to add it to every request. Instead, you can make use of one of the optional methods of the `Client` protocol:
341 |
342 | ````swift
343 | func process(_ promise: Promise, for endpoint: Endpoint) -> Promise
344 | ````
345 |
346 | This method is called by the client before return the `Promise`. By default it returns the promise itself.
347 |
348 | In our example, you just have to add these lines to your `Client`:
349 |
350 | ````swift
351 | func process(_ promise: Promise, for endpoint: Endpoint) -> Promise {
352 | return promise.then { response -> T in
353 | try self.context.save()
354 | return response
355 | }
356 | }
357 | ````
358 |
359 | You can do whatever you need with your promise on this method, for example `recover` from some errors or show/hide the network indicator of the status bar.
360 |
361 | -
362 |
363 | ## License
364 |
365 | Raccoon is available under the [MIT license](LICENSE.md).
366 |
367 | ## Contact
368 | [Manuel García-Estañ Martínez](http://github.com/ManueGE)
369 | [@manueGE](https://twitter.com/ManueGE)
370 |
--------------------------------------------------------------------------------
/raccoon.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 321A2D621DA868550085E399 /* Endpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 321A2D611DA868550085E399 /* Endpoint.swift */; };
11 | 321A2D641DA8689E0085E399 /* Client.swift in Sources */ = {isa = PBXBuildFile; fileRef = 321A2D631DA8689E0085E399 /* Client.swift */; };
12 | 3285AB891CD019FE00350513 /* Raccoon.h in Headers */ = {isa = PBXBuildFile; fileRef = 3285AB881CD019FE00350513 /* Raccoon.h */; settings = {ATTRIBUTES = (Public, ); }; };
13 | 3285AB901CD019FE00350513 /* Raccoon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3285AB861CD019FE00350513 /* Raccoon.framework */; };
14 | 78B30346D0D4AD1764E3D12B /* Pods_abstract_target_Raccoon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2C46CCED049B6F1029FB6131 /* Pods_abstract_target_Raccoon.framework */; };
15 | E1E8473EF5F1DC4C4E3C1D23 /* Pods_abstract_target_RaccoonTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 711C0ADF627C4B11CBD0EDE4 /* Pods_abstract_target_RaccoonTests.framework */; };
16 | /* End PBXBuildFile section */
17 |
18 | /* Begin PBXContainerItemProxy section */
19 | 3285AB911CD019FE00350513 /* PBXContainerItemProxy */ = {
20 | isa = PBXContainerItemProxy;
21 | containerPortal = 32DDC7761CCFA95A008FC6D5 /* Project object */;
22 | proxyType = 1;
23 | remoteGlobalIDString = 3285AB851CD019FE00350513;
24 | remoteInfo = Raccoon;
25 | };
26 | /* End PBXContainerItemProxy section */
27 |
28 | /* Begin PBXFileReference section */
29 | 2C46CCED049B6F1029FB6131 /* Pods_abstract_target_Raccoon.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_abstract_target_Raccoon.framework; sourceTree = BUILT_PRODUCTS_DIR; };
30 | 321A2D611DA868550085E399 /* Endpoint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Endpoint.swift; sourceTree = ""; };
31 | 321A2D631DA8689E0085E399 /* Client.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Client.swift; sourceTree = ""; };
32 | 3285AB861CD019FE00350513 /* Raccoon.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Raccoon.framework; sourceTree = BUILT_PRODUCTS_DIR; };
33 | 3285AB881CD019FE00350513 /* Raccoon.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Raccoon.h; sourceTree = ""; };
34 | 3285AB8A1CD019FE00350513 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
35 | 3285AB8F1CD019FE00350513 /* RaccoonTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RaccoonTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
36 | 3285AB961CD019FE00350513 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
37 | 6DEA79D492FB382729AC1680 /* Pods-abstract_target-RaccoonTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-abstract_target-RaccoonTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-abstract_target-RaccoonTests/Pods-abstract_target-RaccoonTests.debug.xcconfig"; sourceTree = ""; };
38 | 711C0ADF627C4B11CBD0EDE4 /* Pods_abstract_target_RaccoonTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_abstract_target_RaccoonTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
39 | 7F1EB9E06C42FB77CF4402CA /* Pods-abstract_target-Raccoon.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-abstract_target-Raccoon.debug.xcconfig"; path = "Pods/Target Support Files/Pods-abstract_target-Raccoon/Pods-abstract_target-Raccoon.debug.xcconfig"; sourceTree = ""; };
40 | 91B7B199F6351D14F5DBF877 /* Pods-abstract_target-RaccoonTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-abstract_target-RaccoonTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-abstract_target-RaccoonTests/Pods-abstract_target-RaccoonTests.release.xcconfig"; sourceTree = ""; };
41 | B6EECBC99055AAC5595AD492 /* Pods-abstract_target-Raccoon.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-abstract_target-Raccoon.release.xcconfig"; path = "Pods/Target Support Files/Pods-abstract_target-Raccoon/Pods-abstract_target-Raccoon.release.xcconfig"; sourceTree = ""; };
42 | /* End PBXFileReference section */
43 |
44 | /* Begin PBXFrameworksBuildPhase section */
45 | 3285AB821CD019FE00350513 /* Frameworks */ = {
46 | isa = PBXFrameworksBuildPhase;
47 | buildActionMask = 2147483647;
48 | files = (
49 | 78B30346D0D4AD1764E3D12B /* Pods_abstract_target_Raccoon.framework in Frameworks */,
50 | );
51 | runOnlyForDeploymentPostprocessing = 0;
52 | };
53 | 3285AB8C1CD019FE00350513 /* Frameworks */ = {
54 | isa = PBXFrameworksBuildPhase;
55 | buildActionMask = 2147483647;
56 | files = (
57 | 3285AB901CD019FE00350513 /* Raccoon.framework in Frameworks */,
58 | E1E8473EF5F1DC4C4E3C1D23 /* Pods_abstract_target_RaccoonTests.framework in Frameworks */,
59 | );
60 | runOnlyForDeploymentPostprocessing = 0;
61 | };
62 | /* End PBXFrameworksBuildPhase section */
63 |
64 | /* Begin PBXGroup section */
65 | 321A2D601DA8635F0085E399 /* source */ = {
66 | isa = PBXGroup;
67 | children = (
68 | 321A2D611DA868550085E399 /* Endpoint.swift */,
69 | 321A2D631DA8689E0085E399 /* Client.swift */,
70 | );
71 | path = source;
72 | sourceTree = "";
73 | };
74 | 3285AB871CD019FE00350513 /* Raccoon */ = {
75 | isa = PBXGroup;
76 | children = (
77 | 3285AB881CD019FE00350513 /* Raccoon.h */,
78 | 3285AB8A1CD019FE00350513 /* Info.plist */,
79 | 321A2D601DA8635F0085E399 /* source */,
80 | );
81 | path = Raccoon;
82 | sourceTree = "";
83 | };
84 | 3285AB931CD019FE00350513 /* RaccoonTests */ = {
85 | isa = PBXGroup;
86 | children = (
87 | 3285AB961CD019FE00350513 /* Info.plist */,
88 | );
89 | path = RaccoonTests;
90 | sourceTree = "";
91 | };
92 | 32DDC7751CCFA95A008FC6D5 = {
93 | isa = PBXGroup;
94 | children = (
95 | 3285AB871CD019FE00350513 /* Raccoon */,
96 | 3285AB931CD019FE00350513 /* RaccoonTests */,
97 | 32DDC7801CCFA95A008FC6D5 /* Products */,
98 | 3B580E11B197CBE7BBDA8343 /* Pods */,
99 | C6FB965A3F157980BE818A12 /* Frameworks */,
100 | );
101 | sourceTree = "";
102 | };
103 | 32DDC7801CCFA95A008FC6D5 /* Products */ = {
104 | isa = PBXGroup;
105 | children = (
106 | 3285AB861CD019FE00350513 /* Raccoon.framework */,
107 | 3285AB8F1CD019FE00350513 /* RaccoonTests.xctest */,
108 | );
109 | name = Products;
110 | sourceTree = "";
111 | };
112 | 3B580E11B197CBE7BBDA8343 /* Pods */ = {
113 | isa = PBXGroup;
114 | children = (
115 | 7F1EB9E06C42FB77CF4402CA /* Pods-abstract_target-Raccoon.debug.xcconfig */,
116 | B6EECBC99055AAC5595AD492 /* Pods-abstract_target-Raccoon.release.xcconfig */,
117 | 6DEA79D492FB382729AC1680 /* Pods-abstract_target-RaccoonTests.debug.xcconfig */,
118 | 91B7B199F6351D14F5DBF877 /* Pods-abstract_target-RaccoonTests.release.xcconfig */,
119 | );
120 | name = Pods;
121 | sourceTree = "";
122 | };
123 | C6FB965A3F157980BE818A12 /* Frameworks */ = {
124 | isa = PBXGroup;
125 | children = (
126 | 2C46CCED049B6F1029FB6131 /* Pods_abstract_target_Raccoon.framework */,
127 | 711C0ADF627C4B11CBD0EDE4 /* Pods_abstract_target_RaccoonTests.framework */,
128 | );
129 | name = Frameworks;
130 | sourceTree = "";
131 | };
132 | /* End PBXGroup section */
133 |
134 | /* Begin PBXHeadersBuildPhase section */
135 | 3285AB831CD019FE00350513 /* Headers */ = {
136 | isa = PBXHeadersBuildPhase;
137 | buildActionMask = 2147483647;
138 | files = (
139 | 3285AB891CD019FE00350513 /* Raccoon.h in Headers */,
140 | );
141 | runOnlyForDeploymentPostprocessing = 0;
142 | };
143 | /* End PBXHeadersBuildPhase section */
144 |
145 | /* Begin PBXNativeTarget section */
146 | 3285AB851CD019FE00350513 /* Raccoon */ = {
147 | isa = PBXNativeTarget;
148 | buildConfigurationList = 3285AB971CD019FE00350513 /* Build configuration list for PBXNativeTarget "Raccoon" */;
149 | buildPhases = (
150 | 594AFE7DC578B0F927399F1F /* [CP] Check Pods Manifest.lock */,
151 | 3285AB811CD019FE00350513 /* Sources */,
152 | 3285AB821CD019FE00350513 /* Frameworks */,
153 | 3285AB831CD019FE00350513 /* Headers */,
154 | 3285AB841CD019FE00350513 /* Resources */,
155 | );
156 | buildRules = (
157 | );
158 | dependencies = (
159 | );
160 | name = Raccoon;
161 | productName = Raccoon;
162 | productReference = 3285AB861CD019FE00350513 /* Raccoon.framework */;
163 | productType = "com.apple.product-type.framework";
164 | };
165 | 3285AB8E1CD019FE00350513 /* RaccoonTests */ = {
166 | isa = PBXNativeTarget;
167 | buildConfigurationList = 3285AB9A1CD019FE00350513 /* Build configuration list for PBXNativeTarget "RaccoonTests" */;
168 | buildPhases = (
169 | 7D7CDA0AF0199FA86C8CF6A2 /* [CP] Check Pods Manifest.lock */,
170 | 3285AB8B1CD019FE00350513 /* Sources */,
171 | 3285AB8C1CD019FE00350513 /* Frameworks */,
172 | 3285AB8D1CD019FE00350513 /* Resources */,
173 | 2FECD4CAB4CA3B34F3F5375C /* [CP] Embed Pods Frameworks */,
174 | );
175 | buildRules = (
176 | );
177 | dependencies = (
178 | 3285AB921CD019FE00350513 /* PBXTargetDependency */,
179 | );
180 | name = RaccoonTests;
181 | productName = RaccoonTests;
182 | productReference = 3285AB8F1CD019FE00350513 /* RaccoonTests.xctest */;
183 | productType = "com.apple.product-type.bundle.unit-test";
184 | };
185 | /* End PBXNativeTarget section */
186 |
187 | /* Begin PBXProject section */
188 | 32DDC7761CCFA95A008FC6D5 /* Project object */ = {
189 | isa = PBXProject;
190 | attributes = {
191 | LastSwiftUpdateCheck = 0730;
192 | LastUpgradeCheck = 1000;
193 | ORGANIZATIONNAME = manuege;
194 | TargetAttributes = {
195 | 3285AB851CD019FE00350513 = {
196 | CreatedOnToolsVersion = 7.3;
197 | DevelopmentTeam = CF864KN2XE;
198 | LastSwiftMigration = 1000;
199 | ProvisioningStyle = Automatic;
200 | };
201 | 3285AB8E1CD019FE00350513 = {
202 | CreatedOnToolsVersion = 7.3;
203 | LastSwiftMigration = 0900;
204 | };
205 | };
206 | };
207 | buildConfigurationList = 32DDC7791CCFA95A008FC6D5 /* Build configuration list for PBXProject "raccoon" */;
208 | compatibilityVersion = "Xcode 3.2";
209 | developmentRegion = English;
210 | hasScannedForEncodings = 0;
211 | knownRegions = (
212 | en,
213 | );
214 | mainGroup = 32DDC7751CCFA95A008FC6D5;
215 | productRefGroup = 32DDC7801CCFA95A008FC6D5 /* Products */;
216 | projectDirPath = "";
217 | projectRoot = "";
218 | targets = (
219 | 3285AB851CD019FE00350513 /* Raccoon */,
220 | 3285AB8E1CD019FE00350513 /* RaccoonTests */,
221 | );
222 | };
223 | /* End PBXProject section */
224 |
225 | /* Begin PBXResourcesBuildPhase section */
226 | 3285AB841CD019FE00350513 /* Resources */ = {
227 | isa = PBXResourcesBuildPhase;
228 | buildActionMask = 2147483647;
229 | files = (
230 | );
231 | runOnlyForDeploymentPostprocessing = 0;
232 | };
233 | 3285AB8D1CD019FE00350513 /* Resources */ = {
234 | isa = PBXResourcesBuildPhase;
235 | buildActionMask = 2147483647;
236 | files = (
237 | );
238 | runOnlyForDeploymentPostprocessing = 0;
239 | };
240 | /* End PBXResourcesBuildPhase section */
241 |
242 | /* Begin PBXShellScriptBuildPhase section */
243 | 2FECD4CAB4CA3B34F3F5375C /* [CP] Embed Pods Frameworks */ = {
244 | isa = PBXShellScriptBuildPhase;
245 | buildActionMask = 2147483647;
246 | files = (
247 | );
248 | inputPaths = (
249 | "${SRCROOT}/Pods/Target Support Files/Pods-abstract_target-RaccoonTests/Pods-abstract_target-RaccoonTests-frameworks.sh",
250 | "${BUILT_PRODUCTS_DIR}/Alamofire/Alamofire.framework",
251 | "${BUILT_PRODUCTS_DIR}/AlamofireCoreData/AlamofireCoreData.framework",
252 | "${BUILT_PRODUCTS_DIR}/Groot/Groot.framework",
253 | "${BUILT_PRODUCTS_DIR}/PromiseKit/PromiseKit.framework",
254 | "${BUILT_PRODUCTS_DIR}/OHHTTPStubs/OHHTTPStubs.framework",
255 | );
256 | name = "[CP] Embed Pods Frameworks";
257 | outputPaths = (
258 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Alamofire.framework",
259 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AlamofireCoreData.framework",
260 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Groot.framework",
261 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/PromiseKit.framework",
262 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OHHTTPStubs.framework",
263 | );
264 | runOnlyForDeploymentPostprocessing = 0;
265 | shellPath = /bin/sh;
266 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-abstract_target-RaccoonTests/Pods-abstract_target-RaccoonTests-frameworks.sh\"\n";
267 | showEnvVarsInLog = 0;
268 | };
269 | 594AFE7DC578B0F927399F1F /* [CP] Check Pods Manifest.lock */ = {
270 | isa = PBXShellScriptBuildPhase;
271 | buildActionMask = 2147483647;
272 | files = (
273 | );
274 | inputPaths = (
275 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
276 | "${PODS_ROOT}/Manifest.lock",
277 | );
278 | name = "[CP] Check Pods Manifest.lock";
279 | outputPaths = (
280 | "$(DERIVED_FILE_DIR)/Pods-abstract_target-Raccoon-checkManifestLockResult.txt",
281 | );
282 | runOnlyForDeploymentPostprocessing = 0;
283 | shellPath = /bin/sh;
284 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
285 | showEnvVarsInLog = 0;
286 | };
287 | 7D7CDA0AF0199FA86C8CF6A2 /* [CP] Check Pods Manifest.lock */ = {
288 | isa = PBXShellScriptBuildPhase;
289 | buildActionMask = 2147483647;
290 | files = (
291 | );
292 | inputPaths = (
293 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
294 | "${PODS_ROOT}/Manifest.lock",
295 | );
296 | name = "[CP] Check Pods Manifest.lock";
297 | outputPaths = (
298 | "$(DERIVED_FILE_DIR)/Pods-abstract_target-RaccoonTests-checkManifestLockResult.txt",
299 | );
300 | runOnlyForDeploymentPostprocessing = 0;
301 | shellPath = /bin/sh;
302 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
303 | showEnvVarsInLog = 0;
304 | };
305 | /* End PBXShellScriptBuildPhase section */
306 |
307 | /* Begin PBXSourcesBuildPhase section */
308 | 3285AB811CD019FE00350513 /* Sources */ = {
309 | isa = PBXSourcesBuildPhase;
310 | buildActionMask = 2147483647;
311 | files = (
312 | 321A2D641DA8689E0085E399 /* Client.swift in Sources */,
313 | 321A2D621DA868550085E399 /* Endpoint.swift in Sources */,
314 | );
315 | runOnlyForDeploymentPostprocessing = 0;
316 | };
317 | 3285AB8B1CD019FE00350513 /* Sources */ = {
318 | isa = PBXSourcesBuildPhase;
319 | buildActionMask = 2147483647;
320 | files = (
321 | );
322 | runOnlyForDeploymentPostprocessing = 0;
323 | };
324 | /* End PBXSourcesBuildPhase section */
325 |
326 | /* Begin PBXTargetDependency section */
327 | 3285AB921CD019FE00350513 /* PBXTargetDependency */ = {
328 | isa = PBXTargetDependency;
329 | target = 3285AB851CD019FE00350513 /* Raccoon */;
330 | targetProxy = 3285AB911CD019FE00350513 /* PBXContainerItemProxy */;
331 | };
332 | /* End PBXTargetDependency section */
333 |
334 | /* Begin XCBuildConfiguration section */
335 | 3285AB981CD019FE00350513 /* Debug */ = {
336 | isa = XCBuildConfiguration;
337 | baseConfigurationReference = 7F1EB9E06C42FB77CF4402CA /* Pods-abstract_target-Raccoon.debug.xcconfig */;
338 | buildSettings = {
339 | CLANG_ENABLE_MODULES = YES;
340 | CODE_SIGN_IDENTITY = "iPhone Developer";
341 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
342 | CODE_SIGN_STYLE = Automatic;
343 | DEFINES_MODULE = YES;
344 | DEVELOPMENT_TEAM = CF864KN2XE;
345 | DYLIB_COMPATIBILITY_VERSION = 1;
346 | DYLIB_CURRENT_VERSION = 1;
347 | DYLIB_INSTALL_NAME_BASE = "@rpath";
348 | INFOPLIST_FILE = Raccoon/Info.plist;
349 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
350 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
351 | PRODUCT_BUNDLE_IDENTIFIER = com.manuege.Raccoon;
352 | PRODUCT_NAME = "$(TARGET_NAME)";
353 | PROVISIONING_PROFILE_SPECIFIER = "";
354 | SKIP_INSTALL = YES;
355 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
356 | SWIFT_SWIFT3_OBJC_INFERENCE = Default;
357 | SWIFT_VERSION = 4.2;
358 | };
359 | name = Debug;
360 | };
361 | 3285AB991CD019FE00350513 /* Release */ = {
362 | isa = XCBuildConfiguration;
363 | baseConfigurationReference = B6EECBC99055AAC5595AD492 /* Pods-abstract_target-Raccoon.release.xcconfig */;
364 | buildSettings = {
365 | CLANG_ENABLE_MODULES = YES;
366 | CODE_SIGN_IDENTITY = "iPhone Developer";
367 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
368 | CODE_SIGN_STYLE = Automatic;
369 | DEFINES_MODULE = YES;
370 | DEVELOPMENT_TEAM = CF864KN2XE;
371 | DYLIB_COMPATIBILITY_VERSION = 1;
372 | DYLIB_CURRENT_VERSION = 1;
373 | DYLIB_INSTALL_NAME_BASE = "@rpath";
374 | INFOPLIST_FILE = Raccoon/Info.plist;
375 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
376 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
377 | PRODUCT_BUNDLE_IDENTIFIER = com.manuege.Raccoon;
378 | PRODUCT_NAME = "$(TARGET_NAME)";
379 | PROVISIONING_PROFILE_SPECIFIER = "";
380 | SKIP_INSTALL = YES;
381 | SWIFT_SWIFT3_OBJC_INFERENCE = Default;
382 | SWIFT_VERSION = 4.2;
383 | };
384 | name = Release;
385 | };
386 | 3285AB9B1CD019FE00350513 /* Debug */ = {
387 | isa = XCBuildConfiguration;
388 | baseConfigurationReference = 6DEA79D492FB382729AC1680 /* Pods-abstract_target-RaccoonTests.debug.xcconfig */;
389 | buildSettings = {
390 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(inherited)";
391 | CLANG_ENABLE_MODULES = YES;
392 | INFOPLIST_FILE = RaccoonTests/Info.plist;
393 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
394 | PRODUCT_BUNDLE_IDENTIFIER = com.manuege.RaccoonTests;
395 | PRODUCT_NAME = "$(TARGET_NAME)";
396 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
397 | SWIFT_SWIFT3_OBJC_INFERENCE = On;
398 | SWIFT_VERSION = 4.0;
399 | };
400 | name = Debug;
401 | };
402 | 3285AB9C1CD019FE00350513 /* Release */ = {
403 | isa = XCBuildConfiguration;
404 | baseConfigurationReference = 91B7B199F6351D14F5DBF877 /* Pods-abstract_target-RaccoonTests.release.xcconfig */;
405 | buildSettings = {
406 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(inherited)";
407 | CLANG_ENABLE_MODULES = YES;
408 | INFOPLIST_FILE = RaccoonTests/Info.plist;
409 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
410 | PRODUCT_BUNDLE_IDENTIFIER = com.manuege.RaccoonTests;
411 | PRODUCT_NAME = "$(TARGET_NAME)";
412 | SWIFT_SWIFT3_OBJC_INFERENCE = On;
413 | SWIFT_VERSION = 4.0;
414 | };
415 | name = Release;
416 | };
417 | 32DDC7911CCFA95A008FC6D5 /* Debug */ = {
418 | isa = XCBuildConfiguration;
419 | buildSettings = {
420 | ALWAYS_SEARCH_USER_PATHS = NO;
421 | CLANG_ANALYZER_NONNULL = YES;
422 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
423 | CLANG_CXX_LIBRARY = "libc++";
424 | CLANG_ENABLE_MODULES = YES;
425 | CLANG_ENABLE_OBJC_ARC = YES;
426 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
427 | CLANG_WARN_BOOL_CONVERSION = YES;
428 | CLANG_WARN_COMMA = YES;
429 | CLANG_WARN_CONSTANT_CONVERSION = YES;
430 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
431 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
432 | CLANG_WARN_EMPTY_BODY = YES;
433 | CLANG_WARN_ENUM_CONVERSION = YES;
434 | CLANG_WARN_INFINITE_RECURSION = YES;
435 | CLANG_WARN_INT_CONVERSION = YES;
436 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
437 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
438 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
439 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
440 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
441 | CLANG_WARN_STRICT_PROTOTYPES = YES;
442 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
443 | CLANG_WARN_UNREACHABLE_CODE = YES;
444 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
445 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
446 | COPY_PHASE_STRIP = NO;
447 | CURRENT_PROJECT_VERSION = 1;
448 | DEBUG_INFORMATION_FORMAT = dwarf;
449 | ENABLE_STRICT_OBJC_MSGSEND = YES;
450 | ENABLE_TESTABILITY = YES;
451 | GCC_C_LANGUAGE_STANDARD = gnu99;
452 | GCC_DYNAMIC_NO_PIC = NO;
453 | GCC_NO_COMMON_BLOCKS = YES;
454 | GCC_OPTIMIZATION_LEVEL = 0;
455 | GCC_PREPROCESSOR_DEFINITIONS = (
456 | "DEBUG=1",
457 | "$(inherited)",
458 | );
459 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
460 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
461 | GCC_WARN_UNDECLARED_SELECTOR = YES;
462 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
463 | GCC_WARN_UNUSED_FUNCTION = YES;
464 | GCC_WARN_UNUSED_VARIABLE = YES;
465 | IPHONEOS_DEPLOYMENT_TARGET = 9.3;
466 | MTL_ENABLE_DEBUG_INFO = YES;
467 | ONLY_ACTIVE_ARCH = YES;
468 | SDKROOT = iphoneos;
469 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
470 | TARGETED_DEVICE_FAMILY = "1,2";
471 | VERSIONING_SYSTEM = "apple-generic";
472 | VERSION_INFO_PREFIX = "";
473 | };
474 | name = Debug;
475 | };
476 | 32DDC7921CCFA95A008FC6D5 /* Release */ = {
477 | isa = XCBuildConfiguration;
478 | buildSettings = {
479 | ALWAYS_SEARCH_USER_PATHS = NO;
480 | CLANG_ANALYZER_NONNULL = YES;
481 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
482 | CLANG_CXX_LIBRARY = "libc++";
483 | CLANG_ENABLE_MODULES = YES;
484 | CLANG_ENABLE_OBJC_ARC = YES;
485 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
486 | CLANG_WARN_BOOL_CONVERSION = YES;
487 | CLANG_WARN_COMMA = YES;
488 | CLANG_WARN_CONSTANT_CONVERSION = YES;
489 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
490 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
491 | CLANG_WARN_EMPTY_BODY = YES;
492 | CLANG_WARN_ENUM_CONVERSION = YES;
493 | CLANG_WARN_INFINITE_RECURSION = YES;
494 | CLANG_WARN_INT_CONVERSION = YES;
495 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
496 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
497 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
498 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
499 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
500 | CLANG_WARN_STRICT_PROTOTYPES = YES;
501 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
502 | CLANG_WARN_UNREACHABLE_CODE = YES;
503 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
504 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
505 | COPY_PHASE_STRIP = NO;
506 | CURRENT_PROJECT_VERSION = 1;
507 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
508 | ENABLE_NS_ASSERTIONS = NO;
509 | ENABLE_STRICT_OBJC_MSGSEND = YES;
510 | GCC_C_LANGUAGE_STANDARD = gnu99;
511 | GCC_NO_COMMON_BLOCKS = YES;
512 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
513 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
514 | GCC_WARN_UNDECLARED_SELECTOR = YES;
515 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
516 | GCC_WARN_UNUSED_FUNCTION = YES;
517 | GCC_WARN_UNUSED_VARIABLE = YES;
518 | IPHONEOS_DEPLOYMENT_TARGET = 9.3;
519 | MTL_ENABLE_DEBUG_INFO = NO;
520 | SDKROOT = iphoneos;
521 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
522 | TARGETED_DEVICE_FAMILY = "1,2";
523 | VALIDATE_PRODUCT = YES;
524 | VERSIONING_SYSTEM = "apple-generic";
525 | VERSION_INFO_PREFIX = "";
526 | };
527 | name = Release;
528 | };
529 | /* End XCBuildConfiguration section */
530 |
531 | /* Begin XCConfigurationList section */
532 | 3285AB971CD019FE00350513 /* Build configuration list for PBXNativeTarget "Raccoon" */ = {
533 | isa = XCConfigurationList;
534 | buildConfigurations = (
535 | 3285AB981CD019FE00350513 /* Debug */,
536 | 3285AB991CD019FE00350513 /* Release */,
537 | );
538 | defaultConfigurationIsVisible = 0;
539 | defaultConfigurationName = Release;
540 | };
541 | 3285AB9A1CD019FE00350513 /* Build configuration list for PBXNativeTarget "RaccoonTests" */ = {
542 | isa = XCConfigurationList;
543 | buildConfigurations = (
544 | 3285AB9B1CD019FE00350513 /* Debug */,
545 | 3285AB9C1CD019FE00350513 /* Release */,
546 | );
547 | defaultConfigurationIsVisible = 0;
548 | defaultConfigurationName = Release;
549 | };
550 | 32DDC7791CCFA95A008FC6D5 /* Build configuration list for PBXProject "raccoon" */ = {
551 | isa = XCConfigurationList;
552 | buildConfigurations = (
553 | 32DDC7911CCFA95A008FC6D5 /* Debug */,
554 | 32DDC7921CCFA95A008FC6D5 /* Release */,
555 | );
556 | defaultConfigurationIsVisible = 0;
557 | defaultConfigurationName = Release;
558 | };
559 | /* End XCConfigurationList section */
560 | };
561 | rootObject = 32DDC7761CCFA95A008FC6D5 /* Project object */;
562 | }
563 |
--------------------------------------------------------------------------------