├── Podfile ├── Pods ├── Alamofire │ ├── LICENSE │ ├── README.md │ └── Source │ │ ├── Alamofire.swift │ │ ├── Download.swift │ │ ├── Error.swift │ │ ├── Manager.swift │ │ ├── MultipartFormData.swift │ │ ├── ParameterEncoding.swift │ │ ├── Request.swift │ │ ├── Response.swift │ │ ├── ResponseSerialization.swift │ │ ├── Result.swift │ │ ├── ServerTrustPolicy.swift │ │ ├── Stream.swift │ │ ├── Upload.swift │ │ └── Validation.swift ├── Manifest.lock ├── Moya │ ├── License.md │ ├── Readme.md │ └── Source │ │ ├── Endpoint.swift │ │ ├── Error.swift │ │ ├── Image.swift │ │ ├── Moya.swift │ │ ├── Plugin.swift │ │ ├── Plugins │ │ ├── CredentialsPlugin.swift │ │ ├── NetworkActivityPlugin.swift │ │ └── NetworkLoggerPlugin.swift │ │ ├── Response.swift │ │ └── Result.swift ├── Pods.xcodeproj │ ├── project.pbxproj │ └── xcuserdata │ │ └── songlijun.xcuserdatad │ │ └── xcschemes │ │ ├── Alamofire.xcscheme │ │ ├── Moya.xcscheme │ │ ├── Pods.xcscheme │ │ └── xcschememanagement.plist └── Target Support Files │ ├── Alamofire │ ├── Alamofire-dummy.m │ ├── Alamofire-prefix.pch │ ├── Alamofire-umbrella.h │ ├── Alamofire.modulemap │ ├── Alamofire.xcconfig │ └── Info.plist │ ├── Moya │ ├── Info.plist │ ├── Moya-dummy.m │ ├── Moya-prefix.pch │ ├── Moya-umbrella.h │ ├── Moya.modulemap │ └── Moya.xcconfig │ └── Pods │ ├── Info.plist │ ├── Pods-acknowledgements.markdown │ ├── Pods-acknowledgements.plist │ ├── Pods-dummy.m │ ├── Pods-frameworks.sh │ ├── Pods-resources.sh │ ├── Pods-umbrella.h │ ├── Pods.debug.xcconfig │ ├── Pods.modulemap │ └── Pods.release.xcconfig ├── README.md ├── study_Moya.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── songlijun.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── songlijun.xcuserdatad │ └── xcschemes │ ├── study_Moya.xcscheme │ └── xcschememanagement.plist ├── study_Moya.xcworkspace ├── contents.xcworkspacedata └── xcuserdata │ └── songlijun.xcuserdatad │ ├── UserInterfaceState.xcuserstate │ └── xcdebugger │ └── Breakpoints_v2.xcbkptlist └── study_Moya ├── AppDelegate.swift ├── Assets.xcassets └── AppIcon.appiconset │ └── Contents.json ├── Base.lproj ├── LaunchScreen.storyboard └── Main.storyboard ├── DSAPI.swift ├── Info.plist ├── VideosTableViewController.swift └── ViewController.swift /Podfile: -------------------------------------------------------------------------------- 1 | source 'https://github.com/CocoaPods/Specs.git' 2 | 3 | use_frameworks! 4 | 5 | pod 'Moya' 6 | -------------------------------------------------------------------------------- /Pods/Alamofire/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014–2015 Alamofire Software Foundation (http://alamofire.org/) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Pods/Alamofire/Source/Alamofire.swift: -------------------------------------------------------------------------------- 1 | // Alamofire.swift 2 | // 3 | // Copyright (c) 2014–2015 Alamofire Software Foundation (http://alamofire.org/) 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 13 | // all 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 21 | // THE SOFTWARE. 22 | 23 | import Foundation 24 | 25 | // MARK: - URLStringConvertible 26 | 27 | /** 28 | Types adopting the `URLStringConvertible` protocol can be used to construct URL strings, which are then used to 29 | construct URL requests. 30 | */ 31 | public protocol URLStringConvertible { 32 | /** 33 | A URL that conforms to RFC 2396. 34 | 35 | Methods accepting a `URLStringConvertible` type parameter parse it according to RFCs 1738 and 1808. 36 | 37 | See https://tools.ietf.org/html/rfc2396 38 | See https://tools.ietf.org/html/rfc1738 39 | See https://tools.ietf.org/html/rfc1808 40 | */ 41 | var URLString: String { get } 42 | } 43 | 44 | extension String: URLStringConvertible { 45 | public var URLString: String { 46 | return self 47 | } 48 | } 49 | 50 | extension NSURL: URLStringConvertible { 51 | public var URLString: String { 52 | return absoluteString 53 | } 54 | } 55 | 56 | extension NSURLComponents: URLStringConvertible { 57 | public var URLString: String { 58 | return URL!.URLString 59 | } 60 | } 61 | 62 | extension NSURLRequest: URLStringConvertible { 63 | public var URLString: String { 64 | return URL!.URLString 65 | } 66 | } 67 | 68 | // MARK: - URLRequestConvertible 69 | 70 | /** 71 | Types adopting the `URLRequestConvertible` protocol can be used to construct URL requests. 72 | */ 73 | public protocol URLRequestConvertible { 74 | /// The URL request. 75 | var URLRequest: NSMutableURLRequest { get } 76 | } 77 | 78 | extension NSURLRequest: URLRequestConvertible { 79 | public var URLRequest: NSMutableURLRequest { 80 | return self.mutableCopy() as! NSMutableURLRequest 81 | } 82 | } 83 | 84 | // MARK: - Convenience 85 | 86 | func URLRequest( 87 | method: Method, 88 | _ URLString: URLStringConvertible, 89 | headers: [String: String]? = nil) 90 | -> NSMutableURLRequest 91 | { 92 | let mutableURLRequest = NSMutableURLRequest(URL: NSURL(string: URLString.URLString)!) 93 | mutableURLRequest.HTTPMethod = method.rawValue 94 | 95 | if let headers = headers { 96 | for (headerField, headerValue) in headers { 97 | mutableURLRequest.setValue(headerValue, forHTTPHeaderField: headerField) 98 | } 99 | } 100 | 101 | return mutableURLRequest 102 | } 103 | 104 | // MARK: - Request Methods 105 | 106 | /** 107 | Creates a request using the shared manager instance for the specified method, URL string, parameters, and 108 | parameter encoding. 109 | 110 | - parameter method: The HTTP method. 111 | - parameter URLString: The URL string. 112 | - parameter parameters: The parameters. `nil` by default. 113 | - parameter encoding: The parameter encoding. `.URL` by default. 114 | - parameter headers: The HTTP headers. `nil` by default. 115 | 116 | - returns: The created request. 117 | */ 118 | public func request( 119 | method: Method, 120 | _ URLString: URLStringConvertible, 121 | parameters: [String: AnyObject]? = nil, 122 | encoding: ParameterEncoding = .URL, 123 | headers: [String: String]? = nil) 124 | -> Request 125 | { 126 | return Manager.sharedInstance.request( 127 | method, 128 | URLString, 129 | parameters: parameters, 130 | encoding: encoding, 131 | headers: headers 132 | ) 133 | } 134 | 135 | /** 136 | Creates a request using the shared manager instance for the specified URL request. 137 | 138 | If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. 139 | 140 | - parameter URLRequest: The URL request 141 | 142 | - returns: The created request. 143 | */ 144 | public func request(URLRequest: URLRequestConvertible) -> Request { 145 | return Manager.sharedInstance.request(URLRequest.URLRequest) 146 | } 147 | 148 | // MARK: - Upload Methods 149 | 150 | // MARK: File 151 | 152 | /** 153 | Creates an upload request using the shared manager instance for the specified method, URL string, and file. 154 | 155 | - parameter method: The HTTP method. 156 | - parameter URLString: The URL string. 157 | - parameter headers: The HTTP headers. `nil` by default. 158 | - parameter file: The file to upload. 159 | 160 | - returns: The created upload request. 161 | */ 162 | public func upload( 163 | method: Method, 164 | _ URLString: URLStringConvertible, 165 | headers: [String: String]? = nil, 166 | file: NSURL) 167 | -> Request 168 | { 169 | return Manager.sharedInstance.upload(method, URLString, headers: headers, file: file) 170 | } 171 | 172 | /** 173 | Creates an upload request using the shared manager instance for the specified URL request and file. 174 | 175 | - parameter URLRequest: The URL request. 176 | - parameter file: The file to upload. 177 | 178 | - returns: The created upload request. 179 | */ 180 | public func upload(URLRequest: URLRequestConvertible, file: NSURL) -> Request { 181 | return Manager.sharedInstance.upload(URLRequest, file: file) 182 | } 183 | 184 | // MARK: Data 185 | 186 | /** 187 | Creates an upload request using the shared manager instance for the specified method, URL string, and data. 188 | 189 | - parameter method: The HTTP method. 190 | - parameter URLString: The URL string. 191 | - parameter headers: The HTTP headers. `nil` by default. 192 | - parameter data: The data to upload. 193 | 194 | - returns: The created upload request. 195 | */ 196 | public func upload( 197 | method: Method, 198 | _ URLString: URLStringConvertible, 199 | headers: [String: String]? = nil, 200 | data: NSData) 201 | -> Request 202 | { 203 | return Manager.sharedInstance.upload(method, URLString, headers: headers, data: data) 204 | } 205 | 206 | /** 207 | Creates an upload request using the shared manager instance for the specified URL request and data. 208 | 209 | - parameter URLRequest: The URL request. 210 | - parameter data: The data to upload. 211 | 212 | - returns: The created upload request. 213 | */ 214 | public func upload(URLRequest: URLRequestConvertible, data: NSData) -> Request { 215 | return Manager.sharedInstance.upload(URLRequest, data: data) 216 | } 217 | 218 | // MARK: Stream 219 | 220 | /** 221 | Creates an upload request using the shared manager instance for the specified method, URL string, and stream. 222 | 223 | - parameter method: The HTTP method. 224 | - parameter URLString: The URL string. 225 | - parameter headers: The HTTP headers. `nil` by default. 226 | - parameter stream: The stream to upload. 227 | 228 | - returns: The created upload request. 229 | */ 230 | public func upload( 231 | method: Method, 232 | _ URLString: URLStringConvertible, 233 | headers: [String: String]? = nil, 234 | stream: NSInputStream) 235 | -> Request 236 | { 237 | return Manager.sharedInstance.upload(method, URLString, headers: headers, stream: stream) 238 | } 239 | 240 | /** 241 | Creates an upload request using the shared manager instance for the specified URL request and stream. 242 | 243 | - parameter URLRequest: The URL request. 244 | - parameter stream: The stream to upload. 245 | 246 | - returns: The created upload request. 247 | */ 248 | public func upload(URLRequest: URLRequestConvertible, stream: NSInputStream) -> Request { 249 | return Manager.sharedInstance.upload(URLRequest, stream: stream) 250 | } 251 | 252 | // MARK: MultipartFormData 253 | 254 | /** 255 | Creates an upload request using the shared manager instance for the specified method and URL string. 256 | 257 | - parameter method: The HTTP method. 258 | - parameter URLString: The URL string. 259 | - parameter headers: The HTTP headers. `nil` by default. 260 | - parameter multipartFormData: The closure used to append body parts to the `MultipartFormData`. 261 | - parameter encodingMemoryThreshold: The encoding memory threshold in bytes. 262 | `MultipartFormDataEncodingMemoryThreshold` by default. 263 | - parameter encodingCompletion: The closure called when the `MultipartFormData` encoding is complete. 264 | */ 265 | public func upload( 266 | method: Method, 267 | _ URLString: URLStringConvertible, 268 | headers: [String: String]? = nil, 269 | multipartFormData: MultipartFormData -> Void, 270 | encodingMemoryThreshold: UInt64 = Manager.MultipartFormDataEncodingMemoryThreshold, 271 | encodingCompletion: (Manager.MultipartFormDataEncodingResult -> Void)?) 272 | { 273 | return Manager.sharedInstance.upload( 274 | method, 275 | URLString, 276 | headers: headers, 277 | multipartFormData: multipartFormData, 278 | encodingMemoryThreshold: encodingMemoryThreshold, 279 | encodingCompletion: encodingCompletion 280 | ) 281 | } 282 | 283 | /** 284 | Creates an upload request using the shared manager instance for the specified method and URL string. 285 | 286 | - parameter URLRequest: The URL request. 287 | - parameter multipartFormData: The closure used to append body parts to the `MultipartFormData`. 288 | - parameter encodingMemoryThreshold: The encoding memory threshold in bytes. 289 | `MultipartFormDataEncodingMemoryThreshold` by default. 290 | - parameter encodingCompletion: The closure called when the `MultipartFormData` encoding is complete. 291 | */ 292 | public func upload( 293 | URLRequest: URLRequestConvertible, 294 | multipartFormData: MultipartFormData -> Void, 295 | encodingMemoryThreshold: UInt64 = Manager.MultipartFormDataEncodingMemoryThreshold, 296 | encodingCompletion: (Manager.MultipartFormDataEncodingResult -> Void)?) 297 | { 298 | return Manager.sharedInstance.upload( 299 | URLRequest, 300 | multipartFormData: multipartFormData, 301 | encodingMemoryThreshold: encodingMemoryThreshold, 302 | encodingCompletion: encodingCompletion 303 | ) 304 | } 305 | 306 | // MARK: - Download Methods 307 | 308 | // MARK: URL Request 309 | 310 | /** 311 | Creates a download request using the shared manager instance for the specified method and URL string. 312 | 313 | - parameter method: The HTTP method. 314 | - parameter URLString: The URL string. 315 | - parameter parameters: The parameters. `nil` by default. 316 | - parameter encoding: The parameter encoding. `.URL` by default. 317 | - parameter headers: The HTTP headers. `nil` by default. 318 | - parameter destination: The closure used to determine the destination of the downloaded file. 319 | 320 | - returns: The created download request. 321 | */ 322 | public func download( 323 | method: Method, 324 | _ URLString: URLStringConvertible, 325 | parameters: [String: AnyObject]? = nil, 326 | encoding: ParameterEncoding = .URL, 327 | headers: [String: String]? = nil, 328 | destination: Request.DownloadFileDestination) 329 | -> Request 330 | { 331 | return Manager.sharedInstance.download( 332 | method, 333 | URLString, 334 | parameters: parameters, 335 | encoding: encoding, 336 | headers: headers, 337 | destination: destination 338 | ) 339 | } 340 | 341 | /** 342 | Creates a download request using the shared manager instance for the specified URL request. 343 | 344 | - parameter URLRequest: The URL request. 345 | - parameter destination: The closure used to determine the destination of the downloaded file. 346 | 347 | - returns: The created download request. 348 | */ 349 | public func download(URLRequest: URLRequestConvertible, destination: Request.DownloadFileDestination) -> Request { 350 | return Manager.sharedInstance.download(URLRequest, destination: destination) 351 | } 352 | 353 | // MARK: Resume Data 354 | 355 | /** 356 | Creates a request using the shared manager instance for downloading from the resume data produced from a 357 | previous request cancellation. 358 | 359 | - parameter resumeData: The resume data. This is an opaque data blob produced by `NSURLSessionDownloadTask` 360 | when a task is cancelled. See `NSURLSession -downloadTaskWithResumeData:` for additional 361 | information. 362 | - parameter destination: The closure used to determine the destination of the downloaded file. 363 | 364 | - returns: The created download request. 365 | */ 366 | public func download(resumeData data: NSData, destination: Request.DownloadFileDestination) -> Request { 367 | return Manager.sharedInstance.download(data, destination: destination) 368 | } 369 | -------------------------------------------------------------------------------- /Pods/Alamofire/Source/Download.swift: -------------------------------------------------------------------------------- 1 | // Download.swift 2 | // 3 | // Copyright (c) 2014–2015 Alamofire Software Foundation (http://alamofire.org/) 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 13 | // all 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 21 | // THE SOFTWARE. 22 | 23 | import Foundation 24 | 25 | extension Manager { 26 | private enum Downloadable { 27 | case Request(NSURLRequest) 28 | case ResumeData(NSData) 29 | } 30 | 31 | private func download(downloadable: Downloadable, destination: Request.DownloadFileDestination) -> Request { 32 | var downloadTask: NSURLSessionDownloadTask! 33 | 34 | switch downloadable { 35 | case .Request(let request): 36 | dispatch_sync(queue) { 37 | downloadTask = self.session.downloadTaskWithRequest(request) 38 | } 39 | case .ResumeData(let resumeData): 40 | dispatch_sync(queue) { 41 | downloadTask = self.session.downloadTaskWithResumeData(resumeData) 42 | } 43 | } 44 | 45 | let request = Request(session: session, task: downloadTask) 46 | 47 | if let downloadDelegate = request.delegate as? Request.DownloadTaskDelegate { 48 | downloadDelegate.downloadTaskDidFinishDownloadingToURL = { session, downloadTask, URL in 49 | return destination(URL, downloadTask.response as! NSHTTPURLResponse) 50 | } 51 | } 52 | 53 | delegate[request.delegate.task] = request.delegate 54 | 55 | if startRequestsImmediately { 56 | request.resume() 57 | } 58 | 59 | return request 60 | } 61 | 62 | // MARK: Request 63 | 64 | /** 65 | Creates a download request for the specified method, URL string, parameters, parameter encoding, headers 66 | and destination. 67 | 68 | If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. 69 | 70 | - parameter method: The HTTP method. 71 | - parameter URLString: The URL string. 72 | - parameter parameters: The parameters. `nil` by default. 73 | - parameter encoding: The parameter encoding. `.URL` by default. 74 | - parameter headers: The HTTP headers. `nil` by default. 75 | - parameter destination: The closure used to determine the destination of the downloaded file. 76 | 77 | - returns: The created download request. 78 | */ 79 | public func download( 80 | method: Method, 81 | _ URLString: URLStringConvertible, 82 | parameters: [String: AnyObject]? = nil, 83 | encoding: ParameterEncoding = .URL, 84 | headers: [String: String]? = nil, 85 | destination: Request.DownloadFileDestination) 86 | -> Request 87 | { 88 | let mutableURLRequest = URLRequest(method, URLString, headers: headers) 89 | let encodedURLRequest = encoding.encode(mutableURLRequest, parameters: parameters).0 90 | 91 | return download(encodedURLRequest, destination: destination) 92 | } 93 | 94 | /** 95 | Creates a request for downloading from the specified URL request. 96 | 97 | If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. 98 | 99 | - parameter URLRequest: The URL request 100 | - parameter destination: The closure used to determine the destination of the downloaded file. 101 | 102 | - returns: The created download request. 103 | */ 104 | public func download(URLRequest: URLRequestConvertible, destination: Request.DownloadFileDestination) -> Request { 105 | return download(.Request(URLRequest.URLRequest), destination: destination) 106 | } 107 | 108 | // MARK: Resume Data 109 | 110 | /** 111 | Creates a request for downloading from the resume data produced from a previous request cancellation. 112 | 113 | If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. 114 | 115 | - parameter resumeData: The resume data. This is an opaque data blob produced by `NSURLSessionDownloadTask` 116 | when a task is cancelled. See `NSURLSession -downloadTaskWithResumeData:` for 117 | additional information. 118 | - parameter destination: The closure used to determine the destination of the downloaded file. 119 | 120 | - returns: The created download request. 121 | */ 122 | public func download(resumeData: NSData, destination: Request.DownloadFileDestination) -> Request { 123 | return download(.ResumeData(resumeData), destination: destination) 124 | } 125 | } 126 | 127 | // MARK: - 128 | 129 | extension Request { 130 | /** 131 | A closure executed once a request has successfully completed in order to determine where to move the temporary 132 | file written to during the download process. The closure takes two arguments: the temporary file URL and the URL 133 | response, and returns a single argument: the file URL where the temporary file should be moved. 134 | */ 135 | public typealias DownloadFileDestination = (NSURL, NSHTTPURLResponse) -> NSURL 136 | 137 | /** 138 | Creates a download file destination closure which uses the default file manager to move the temporary file to a 139 | file URL in the first available directory with the specified search path directory and search path domain mask. 140 | 141 | - parameter directory: The search path directory. `.DocumentDirectory` by default. 142 | - parameter domain: The search path domain mask. `.UserDomainMask` by default. 143 | 144 | - returns: A download file destination closure. 145 | */ 146 | public class func suggestedDownloadDestination( 147 | directory directory: NSSearchPathDirectory = .DocumentDirectory, 148 | domain: NSSearchPathDomainMask = .UserDomainMask) 149 | -> DownloadFileDestination 150 | { 151 | return { temporaryURL, response -> NSURL in 152 | let directoryURLs = NSFileManager.defaultManager().URLsForDirectory(directory, inDomains: domain) 153 | 154 | if !directoryURLs.isEmpty { 155 | return directoryURLs[0].URLByAppendingPathComponent(response.suggestedFilename!) 156 | } 157 | 158 | return temporaryURL 159 | } 160 | } 161 | 162 | /// The resume data of the underlying download task if available after a failure. 163 | public var resumeData: NSData? { 164 | var data: NSData? 165 | 166 | if let delegate = delegate as? DownloadTaskDelegate { 167 | data = delegate.resumeData 168 | } 169 | 170 | return data 171 | } 172 | 173 | // MARK: - DownloadTaskDelegate 174 | 175 | class DownloadTaskDelegate: TaskDelegate, NSURLSessionDownloadDelegate { 176 | var downloadTask: NSURLSessionDownloadTask? { return task as? NSURLSessionDownloadTask } 177 | var downloadProgress: ((Int64, Int64, Int64) -> Void)? 178 | 179 | var resumeData: NSData? 180 | override var data: NSData? { return resumeData } 181 | 182 | // MARK: - NSURLSessionDownloadDelegate 183 | 184 | // MARK: Override Closures 185 | 186 | var downloadTaskDidFinishDownloadingToURL: ((NSURLSession, NSURLSessionDownloadTask, NSURL) -> NSURL)? 187 | var downloadTaskDidWriteData: ((NSURLSession, NSURLSessionDownloadTask, Int64, Int64, Int64) -> Void)? 188 | var downloadTaskDidResumeAtOffset: ((NSURLSession, NSURLSessionDownloadTask, Int64, Int64) -> Void)? 189 | 190 | // MARK: Delegate Methods 191 | 192 | func URLSession( 193 | session: NSURLSession, 194 | downloadTask: NSURLSessionDownloadTask, 195 | didFinishDownloadingToURL location: NSURL) 196 | { 197 | if let downloadTaskDidFinishDownloadingToURL = downloadTaskDidFinishDownloadingToURL { 198 | do { 199 | let destination = downloadTaskDidFinishDownloadingToURL(session, downloadTask, location) 200 | try NSFileManager.defaultManager().moveItemAtURL(location, toURL: destination) 201 | } catch { 202 | self.error = error as NSError 203 | } 204 | } 205 | } 206 | 207 | func URLSession( 208 | session: NSURLSession, 209 | downloadTask: NSURLSessionDownloadTask, 210 | didWriteData bytesWritten: Int64, 211 | totalBytesWritten: Int64, 212 | totalBytesExpectedToWrite: Int64) 213 | { 214 | if let downloadTaskDidWriteData = downloadTaskDidWriteData { 215 | downloadTaskDidWriteData( 216 | session, 217 | downloadTask, 218 | bytesWritten, 219 | totalBytesWritten, 220 | totalBytesExpectedToWrite 221 | ) 222 | } else { 223 | progress.totalUnitCount = totalBytesExpectedToWrite 224 | progress.completedUnitCount = totalBytesWritten 225 | 226 | downloadProgress?(bytesWritten, totalBytesWritten, totalBytesExpectedToWrite) 227 | } 228 | } 229 | 230 | func URLSession( 231 | session: NSURLSession, 232 | downloadTask: NSURLSessionDownloadTask, 233 | didResumeAtOffset fileOffset: Int64, 234 | expectedTotalBytes: Int64) 235 | { 236 | if let downloadTaskDidResumeAtOffset = downloadTaskDidResumeAtOffset { 237 | downloadTaskDidResumeAtOffset(session, downloadTask, fileOffset, expectedTotalBytes) 238 | } else { 239 | progress.totalUnitCount = expectedTotalBytes 240 | progress.completedUnitCount = fileOffset 241 | } 242 | } 243 | } 244 | } 245 | -------------------------------------------------------------------------------- /Pods/Alamofire/Source/Error.swift: -------------------------------------------------------------------------------- 1 | // Error.swift 2 | // 3 | // Copyright (c) 2014–2015 Alamofire Software Foundation (http://alamofire.org/) 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 13 | // all 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 21 | // THE SOFTWARE. 22 | 23 | import Foundation 24 | 25 | /// The `Error` struct provides a convenience for creating custom Alamofire NSErrors. 26 | public struct Error { 27 | /// The domain used for creating all Alamofire errors. 28 | public static let Domain = "com.alamofire.error" 29 | 30 | /// The custom error codes generated by Alamofire. 31 | public enum Code: Int { 32 | case InputStreamReadFailed = -6000 33 | case OutputStreamWriteFailed = -6001 34 | case ContentTypeValidationFailed = -6002 35 | case StatusCodeValidationFailed = -6003 36 | case DataSerializationFailed = -6004 37 | case StringSerializationFailed = -6005 38 | case JSONSerializationFailed = -6006 39 | case PropertyListSerializationFailed = -6007 40 | } 41 | 42 | /** 43 | Creates an `NSError` with the given error code and failure reason. 44 | 45 | - parameter code: The error code. 46 | - parameter failureReason: The failure reason. 47 | 48 | - returns: An `NSError` with the given error code and failure reason. 49 | */ 50 | public static func errorWithCode(code: Code, failureReason: String) -> NSError { 51 | return errorWithCode(code.rawValue, failureReason: failureReason) 52 | } 53 | 54 | /** 55 | Creates an `NSError` with the given error code and failure reason. 56 | 57 | - parameter code: The error code. 58 | - parameter failureReason: The failure reason. 59 | 60 | - returns: An `NSError` with the given error code and failure reason. 61 | */ 62 | public static func errorWithCode(code: Int, failureReason: String) -> NSError { 63 | let userInfo = [NSLocalizedFailureReasonErrorKey: failureReason] 64 | return NSError(domain: Domain, code: code, userInfo: userInfo) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Pods/Alamofire/Source/ParameterEncoding.swift: -------------------------------------------------------------------------------- 1 | // ParameterEncoding.swift 2 | // 3 | // Copyright (c) 2014–2015 Alamofire Software Foundation (http://alamofire.org/) 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 13 | // all 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 21 | // THE SOFTWARE. 22 | 23 | import Foundation 24 | 25 | /** 26 | HTTP method definitions. 27 | 28 | See https://tools.ietf.org/html/rfc7231#section-4.3 29 | */ 30 | public enum Method: String { 31 | case OPTIONS, GET, HEAD, POST, PUT, PATCH, DELETE, TRACE, CONNECT 32 | } 33 | 34 | // MARK: ParameterEncoding 35 | 36 | /** 37 | Used to specify the way in which a set of parameters are applied to a URL request. 38 | 39 | - `URL`: Creates a query string to be set as or appended to any existing URL query for `GET`, `HEAD`, 40 | and `DELETE` requests, or set as the body for requests with any other HTTP method. The 41 | `Content-Type` HTTP header field of an encoded request with HTTP body is set to 42 | `application/x-www-form-urlencoded; charset=utf-8`. Since there is no published specification 43 | for how to encode collection types, the convention of appending `[]` to the key for array 44 | values (`foo[]=1&foo[]=2`), and appending the key surrounded by square brackets for nested 45 | dictionary values (`foo[bar]=baz`). 46 | 47 | - `URLEncodedInURL`: Creates query string to be set as or appended to any existing URL query. Uses the same 48 | implementation as the `.URL` case, but always applies the encoded result to the URL. 49 | 50 | - `JSON`: Uses `NSJSONSerialization` to create a JSON representation of the parameters object, which is 51 | set as the body of the request. The `Content-Type` HTTP header field of an encoded request is 52 | set to `application/json`. 53 | 54 | - `PropertyList`: Uses `NSPropertyListSerialization` to create a plist representation of the parameters object, 55 | according to the associated format and write options values, which is set as the body of the 56 | request. The `Content-Type` HTTP header field of an encoded request is set to 57 | `application/x-plist`. 58 | 59 | - `Custom`: Uses the associated closure value to construct a new request given an existing request and 60 | parameters. 61 | */ 62 | public enum ParameterEncoding { 63 | case URL 64 | case URLEncodedInURL 65 | case JSON 66 | case PropertyList(NSPropertyListFormat, NSPropertyListWriteOptions) 67 | case Custom((URLRequestConvertible, [String: AnyObject]?) -> (NSMutableURLRequest, NSError?)) 68 | 69 | /** 70 | Creates a URL request by encoding parameters and applying them onto an existing request. 71 | 72 | - parameter URLRequest: The request to have parameters applied 73 | - parameter parameters: The parameters to apply 74 | 75 | - returns: A tuple containing the constructed request and the error that occurred during parameter encoding, 76 | if any. 77 | */ 78 | public func encode( 79 | URLRequest: URLRequestConvertible, 80 | parameters: [String: AnyObject]?) 81 | -> (NSMutableURLRequest, NSError?) 82 | { 83 | var mutableURLRequest = URLRequest.URLRequest 84 | 85 | guard let parameters = parameters else { 86 | return (mutableURLRequest, nil) 87 | } 88 | 89 | var encodingError: NSError? = nil 90 | 91 | switch self { 92 | case .URL, .URLEncodedInURL: 93 | func query(parameters: [String: AnyObject]) -> String { 94 | var components: [(String, String)] = [] 95 | 96 | for key in parameters.keys.sort(<) { 97 | let value = parameters[key]! 98 | components += queryComponents(key, value) 99 | } 100 | 101 | return (components.map { "\($0)=\($1)" } as [String]).joinWithSeparator("&") 102 | } 103 | 104 | func encodesParametersInURL(method: Method) -> Bool { 105 | switch self { 106 | case .URLEncodedInURL: 107 | return true 108 | default: 109 | break 110 | } 111 | 112 | switch method { 113 | case .GET, .HEAD, .DELETE: 114 | return true 115 | default: 116 | return false 117 | } 118 | } 119 | 120 | if let method = Method(rawValue: mutableURLRequest.HTTPMethod) where encodesParametersInURL(method) { 121 | if let URLComponents = NSURLComponents(URL: mutableURLRequest.URL!, resolvingAgainstBaseURL: false) { 122 | let percentEncodedQuery = (URLComponents.percentEncodedQuery.map { $0 + "&" } ?? "") + query(parameters) 123 | URLComponents.percentEncodedQuery = percentEncodedQuery 124 | mutableURLRequest.URL = URLComponents.URL 125 | } 126 | } else { 127 | if mutableURLRequest.valueForHTTPHeaderField("Content-Type") == nil { 128 | mutableURLRequest.setValue( 129 | "application/x-www-form-urlencoded; charset=utf-8", 130 | forHTTPHeaderField: "Content-Type" 131 | ) 132 | } 133 | 134 | mutableURLRequest.HTTPBody = query(parameters).dataUsingEncoding( 135 | NSUTF8StringEncoding, 136 | allowLossyConversion: false 137 | ) 138 | } 139 | case .JSON: 140 | do { 141 | let options = NSJSONWritingOptions() 142 | let data = try NSJSONSerialization.dataWithJSONObject(parameters, options: options) 143 | 144 | mutableURLRequest.setValue("application/json", forHTTPHeaderField: "Content-Type") 145 | mutableURLRequest.HTTPBody = data 146 | } catch { 147 | encodingError = error as NSError 148 | } 149 | case .PropertyList(let format, let options): 150 | do { 151 | let data = try NSPropertyListSerialization.dataWithPropertyList( 152 | parameters, 153 | format: format, 154 | options: options 155 | ) 156 | mutableURLRequest.setValue("application/x-plist", forHTTPHeaderField: "Content-Type") 157 | mutableURLRequest.HTTPBody = data 158 | } catch { 159 | encodingError = error as NSError 160 | } 161 | case .Custom(let closure): 162 | (mutableURLRequest, encodingError) = closure(mutableURLRequest, parameters) 163 | } 164 | 165 | return (mutableURLRequest, encodingError) 166 | } 167 | 168 | /** 169 | Creates percent-escaped, URL encoded query string components from the given key-value pair using recursion. 170 | 171 | - parameter key: The key of the query component. 172 | - parameter value: The value of the query component. 173 | 174 | - returns: The percent-escaped, URL encoded query string components. 175 | */ 176 | public func queryComponents(key: String, _ value: AnyObject) -> [(String, String)] { 177 | var components: [(String, String)] = [] 178 | 179 | if let dictionary = value as? [String: AnyObject] { 180 | for (nestedKey, value) in dictionary { 181 | components += queryComponents("\(key)[\(nestedKey)]", value) 182 | } 183 | } else if let array = value as? [AnyObject] { 184 | for value in array { 185 | components += queryComponents("\(key)[]", value) 186 | } 187 | } else { 188 | components.append((escape(key), escape("\(value)"))) 189 | } 190 | 191 | return components 192 | } 193 | 194 | /** 195 | Returns a percent-escaped string following RFC 3986 for a query string key or value. 196 | 197 | RFC 3986 states that the following characters are "reserved" characters. 198 | 199 | - General Delimiters: ":", "#", "[", "]", "@", "?", "/" 200 | - Sub-Delimiters: "!", "$", "&", "'", "(", ")", "*", "+", ",", ";", "=" 201 | 202 | In RFC 3986 - Section 3.4, it states that the "?" and "/" characters should not be escaped to allow 203 | query strings to include a URL. Therefore, all "reserved" characters with the exception of "?" and "/" 204 | should be percent-escaped in the query string. 205 | 206 | - parameter string: The string to be percent-escaped. 207 | 208 | - returns: The percent-escaped string. 209 | */ 210 | public func escape(string: String) -> String { 211 | let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4 212 | let subDelimitersToEncode = "!$&'()*+,;=" 213 | 214 | let allowedCharacterSet = NSCharacterSet.URLQueryAllowedCharacterSet().mutableCopy() as! NSMutableCharacterSet 215 | allowedCharacterSet.removeCharactersInString(generalDelimitersToEncode + subDelimitersToEncode) 216 | 217 | var escaped = "" 218 | 219 | //========================================================================================================== 220 | // 221 | // Batching is required for escaping due to an internal bug in iOS 8.1 and 8.2. Encoding more than a few 222 | // hundred Chinense characters causes various malloc error crashes. To avoid this issue until iOS 8 is no 223 | // longer supported, batching MUST be used for encoding. This introduces roughly a 20% overhead. For more 224 | // info, please refer to: 225 | // 226 | // - https://github.com/Alamofire/Alamofire/issues/206 227 | // 228 | //========================================================================================================== 229 | 230 | if #available(iOS 8.3, OSX 10.10, *) { 231 | escaped = string.stringByAddingPercentEncodingWithAllowedCharacters(allowedCharacterSet) ?? string 232 | } else { 233 | let batchSize = 50 234 | var index = string.startIndex 235 | 236 | while index != string.endIndex { 237 | let startIndex = index 238 | let endIndex = index.advancedBy(batchSize, limit: string.endIndex) 239 | let range = Range(start: startIndex, end: endIndex) 240 | 241 | let substring = string.substringWithRange(range) 242 | 243 | escaped += substring.stringByAddingPercentEncodingWithAllowedCharacters(allowedCharacterSet) ?? substring 244 | 245 | index = endIndex 246 | } 247 | } 248 | 249 | return escaped 250 | } 251 | } 252 | -------------------------------------------------------------------------------- /Pods/Alamofire/Source/Response.swift: -------------------------------------------------------------------------------- 1 | // Response.swift 2 | // 3 | // Copyright (c) 2014–2015 Alamofire Software Foundation (http://alamofire.org/) 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 13 | // all 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 21 | // THE SOFTWARE. 22 | 23 | import Foundation 24 | 25 | /// Used to store all response data returned from a completed `Request`. 26 | public struct Response { 27 | /// The URL request sent to the server. 28 | public let request: NSURLRequest? 29 | 30 | /// The server's response to the URL request. 31 | public let response: NSHTTPURLResponse? 32 | 33 | /// The data returned by the server. 34 | public let data: NSData? 35 | 36 | /// The result of response serialization. 37 | public let result: Result 38 | 39 | /** 40 | Initializes the `Response` instance with the specified URL request, URL response, server data and response 41 | serialization result. 42 | 43 | - parameter request: The URL request sent to the server. 44 | - parameter response: The server's response to the URL request. 45 | - parameter data: The data returned by the server. 46 | - parameter result: The result of response serialization. 47 | 48 | - returns: the new `Response` instance. 49 | */ 50 | public init(request: NSURLRequest?, response: NSHTTPURLResponse?, data: NSData?, result: Result) { 51 | self.request = request 52 | self.response = response 53 | self.data = data 54 | self.result = result 55 | } 56 | } 57 | 58 | // MARK: - CustomStringConvertible 59 | 60 | extension Response: CustomStringConvertible { 61 | /// The textual representation used when written to an output stream, which includes whether the result was a 62 | /// success or failure. 63 | public var description: String { 64 | return result.debugDescription 65 | } 66 | } 67 | 68 | // MARK: - CustomDebugStringConvertible 69 | 70 | extension Response: CustomDebugStringConvertible { 71 | /// The debug textual representation used when written to an output stream, which includes the URL request, the URL 72 | /// response, the server data and the response serialization result. 73 | public var debugDescription: String { 74 | var output: [String] = [] 75 | 76 | output.append(request != nil ? "[Request]: \(request!)" : "[Request]: nil") 77 | output.append(response != nil ? "[Response]: \(response!)" : "[Response]: nil") 78 | output.append("[Data]: \(data?.length ?? 0) bytes") 79 | output.append("[Result]: \(result.debugDescription)") 80 | 81 | return output.joinWithSeparator("\n") 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Pods/Alamofire/Source/ResponseSerialization.swift: -------------------------------------------------------------------------------- 1 | // ResponseSerialization.swift 2 | // 3 | // Copyright (c) 2014–2015 Alamofire Software Foundation (http://alamofire.org/) 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 13 | // all 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 21 | // THE SOFTWARE. 22 | 23 | import Foundation 24 | 25 | // MARK: ResponseSerializer 26 | 27 | /** 28 | The type in which all response serializers must conform to in order to serialize a response. 29 | */ 30 | public protocol ResponseSerializerType { 31 | /// The type of serialized object to be created by this `ResponseSerializerType`. 32 | typealias SerializedObject 33 | 34 | /// The type of error to be created by this `ResponseSerializer` if serialization fails. 35 | typealias ErrorObject: ErrorType 36 | 37 | /** 38 | A closure used by response handlers that takes a request, response, data and error and returns a result. 39 | */ 40 | var serializeResponse: (NSURLRequest?, NSHTTPURLResponse?, NSData?, NSError?) -> Result { get } 41 | } 42 | 43 | // MARK: - 44 | 45 | /** 46 | A generic `ResponseSerializerType` used to serialize a request, response, and data into a serialized object. 47 | */ 48 | public struct ResponseSerializer: ResponseSerializerType { 49 | /// The type of serialized object to be created by this `ResponseSerializer`. 50 | public typealias SerializedObject = Value 51 | 52 | /// The type of error to be created by this `ResponseSerializer` if serialization fails. 53 | public typealias ErrorObject = Error 54 | 55 | /** 56 | A closure used by response handlers that takes a request, response, data and error and returns a result. 57 | */ 58 | public var serializeResponse: (NSURLRequest?, NSHTTPURLResponse?, NSData?, NSError?) -> Result 59 | 60 | /** 61 | Initializes the `ResponseSerializer` instance with the given serialize response closure. 62 | 63 | - parameter serializeResponse: The closure used to serialize the response. 64 | 65 | - returns: The new generic response serializer instance. 66 | */ 67 | public init(serializeResponse: (NSURLRequest?, NSHTTPURLResponse?, NSData?, NSError?) -> Result) { 68 | self.serializeResponse = serializeResponse 69 | } 70 | } 71 | 72 | // MARK: - Default 73 | 74 | extension Request { 75 | 76 | /** 77 | Adds a handler to be called once the request has finished. 78 | 79 | - parameter queue: The queue on which the completion handler is dispatched. 80 | - parameter completionHandler: The code to be executed once the request has finished. 81 | 82 | - returns: The request. 83 | */ 84 | public func response( 85 | queue queue: dispatch_queue_t? = nil, 86 | completionHandler: (NSURLRequest?, NSHTTPURLResponse?, NSData?, NSError?) -> Void) 87 | -> Self 88 | { 89 | delegate.queue.addOperationWithBlock { 90 | dispatch_async(queue ?? dispatch_get_main_queue()) { 91 | completionHandler(self.request, self.response, self.delegate.data, self.delegate.error) 92 | } 93 | } 94 | 95 | return self 96 | } 97 | 98 | /** 99 | Adds a handler to be called once the request has finished. 100 | 101 | - parameter queue: The queue on which the completion handler is dispatched. 102 | - parameter responseSerializer: The response serializer responsible for serializing the request, response, 103 | and data. 104 | - parameter completionHandler: The code to be executed once the request has finished. 105 | 106 | - returns: The request. 107 | */ 108 | public func response( 109 | queue queue: dispatch_queue_t? = nil, 110 | responseSerializer: T, 111 | completionHandler: Response -> Void) 112 | -> Self 113 | { 114 | delegate.queue.addOperationWithBlock { 115 | let result = responseSerializer.serializeResponse( 116 | self.request, 117 | self.response, 118 | self.delegate.data, 119 | self.delegate.error 120 | ) 121 | 122 | dispatch_async(queue ?? dispatch_get_main_queue()) { 123 | let response = Response( 124 | request: self.request, 125 | response: self.response, 126 | data: self.delegate.data, 127 | result: result 128 | ) 129 | 130 | completionHandler(response) 131 | } 132 | } 133 | 134 | return self 135 | } 136 | } 137 | 138 | // MARK: - Data 139 | 140 | extension Request { 141 | 142 | /** 143 | Creates a response serializer that returns the associated data as-is. 144 | 145 | - returns: A data response serializer. 146 | */ 147 | public static func dataResponseSerializer() -> ResponseSerializer { 148 | return ResponseSerializer { _, response, data, error in 149 | guard error == nil else { return .Failure(error!) } 150 | 151 | if let response = response where response.statusCode == 204 { return .Success(NSData()) } 152 | 153 | guard let validData = data else { 154 | let failureReason = "Data could not be serialized. Input data was nil." 155 | let error = Error.errorWithCode(.DataSerializationFailed, failureReason: failureReason) 156 | return .Failure(error) 157 | } 158 | 159 | return .Success(validData) 160 | } 161 | } 162 | 163 | /** 164 | Adds a handler to be called once the request has finished. 165 | 166 | - parameter completionHandler: The code to be executed once the request has finished. 167 | 168 | - returns: The request. 169 | */ 170 | public func responseData(completionHandler: Response -> Void) -> Self { 171 | return response(responseSerializer: Request.dataResponseSerializer(), completionHandler: completionHandler) 172 | } 173 | } 174 | 175 | // MARK: - String 176 | 177 | extension Request { 178 | 179 | /** 180 | Creates a response serializer that returns a string initialized from the response data with the specified 181 | string encoding. 182 | 183 | - parameter encoding: The string encoding. If `nil`, the string encoding will be determined from the server 184 | response, falling back to the default HTTP default character set, ISO-8859-1. 185 | 186 | - returns: A string response serializer. 187 | */ 188 | public static func stringResponseSerializer( 189 | var encoding encoding: NSStringEncoding? = nil) 190 | -> ResponseSerializer 191 | { 192 | return ResponseSerializer { _, response, data, error in 193 | guard error == nil else { return .Failure(error!) } 194 | 195 | if let response = response where response.statusCode == 204 { return .Success("") } 196 | 197 | guard let validData = data else { 198 | let failureReason = "String could not be serialized. Input data was nil." 199 | let error = Error.errorWithCode(.StringSerializationFailed, failureReason: failureReason) 200 | return .Failure(error) 201 | } 202 | 203 | if let encodingName = response?.textEncodingName where encoding == nil { 204 | encoding = CFStringConvertEncodingToNSStringEncoding( 205 | CFStringConvertIANACharSetNameToEncoding(encodingName) 206 | ) 207 | } 208 | 209 | let actualEncoding = encoding ?? NSISOLatin1StringEncoding 210 | 211 | if let string = String(data: validData, encoding: actualEncoding) { 212 | return .Success(string) 213 | } else { 214 | let failureReason = "String could not be serialized with encoding: \(actualEncoding)" 215 | let error = Error.errorWithCode(.StringSerializationFailed, failureReason: failureReason) 216 | return .Failure(error) 217 | } 218 | } 219 | } 220 | 221 | /** 222 | Adds a handler to be called once the request has finished. 223 | 224 | - parameter encoding: The string encoding. If `nil`, the string encoding will be determined from the 225 | server response, falling back to the default HTTP default character set, 226 | ISO-8859-1. 227 | - parameter completionHandler: A closure to be executed once the request has finished. 228 | 229 | - returns: The request. 230 | */ 231 | public func responseString( 232 | encoding encoding: NSStringEncoding? = nil, 233 | completionHandler: Response -> Void) 234 | -> Self 235 | { 236 | return response( 237 | responseSerializer: Request.stringResponseSerializer(encoding: encoding), 238 | completionHandler: completionHandler 239 | ) 240 | } 241 | } 242 | 243 | // MARK: - JSON 244 | 245 | extension Request { 246 | 247 | /** 248 | Creates a response serializer that returns a JSON object constructed from the response data using 249 | `NSJSONSerialization` with the specified reading options. 250 | 251 | - parameter options: The JSON serialization reading options. `.AllowFragments` by default. 252 | 253 | - returns: A JSON object response serializer. 254 | */ 255 | public static func JSONResponseSerializer( 256 | options options: NSJSONReadingOptions = .AllowFragments) 257 | -> ResponseSerializer 258 | { 259 | return ResponseSerializer { _, response, data, error in 260 | guard error == nil else { return .Failure(error!) } 261 | 262 | if let response = response where response.statusCode == 204 { return .Success(NSNull()) } 263 | 264 | guard let validData = data where validData.length > 0 else { 265 | let failureReason = "JSON could not be serialized. Input data was nil or zero length." 266 | let error = Error.errorWithCode(.JSONSerializationFailed, failureReason: failureReason) 267 | return .Failure(error) 268 | } 269 | 270 | do { 271 | let JSON = try NSJSONSerialization.JSONObjectWithData(validData, options: options) 272 | return .Success(JSON) 273 | } catch { 274 | return .Failure(error as NSError) 275 | } 276 | } 277 | } 278 | 279 | /** 280 | Adds a handler to be called once the request has finished. 281 | 282 | - parameter options: The JSON serialization reading options. `.AllowFragments` by default. 283 | - parameter completionHandler: A closure to be executed once the request has finished. 284 | 285 | - returns: The request. 286 | */ 287 | public func responseJSON( 288 | options options: NSJSONReadingOptions = .AllowFragments, 289 | completionHandler: Response -> Void) 290 | -> Self 291 | { 292 | return response( 293 | responseSerializer: Request.JSONResponseSerializer(options: options), 294 | completionHandler: completionHandler 295 | ) 296 | } 297 | } 298 | 299 | // MARK: - Property List 300 | 301 | extension Request { 302 | 303 | /** 304 | Creates a response serializer that returns an object constructed from the response data using 305 | `NSPropertyListSerialization` with the specified reading options. 306 | 307 | - parameter options: The property list reading options. `NSPropertyListReadOptions()` by default. 308 | 309 | - returns: A property list object response serializer. 310 | */ 311 | public static func propertyListResponseSerializer( 312 | options options: NSPropertyListReadOptions = NSPropertyListReadOptions()) 313 | -> ResponseSerializer 314 | { 315 | return ResponseSerializer { _, response, data, error in 316 | guard error == nil else { return .Failure(error!) } 317 | 318 | if let response = response where response.statusCode == 204 { return .Success(NSNull()) } 319 | 320 | guard let validData = data where validData.length > 0 else { 321 | let failureReason = "Property list could not be serialized. Input data was nil or zero length." 322 | let error = Error.errorWithCode(.PropertyListSerializationFailed, failureReason: failureReason) 323 | return .Failure(error) 324 | } 325 | 326 | do { 327 | let plist = try NSPropertyListSerialization.propertyListWithData(validData, options: options, format: nil) 328 | return .Success(plist) 329 | } catch { 330 | return .Failure(error as NSError) 331 | } 332 | } 333 | } 334 | 335 | /** 336 | Adds a handler to be called once the request has finished. 337 | 338 | - parameter options: The property list reading options. `0` by default. 339 | - parameter completionHandler: A closure to be executed once the request has finished. The closure takes 3 340 | arguments: the URL request, the URL response, the server data and the result 341 | produced while creating the property list. 342 | 343 | - returns: The request. 344 | */ 345 | public func responsePropertyList( 346 | options options: NSPropertyListReadOptions = NSPropertyListReadOptions(), 347 | completionHandler: Response -> Void) 348 | -> Self 349 | { 350 | return response( 351 | responseSerializer: Request.propertyListResponseSerializer(options: options), 352 | completionHandler: completionHandler 353 | ) 354 | } 355 | } 356 | -------------------------------------------------------------------------------- /Pods/Alamofire/Source/Result.swift: -------------------------------------------------------------------------------- 1 | // Result.swift 2 | // 3 | // Copyright (c) 2014–2015 Alamofire Software Foundation (http://alamofire.org/) 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 13 | // all 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 21 | // THE SOFTWARE. 22 | 23 | import Foundation 24 | 25 | /** 26 | Used to represent whether a request was successful or encountered an error. 27 | 28 | - Success: The request and all post processing operations were successful resulting in the serialization of the 29 | provided associated value. 30 | - Failure: The request encountered an error resulting in a failure. The associated values are the original data 31 | provided by the server as well as the error that caused the failure. 32 | */ 33 | public enum Result { 34 | case Success(Value) 35 | case Failure(Error) 36 | 37 | /// Returns `true` if the result is a success, `false` otherwise. 38 | public var isSuccess: Bool { 39 | switch self { 40 | case .Success: 41 | return true 42 | case .Failure: 43 | return false 44 | } 45 | } 46 | 47 | /// Returns `true` if the result is a failure, `false` otherwise. 48 | public var isFailure: Bool { 49 | return !isSuccess 50 | } 51 | 52 | /// Returns the associated value if the result is a success, `nil` otherwise. 53 | public var value: Value? { 54 | switch self { 55 | case .Success(let value): 56 | return value 57 | case .Failure: 58 | return nil 59 | } 60 | } 61 | 62 | /// Returns the associated error value if the result is a failure, `nil` otherwise. 63 | public var error: Error? { 64 | switch self { 65 | case .Success: 66 | return nil 67 | case .Failure(let error): 68 | return error 69 | } 70 | } 71 | } 72 | 73 | // MARK: - CustomStringConvertible 74 | 75 | extension Result: CustomStringConvertible { 76 | /// The textual representation used when written to an output stream, which includes whether the result was a 77 | /// success or failure. 78 | public var description: String { 79 | switch self { 80 | case .Success: 81 | return "SUCCESS" 82 | case .Failure: 83 | return "FAILURE" 84 | } 85 | } 86 | } 87 | 88 | // MARK: - CustomDebugStringConvertible 89 | 90 | extension Result: CustomDebugStringConvertible { 91 | /// The debug textual representation used when written to an output stream, which includes whether the result was a 92 | /// success or failure in addition to the value or error. 93 | public var debugDescription: String { 94 | switch self { 95 | case .Success(let value): 96 | return "SUCCESS: \(value)" 97 | case .Failure(let error): 98 | return "FAILURE: \(error)" 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /Pods/Alamofire/Source/ServerTrustPolicy.swift: -------------------------------------------------------------------------------- 1 | // ServerTrustPolicy.swift 2 | // 3 | // Copyright (c) 2014–2015 Alamofire Software Foundation (http://alamofire.org/) 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 13 | // all 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 21 | // THE SOFTWARE. 22 | 23 | import Foundation 24 | 25 | /// Responsible for managing the mapping of `ServerTrustPolicy` objects to a given host. 26 | public class ServerTrustPolicyManager { 27 | /// The dictionary of policies mapped to a particular host. 28 | public let policies: [String: ServerTrustPolicy] 29 | 30 | /** 31 | Initializes the `ServerTrustPolicyManager` instance with the given policies. 32 | 33 | Since different servers and web services can have different leaf certificates, intermediate and even root 34 | certficates, it is important to have the flexibility to specify evaluation policies on a per host basis. This 35 | allows for scenarios such as using default evaluation for host1, certificate pinning for host2, public key 36 | pinning for host3 and disabling evaluation for host4. 37 | 38 | - parameter policies: A dictionary of all policies mapped to a particular host. 39 | 40 | - returns: The new `ServerTrustPolicyManager` instance. 41 | */ 42 | public init(policies: [String: ServerTrustPolicy]) { 43 | self.policies = policies 44 | } 45 | 46 | /** 47 | Returns the `ServerTrustPolicy` for the given host if applicable. 48 | 49 | By default, this method will return the policy that perfectly matches the given host. Subclasses could override 50 | this method and implement more complex mapping implementations such as wildcards. 51 | 52 | - parameter host: The host to use when searching for a matching policy. 53 | 54 | - returns: The server trust policy for the given host if found. 55 | */ 56 | public func serverTrustPolicyForHost(host: String) -> ServerTrustPolicy? { 57 | return policies[host] 58 | } 59 | } 60 | 61 | // MARK: - 62 | 63 | extension NSURLSession { 64 | private struct AssociatedKeys { 65 | static var ManagerKey = "NSURLSession.ServerTrustPolicyManager" 66 | } 67 | 68 | var serverTrustPolicyManager: ServerTrustPolicyManager? { 69 | get { 70 | return objc_getAssociatedObject(self, &AssociatedKeys.ManagerKey) as? ServerTrustPolicyManager 71 | } 72 | set (manager) { 73 | objc_setAssociatedObject(self, &AssociatedKeys.ManagerKey, manager, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) 74 | } 75 | } 76 | } 77 | 78 | // MARK: - ServerTrustPolicy 79 | 80 | /** 81 | The `ServerTrustPolicy` evaluates the server trust generally provided by an `NSURLAuthenticationChallenge` when 82 | connecting to a server over a secure HTTPS connection. The policy configuration then evaluates the server trust 83 | with a given set of criteria to determine whether the server trust is valid and the connection should be made. 84 | 85 | Using pinned certificates or public keys for evaluation helps prevent man-in-the-middle (MITM) attacks and other 86 | vulnerabilities. Applications dealing with sensitive customer data or financial information are strongly encouraged 87 | to route all communication over an HTTPS connection with pinning enabled. 88 | 89 | - PerformDefaultEvaluation: Uses the default server trust evaluation while allowing you to control whether to 90 | validate the host provided by the challenge. Applications are encouraged to always 91 | validate the host in production environments to guarantee the validity of the server's 92 | certificate chain. 93 | 94 | - PinCertificates: Uses the pinned certificates to validate the server trust. The server trust is 95 | considered valid if one of the pinned certificates match one of the server certificates. 96 | By validating both the certificate chain and host, certificate pinning provides a very 97 | secure form of server trust validation mitigating most, if not all, MITM attacks. 98 | Applications are encouraged to always validate the host and require a valid certificate 99 | chain in production environments. 100 | 101 | - PinPublicKeys: Uses the pinned public keys to validate the server trust. The server trust is considered 102 | valid if one of the pinned public keys match one of the server certificate public keys. 103 | By validating both the certificate chain and host, public key pinning provides a very 104 | secure form of server trust validation mitigating most, if not all, MITM attacks. 105 | Applications are encouraged to always validate the host and require a valid certificate 106 | chain in production environments. 107 | 108 | - DisableEvaluation: Disables all evaluation which in turn will always consider any server trust as valid. 109 | 110 | - CustomEvaluation: Uses the associated closure to evaluate the validity of the server trust. 111 | */ 112 | public enum ServerTrustPolicy { 113 | case PerformDefaultEvaluation(validateHost: Bool) 114 | case PinCertificates(certificates: [SecCertificate], validateCertificateChain: Bool, validateHost: Bool) 115 | case PinPublicKeys(publicKeys: [SecKey], validateCertificateChain: Bool, validateHost: Bool) 116 | case DisableEvaluation 117 | case CustomEvaluation((serverTrust: SecTrust, host: String) -> Bool) 118 | 119 | // MARK: - Bundle Location 120 | 121 | /** 122 | Returns all certificates within the given bundle with a `.cer` file extension. 123 | 124 | - parameter bundle: The bundle to search for all `.cer` files. 125 | 126 | - returns: All certificates within the given bundle. 127 | */ 128 | public static func certificatesInBundle(bundle: NSBundle = NSBundle.mainBundle()) -> [SecCertificate] { 129 | var certificates: [SecCertificate] = [] 130 | 131 | for path in bundle.pathsForResourcesOfType(".cer", inDirectory: nil) { 132 | if let 133 | certificateData = NSData(contentsOfFile: path), 134 | certificate = SecCertificateCreateWithData(nil, certificateData) 135 | { 136 | certificates.append(certificate) 137 | } 138 | } 139 | 140 | return certificates 141 | } 142 | 143 | /** 144 | Returns all public keys within the given bundle with a `.cer` file extension. 145 | 146 | - parameter bundle: The bundle to search for all `*.cer` files. 147 | 148 | - returns: All public keys within the given bundle. 149 | */ 150 | public static func publicKeysInBundle(bundle: NSBundle = NSBundle.mainBundle()) -> [SecKey] { 151 | var publicKeys: [SecKey] = [] 152 | 153 | for certificate in certificatesInBundle(bundle) { 154 | if let publicKey = publicKeyForCertificate(certificate) { 155 | publicKeys.append(publicKey) 156 | } 157 | } 158 | 159 | return publicKeys 160 | } 161 | 162 | // MARK: - Evaluation 163 | 164 | /** 165 | Evaluates whether the server trust is valid for the given host. 166 | 167 | - parameter serverTrust: The server trust to evaluate. 168 | - parameter host: The host of the challenge protection space. 169 | 170 | - returns: Whether the server trust is valid. 171 | */ 172 | public func evaluateServerTrust(serverTrust: SecTrust, isValidForHost host: String) -> Bool { 173 | var serverTrustIsValid = false 174 | 175 | switch self { 176 | case let .PerformDefaultEvaluation(validateHost): 177 | let policy = SecPolicyCreateSSL(true, validateHost ? host as CFString : nil) 178 | SecTrustSetPolicies(serverTrust, [policy]) 179 | 180 | serverTrustIsValid = trustIsValid(serverTrust) 181 | case let .PinCertificates(pinnedCertificates, validateCertificateChain, validateHost): 182 | if validateCertificateChain { 183 | let policy = SecPolicyCreateSSL(true, validateHost ? host as CFString : nil) 184 | SecTrustSetPolicies(serverTrust, [policy]) 185 | 186 | SecTrustSetAnchorCertificates(serverTrust, pinnedCertificates) 187 | SecTrustSetAnchorCertificatesOnly(serverTrust, true) 188 | 189 | serverTrustIsValid = trustIsValid(serverTrust) 190 | } else { 191 | let serverCertificatesDataArray = certificateDataForTrust(serverTrust) 192 | 193 | //====================================================================================================== 194 | // The following `[] +` is a temporary workaround for a Swift 2.0 compiler error. This workaround should 195 | // be removed once the following radar has been resolved: 196 | // - http://openradar.appspot.com/radar?id=6082025006039040 197 | //====================================================================================================== 198 | 199 | let pinnedCertificatesDataArray = certificateDataForCertificates([] + pinnedCertificates) 200 | 201 | outerLoop: for serverCertificateData in serverCertificatesDataArray { 202 | for pinnedCertificateData in pinnedCertificatesDataArray { 203 | if serverCertificateData.isEqualToData(pinnedCertificateData) { 204 | serverTrustIsValid = true 205 | break outerLoop 206 | } 207 | } 208 | } 209 | } 210 | case let .PinPublicKeys(pinnedPublicKeys, validateCertificateChain, validateHost): 211 | var certificateChainEvaluationPassed = true 212 | 213 | if validateCertificateChain { 214 | let policy = SecPolicyCreateSSL(true, validateHost ? host as CFString : nil) 215 | SecTrustSetPolicies(serverTrust, [policy]) 216 | 217 | certificateChainEvaluationPassed = trustIsValid(serverTrust) 218 | } 219 | 220 | if certificateChainEvaluationPassed { 221 | outerLoop: for serverPublicKey in ServerTrustPolicy.publicKeysForTrust(serverTrust) as [AnyObject] { 222 | for pinnedPublicKey in pinnedPublicKeys as [AnyObject] { 223 | if serverPublicKey.isEqual(pinnedPublicKey) { 224 | serverTrustIsValid = true 225 | break outerLoop 226 | } 227 | } 228 | } 229 | } 230 | case .DisableEvaluation: 231 | serverTrustIsValid = true 232 | case let .CustomEvaluation(closure): 233 | serverTrustIsValid = closure(serverTrust: serverTrust, host: host) 234 | } 235 | 236 | return serverTrustIsValid 237 | } 238 | 239 | // MARK: - Private - Trust Validation 240 | 241 | private func trustIsValid(trust: SecTrust) -> Bool { 242 | var isValid = false 243 | 244 | var result = SecTrustResultType(kSecTrustResultInvalid) 245 | let status = SecTrustEvaluate(trust, &result) 246 | 247 | if status == errSecSuccess { 248 | let unspecified = SecTrustResultType(kSecTrustResultUnspecified) 249 | let proceed = SecTrustResultType(kSecTrustResultProceed) 250 | 251 | isValid = result == unspecified || result == proceed 252 | } 253 | 254 | return isValid 255 | } 256 | 257 | // MARK: - Private - Certificate Data 258 | 259 | private func certificateDataForTrust(trust: SecTrust) -> [NSData] { 260 | var certificates: [SecCertificate] = [] 261 | 262 | for index in 0.. [NSData] { 272 | return certificates.map { SecCertificateCopyData($0) as NSData } 273 | } 274 | 275 | // MARK: - Private - Public Key Extraction 276 | 277 | private static func publicKeysForTrust(trust: SecTrust) -> [SecKey] { 278 | var publicKeys: [SecKey] = [] 279 | 280 | for index in 0.. SecKey? { 293 | var publicKey: SecKey? 294 | 295 | let policy = SecPolicyCreateBasicX509() 296 | var trust: SecTrust? 297 | let trustCreationStatus = SecTrustCreateWithCertificates(certificate, policy, &trust) 298 | 299 | if let trust = trust where trustCreationStatus == errSecSuccess { 300 | publicKey = SecTrustCopyPublicKey(trust) 301 | } 302 | 303 | return publicKey 304 | } 305 | } 306 | -------------------------------------------------------------------------------- /Pods/Alamofire/Source/Stream.swift: -------------------------------------------------------------------------------- 1 | // Stream.swift 2 | // 3 | // Copyright (c) 2014–2015 Alamofire Software Foundation (http://alamofire.org/) 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 13 | // all 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 21 | // THE SOFTWARE. 22 | 23 | import Foundation 24 | 25 | #if !os(watchOS) 26 | 27 | @available(iOS 9.0, OSX 10.11, *) 28 | extension Manager { 29 | private enum Streamable { 30 | case Stream(String, Int) 31 | case NetService(NSNetService) 32 | } 33 | 34 | private func stream(streamable: Streamable) -> Request { 35 | var streamTask: NSURLSessionStreamTask! 36 | 37 | switch streamable { 38 | case .Stream(let hostName, let port): 39 | dispatch_sync(queue) { 40 | streamTask = self.session.streamTaskWithHostName(hostName, port: port) 41 | } 42 | case .NetService(let netService): 43 | dispatch_sync(queue) { 44 | streamTask = self.session.streamTaskWithNetService(netService) 45 | } 46 | } 47 | 48 | let request = Request(session: session, task: streamTask) 49 | 50 | delegate[request.delegate.task] = request.delegate 51 | 52 | if startRequestsImmediately { 53 | request.resume() 54 | } 55 | 56 | return request 57 | } 58 | 59 | /** 60 | Creates a request for bidirectional streaming with the given hostname and port. 61 | 62 | - parameter hostName: The hostname of the server to connect to. 63 | - parameter port: The port of the server to connect to. 64 | 65 | :returns: The created stream request. 66 | */ 67 | public func stream(hostName hostName: String, port: Int) -> Request { 68 | return stream(.Stream(hostName, port)) 69 | } 70 | 71 | /** 72 | Creates a request for bidirectional streaming with the given `NSNetService`. 73 | 74 | - parameter netService: The net service used to identify the endpoint. 75 | 76 | - returns: The created stream request. 77 | */ 78 | public func stream(netService netService: NSNetService) -> Request { 79 | return stream(.NetService(netService)) 80 | } 81 | } 82 | 83 | // MARK: - 84 | 85 | @available(iOS 9.0, OSX 10.11, *) 86 | extension Manager.SessionDelegate: NSURLSessionStreamDelegate { 87 | 88 | // MARK: Override Closures 89 | 90 | /// Overrides default behavior for NSURLSessionStreamDelegate method `URLSession:readClosedForStreamTask:`. 91 | public var streamTaskReadClosed: ((NSURLSession, NSURLSessionStreamTask) -> Void)? { 92 | get { 93 | return _streamTaskReadClosed as? (NSURLSession, NSURLSessionStreamTask) -> Void 94 | } 95 | set { 96 | _streamTaskReadClosed = newValue 97 | } 98 | } 99 | 100 | /// Overrides default behavior for NSURLSessionStreamDelegate method `URLSession:writeClosedForStreamTask:`. 101 | public var streamTaskWriteClosed: ((NSURLSession, NSURLSessionStreamTask) -> Void)? { 102 | get { 103 | return _streamTaskWriteClosed as? (NSURLSession, NSURLSessionStreamTask) -> Void 104 | } 105 | set { 106 | _streamTaskWriteClosed = newValue 107 | } 108 | } 109 | 110 | /// Overrides default behavior for NSURLSessionStreamDelegate method `URLSession:betterRouteDiscoveredForStreamTask:`. 111 | public var streamTaskBetterRouteDiscovered: ((NSURLSession, NSURLSessionStreamTask) -> Void)? { 112 | get { 113 | return _streamTaskBetterRouteDiscovered as? (NSURLSession, NSURLSessionStreamTask) -> Void 114 | } 115 | set { 116 | _streamTaskBetterRouteDiscovered = newValue 117 | } 118 | } 119 | 120 | /// Overrides default behavior for NSURLSessionStreamDelegate method `URLSession:streamTask:didBecomeInputStream:outputStream:`. 121 | public var streamTaskDidBecomeInputStream: ((NSURLSession, NSURLSessionStreamTask, NSInputStream, NSOutputStream) -> Void)? { 122 | get { 123 | return _streamTaskDidBecomeInputStream as? (NSURLSession, NSURLSessionStreamTask, NSInputStream, NSOutputStream) -> Void 124 | } 125 | set { 126 | _streamTaskDidBecomeInputStream = newValue 127 | } 128 | } 129 | 130 | // MARK: Delegate Methods 131 | 132 | /** 133 | Tells the delegate that the read side of the connection has been closed. 134 | 135 | - parameter session: The session. 136 | - parameter streamTask: The stream task. 137 | */ 138 | public func URLSession(session: NSURLSession, readClosedForStreamTask streamTask: NSURLSessionStreamTask) { 139 | streamTaskReadClosed?(session, streamTask) 140 | } 141 | 142 | /** 143 | Tells the delegate that the write side of the connection has been closed. 144 | 145 | - parameter session: The session. 146 | - parameter streamTask: The stream task. 147 | */ 148 | public func URLSession(session: NSURLSession, writeClosedForStreamTask streamTask: NSURLSessionStreamTask) { 149 | streamTaskWriteClosed?(session, streamTask) 150 | } 151 | 152 | /** 153 | Tells the delegate that the system has determined that a better route to the host is available. 154 | 155 | - parameter session: The session. 156 | - parameter streamTask: The stream task. 157 | */ 158 | public func URLSession(session: NSURLSession, betterRouteDiscoveredForStreamTask streamTask: NSURLSessionStreamTask) { 159 | streamTaskBetterRouteDiscovered?(session, streamTask) 160 | } 161 | 162 | /** 163 | Tells the delegate that the stream task has been completed and provides the unopened stream objects. 164 | 165 | - parameter session: The session. 166 | - parameter streamTask: The stream task. 167 | - parameter inputStream: The new input stream. 168 | - parameter outputStream: The new output stream. 169 | */ 170 | public func URLSession( 171 | session: NSURLSession, 172 | streamTask: NSURLSessionStreamTask, 173 | didBecomeInputStream inputStream: NSInputStream, 174 | outputStream: NSOutputStream) 175 | { 176 | streamTaskDidBecomeInputStream?(session, streamTask, inputStream, outputStream) 177 | } 178 | } 179 | 180 | #endif 181 | -------------------------------------------------------------------------------- /Pods/Alamofire/Source/Upload.swift: -------------------------------------------------------------------------------- 1 | // Upload.swift 2 | // 3 | // Copyright (c) 2014–2015 Alamofire Software Foundation (http://alamofire.org/) 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 13 | // all 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 21 | // THE SOFTWARE. 22 | 23 | import Foundation 24 | 25 | extension Manager { 26 | private enum Uploadable { 27 | case Data(NSURLRequest, NSData) 28 | case File(NSURLRequest, NSURL) 29 | case Stream(NSURLRequest, NSInputStream) 30 | } 31 | 32 | private func upload(uploadable: Uploadable) -> Request { 33 | var uploadTask: NSURLSessionUploadTask! 34 | var HTTPBodyStream: NSInputStream? 35 | 36 | switch uploadable { 37 | case .Data(let request, let data): 38 | dispatch_sync(queue) { 39 | uploadTask = self.session.uploadTaskWithRequest(request, fromData: data) 40 | } 41 | case .File(let request, let fileURL): 42 | dispatch_sync(queue) { 43 | uploadTask = self.session.uploadTaskWithRequest(request, fromFile: fileURL) 44 | } 45 | case .Stream(let request, let stream): 46 | dispatch_sync(queue) { 47 | uploadTask = self.session.uploadTaskWithStreamedRequest(request) 48 | } 49 | 50 | HTTPBodyStream = stream 51 | } 52 | 53 | let request = Request(session: session, task: uploadTask) 54 | 55 | if HTTPBodyStream != nil { 56 | request.delegate.taskNeedNewBodyStream = { _, _ in 57 | return HTTPBodyStream 58 | } 59 | } 60 | 61 | delegate[request.delegate.task] = request.delegate 62 | 63 | if startRequestsImmediately { 64 | request.resume() 65 | } 66 | 67 | return request 68 | } 69 | 70 | // MARK: File 71 | 72 | /** 73 | Creates a request for uploading a file to the specified URL request. 74 | 75 | If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. 76 | 77 | - parameter URLRequest: The URL request 78 | - parameter file: The file to upload 79 | 80 | - returns: The created upload request. 81 | */ 82 | public func upload(URLRequest: URLRequestConvertible, file: NSURL) -> Request { 83 | return upload(.File(URLRequest.URLRequest, file)) 84 | } 85 | 86 | /** 87 | Creates a request for uploading a file to the specified URL request. 88 | 89 | If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. 90 | 91 | - parameter method: The HTTP method. 92 | - parameter URLString: The URL string. 93 | - parameter headers: The HTTP headers. `nil` by default. 94 | - parameter file: The file to upload 95 | 96 | - returns: The created upload request. 97 | */ 98 | public func upload( 99 | method: Method, 100 | _ URLString: URLStringConvertible, 101 | headers: [String: String]? = nil, 102 | file: NSURL) 103 | -> Request 104 | { 105 | let mutableURLRequest = URLRequest(method, URLString, headers: headers) 106 | return upload(mutableURLRequest, file: file) 107 | } 108 | 109 | // MARK: Data 110 | 111 | /** 112 | Creates a request for uploading data to the specified URL request. 113 | 114 | If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. 115 | 116 | - parameter URLRequest: The URL request. 117 | - parameter data: The data to upload. 118 | 119 | - returns: The created upload request. 120 | */ 121 | public func upload(URLRequest: URLRequestConvertible, data: NSData) -> Request { 122 | return upload(.Data(URLRequest.URLRequest, data)) 123 | } 124 | 125 | /** 126 | Creates a request for uploading data to the specified URL request. 127 | 128 | If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. 129 | 130 | - parameter method: The HTTP method. 131 | - parameter URLString: The URL string. 132 | - parameter headers: The HTTP headers. `nil` by default. 133 | - parameter data: The data to upload 134 | 135 | - returns: The created upload request. 136 | */ 137 | public func upload( 138 | method: Method, 139 | _ URLString: URLStringConvertible, 140 | headers: [String: String]? = nil, 141 | data: NSData) 142 | -> Request 143 | { 144 | let mutableURLRequest = URLRequest(method, URLString, headers: headers) 145 | 146 | return upload(mutableURLRequest, data: data) 147 | } 148 | 149 | // MARK: Stream 150 | 151 | /** 152 | Creates a request for uploading a stream to the specified URL request. 153 | 154 | If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. 155 | 156 | - parameter URLRequest: The URL request. 157 | - parameter stream: The stream to upload. 158 | 159 | - returns: The created upload request. 160 | */ 161 | public func upload(URLRequest: URLRequestConvertible, stream: NSInputStream) -> Request { 162 | return upload(.Stream(URLRequest.URLRequest, stream)) 163 | } 164 | 165 | /** 166 | Creates a request for uploading a stream to the specified URL request. 167 | 168 | If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. 169 | 170 | - parameter method: The HTTP method. 171 | - parameter URLString: The URL string. 172 | - parameter headers: The HTTP headers. `nil` by default. 173 | - parameter stream: The stream to upload. 174 | 175 | - returns: The created upload request. 176 | */ 177 | public func upload( 178 | method: Method, 179 | _ URLString: URLStringConvertible, 180 | headers: [String: String]? = nil, 181 | stream: NSInputStream) 182 | -> Request 183 | { 184 | let mutableURLRequest = URLRequest(method, URLString, headers: headers) 185 | 186 | return upload(mutableURLRequest, stream: stream) 187 | } 188 | 189 | // MARK: MultipartFormData 190 | 191 | /// Default memory threshold used when encoding `MultipartFormData`. 192 | public static let MultipartFormDataEncodingMemoryThreshold: UInt64 = 10 * 1024 * 1024 193 | 194 | /** 195 | Defines whether the `MultipartFormData` encoding was successful and contains result of the encoding as 196 | associated values. 197 | 198 | - Success: Represents a successful `MultipartFormData` encoding and contains the new `Request` along with 199 | streaming information. 200 | - Failure: Used to represent a failure in the `MultipartFormData` encoding and also contains the encoding 201 | error. 202 | */ 203 | public enum MultipartFormDataEncodingResult { 204 | case Success(request: Request, streamingFromDisk: Bool, streamFileURL: NSURL?) 205 | case Failure(ErrorType) 206 | } 207 | 208 | /** 209 | Encodes the `MultipartFormData` and creates a request to upload the result to the specified URL request. 210 | 211 | It is important to understand the memory implications of uploading `MultipartFormData`. If the cummulative 212 | payload is small, encoding the data in-memory and directly uploading to a server is the by far the most 213 | efficient approach. However, if the payload is too large, encoding the data in-memory could cause your app to 214 | be terminated. Larger payloads must first be written to disk using input and output streams to keep the memory 215 | footprint low, then the data can be uploaded as a stream from the resulting file. Streaming from disk MUST be 216 | used for larger payloads such as video content. 217 | 218 | The `encodingMemoryThreshold` parameter allows Alamofire to automatically determine whether to encode in-memory 219 | or stream from disk. If the content length of the `MultipartFormData` is below the `encodingMemoryThreshold`, 220 | encoding takes place in-memory. If the content length exceeds the threshold, the data is streamed to disk 221 | during the encoding process. Then the result is uploaded as data or as a stream depending on which encoding 222 | technique was used. 223 | 224 | If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. 225 | 226 | - parameter method: The HTTP method. 227 | - parameter URLString: The URL string. 228 | - parameter headers: The HTTP headers. `nil` by default. 229 | - parameter multipartFormData: The closure used to append body parts to the `MultipartFormData`. 230 | - parameter encodingMemoryThreshold: The encoding memory threshold in bytes. 231 | `MultipartFormDataEncodingMemoryThreshold` by default. 232 | - parameter encodingCompletion: The closure called when the `MultipartFormData` encoding is complete. 233 | */ 234 | public func upload( 235 | method: Method, 236 | _ URLString: URLStringConvertible, 237 | headers: [String: String]? = nil, 238 | multipartFormData: MultipartFormData -> Void, 239 | encodingMemoryThreshold: UInt64 = Manager.MultipartFormDataEncodingMemoryThreshold, 240 | encodingCompletion: (MultipartFormDataEncodingResult -> Void)?) 241 | { 242 | let mutableURLRequest = URLRequest(method, URLString, headers: headers) 243 | 244 | return upload( 245 | mutableURLRequest, 246 | multipartFormData: multipartFormData, 247 | encodingMemoryThreshold: encodingMemoryThreshold, 248 | encodingCompletion: encodingCompletion 249 | ) 250 | } 251 | 252 | /** 253 | Encodes the `MultipartFormData` and creates a request to upload the result to the specified URL request. 254 | 255 | It is important to understand the memory implications of uploading `MultipartFormData`. If the cummulative 256 | payload is small, encoding the data in-memory and directly uploading to a server is the by far the most 257 | efficient approach. However, if the payload is too large, encoding the data in-memory could cause your app to 258 | be terminated. Larger payloads must first be written to disk using input and output streams to keep the memory 259 | footprint low, then the data can be uploaded as a stream from the resulting file. Streaming from disk MUST be 260 | used for larger payloads such as video content. 261 | 262 | The `encodingMemoryThreshold` parameter allows Alamofire to automatically determine whether to encode in-memory 263 | or stream from disk. If the content length of the `MultipartFormData` is below the `encodingMemoryThreshold`, 264 | encoding takes place in-memory. If the content length exceeds the threshold, the data is streamed to disk 265 | during the encoding process. Then the result is uploaded as data or as a stream depending on which encoding 266 | technique was used. 267 | 268 | If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. 269 | 270 | - parameter URLRequest: The URL request. 271 | - parameter multipartFormData: The closure used to append body parts to the `MultipartFormData`. 272 | - parameter encodingMemoryThreshold: The encoding memory threshold in bytes. 273 | `MultipartFormDataEncodingMemoryThreshold` by default. 274 | - parameter encodingCompletion: The closure called when the `MultipartFormData` encoding is complete. 275 | */ 276 | public func upload( 277 | URLRequest: URLRequestConvertible, 278 | multipartFormData: MultipartFormData -> Void, 279 | encodingMemoryThreshold: UInt64 = Manager.MultipartFormDataEncodingMemoryThreshold, 280 | encodingCompletion: (MultipartFormDataEncodingResult -> Void)?) 281 | { 282 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { 283 | let formData = MultipartFormData() 284 | multipartFormData(formData) 285 | 286 | let URLRequestWithContentType = URLRequest.URLRequest 287 | URLRequestWithContentType.setValue(formData.contentType, forHTTPHeaderField: "Content-Type") 288 | 289 | let isBackgroundSession = self.session.configuration.identifier != nil 290 | 291 | if formData.contentLength < encodingMemoryThreshold && !isBackgroundSession { 292 | do { 293 | let data = try formData.encode() 294 | let encodingResult = MultipartFormDataEncodingResult.Success( 295 | request: self.upload(URLRequestWithContentType, data: data), 296 | streamingFromDisk: false, 297 | streamFileURL: nil 298 | ) 299 | 300 | dispatch_async(dispatch_get_main_queue()) { 301 | encodingCompletion?(encodingResult) 302 | } 303 | } catch { 304 | dispatch_async(dispatch_get_main_queue()) { 305 | encodingCompletion?(.Failure(error as NSError)) 306 | } 307 | } 308 | } else { 309 | let fileManager = NSFileManager.defaultManager() 310 | let tempDirectoryURL = NSURL(fileURLWithPath: NSTemporaryDirectory()) 311 | let directoryURL = tempDirectoryURL.URLByAppendingPathComponent("com.alamofire.manager/multipart.form.data") 312 | let fileName = NSUUID().UUIDString 313 | let fileURL = directoryURL.URLByAppendingPathComponent(fileName) 314 | 315 | do { 316 | try fileManager.createDirectoryAtURL(directoryURL, withIntermediateDirectories: true, attributes: nil) 317 | try formData.writeEncodedDataToDisk(fileURL) 318 | 319 | dispatch_async(dispatch_get_main_queue()) { 320 | let encodingResult = MultipartFormDataEncodingResult.Success( 321 | request: self.upload(URLRequestWithContentType, file: fileURL), 322 | streamingFromDisk: true, 323 | streamFileURL: fileURL 324 | ) 325 | encodingCompletion?(encodingResult) 326 | } 327 | } catch { 328 | dispatch_async(dispatch_get_main_queue()) { 329 | encodingCompletion?(.Failure(error as NSError)) 330 | } 331 | } 332 | } 333 | } 334 | } 335 | } 336 | 337 | // MARK: - 338 | 339 | extension Request { 340 | 341 | // MARK: - UploadTaskDelegate 342 | 343 | class UploadTaskDelegate: DataTaskDelegate { 344 | var uploadTask: NSURLSessionUploadTask? { return task as? NSURLSessionUploadTask } 345 | var uploadProgress: ((Int64, Int64, Int64) -> Void)! 346 | 347 | // MARK: - NSURLSessionTaskDelegate 348 | 349 | // MARK: Override Closures 350 | 351 | var taskDidSendBodyData: ((NSURLSession, NSURLSessionTask, Int64, Int64, Int64) -> Void)? 352 | 353 | // MARK: Delegate Methods 354 | 355 | func URLSession( 356 | session: NSURLSession, 357 | task: NSURLSessionTask, 358 | didSendBodyData bytesSent: Int64, 359 | totalBytesSent: Int64, 360 | totalBytesExpectedToSend: Int64) 361 | { 362 | if let taskDidSendBodyData = taskDidSendBodyData { 363 | taskDidSendBodyData(session, task, bytesSent, totalBytesSent, totalBytesExpectedToSend) 364 | } else { 365 | progress.totalUnitCount = totalBytesExpectedToSend 366 | progress.completedUnitCount = totalBytesSent 367 | 368 | uploadProgress?(bytesSent, totalBytesSent, totalBytesExpectedToSend) 369 | } 370 | } 371 | } 372 | } 373 | -------------------------------------------------------------------------------- /Pods/Alamofire/Source/Validation.swift: -------------------------------------------------------------------------------- 1 | // Validation.swift 2 | // 3 | // Copyright (c) 2014–2015 Alamofire Software Foundation (http://alamofire.org/) 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 13 | // all 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 21 | // THE SOFTWARE. 22 | 23 | import Foundation 24 | 25 | extension Request { 26 | 27 | /** 28 | Used to represent whether validation was successful or encountered an error resulting in a failure. 29 | 30 | - Success: The validation was successful. 31 | - Failure: The validation failed encountering the provided error. 32 | */ 33 | public enum ValidationResult { 34 | case Success 35 | case Failure(NSError) 36 | } 37 | 38 | /** 39 | A closure used to validate a request that takes a URL request and URL response, and returns whether the 40 | request was valid. 41 | */ 42 | public typealias Validation = (NSURLRequest?, NSHTTPURLResponse) -> ValidationResult 43 | 44 | /** 45 | Validates the request, using the specified closure. 46 | 47 | If validation fails, subsequent calls to response handlers will have an associated error. 48 | 49 | - parameter validation: A closure to validate the request. 50 | 51 | - returns: The request. 52 | */ 53 | public func validate(validation: Validation) -> Self { 54 | delegate.queue.addOperationWithBlock { 55 | if let 56 | response = self.response where self.delegate.error == nil, 57 | case let .Failure(error) = validation(self.request, response) 58 | { 59 | self.delegate.error = error 60 | } 61 | } 62 | 63 | return self 64 | } 65 | 66 | // MARK: - Status Code 67 | 68 | /** 69 | Validates that the response has a status code in the specified range. 70 | 71 | If validation fails, subsequent calls to response handlers will have an associated error. 72 | 73 | - parameter range: The range of acceptable status codes. 74 | 75 | - returns: The request. 76 | */ 77 | public func validate(statusCode acceptableStatusCode: S) -> Self { 78 | return validate { _, response in 79 | if acceptableStatusCode.contains(response.statusCode) { 80 | return .Success 81 | } else { 82 | let failureReason = "Response status code was unacceptable: \(response.statusCode)" 83 | return .Failure(Error.errorWithCode(.StatusCodeValidationFailed, failureReason: failureReason)) 84 | } 85 | } 86 | } 87 | 88 | // MARK: - Content-Type 89 | 90 | private struct MIMEType { 91 | let type: String 92 | let subtype: String 93 | 94 | init?(_ string: String) { 95 | let components: [String] = { 96 | let stripped = string.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()) 97 | let split = stripped.substringToIndex(stripped.rangeOfString(";")?.startIndex ?? stripped.endIndex) 98 | return split.componentsSeparatedByString("/") 99 | }() 100 | 101 | if let 102 | type = components.first, 103 | subtype = components.last 104 | { 105 | self.type = type 106 | self.subtype = subtype 107 | } else { 108 | return nil 109 | } 110 | } 111 | 112 | func matches(MIME: MIMEType) -> Bool { 113 | switch (type, subtype) { 114 | case (MIME.type, MIME.subtype), (MIME.type, "*"), ("*", MIME.subtype), ("*", "*"): 115 | return true 116 | default: 117 | return false 118 | } 119 | } 120 | } 121 | 122 | /** 123 | Validates that the response has a content type in the specified array. 124 | 125 | If validation fails, subsequent calls to response handlers will have an associated error. 126 | 127 | - parameter contentType: The acceptable content types, which may specify wildcard types and/or subtypes. 128 | 129 | - returns: The request. 130 | */ 131 | public func validate(contentType acceptableContentTypes: S) -> Self { 132 | return validate { _, response in 133 | guard let validData = self.delegate.data where validData.length > 0 else { return .Success } 134 | 135 | if let 136 | responseContentType = response.MIMEType, 137 | responseMIMEType = MIMEType(responseContentType) 138 | { 139 | for contentType in acceptableContentTypes { 140 | if let acceptableMIMEType = MIMEType(contentType) where acceptableMIMEType.matches(responseMIMEType) { 141 | return .Success 142 | } 143 | } 144 | } else { 145 | for contentType in acceptableContentTypes { 146 | if let MIMEType = MIMEType(contentType) where MIMEType.type == "*" && MIMEType.subtype == "*" { 147 | return .Success 148 | } 149 | } 150 | } 151 | 152 | let failureReason: String 153 | 154 | if let responseContentType = response.MIMEType { 155 | failureReason = ( 156 | "Response content type \"\(responseContentType)\" does not match any acceptable " + 157 | "content types: \(acceptableContentTypes)" 158 | ) 159 | } else { 160 | failureReason = "Response content type was missing and acceptable content type does not match \"*/*\"" 161 | } 162 | 163 | return .Failure(Error.errorWithCode(.ContentTypeValidationFailed, failureReason: failureReason)) 164 | } 165 | } 166 | 167 | // MARK: - Automatic 168 | 169 | /** 170 | Validates that the response has a status code in the default acceptable range of 200...299, and that the content 171 | type matches any specified in the Accept HTTP header field. 172 | 173 | If validation fails, subsequent calls to response handlers will have an associated error. 174 | 175 | - returns: The request. 176 | */ 177 | public func validate() -> Self { 178 | let acceptableStatusCodes: Range = 200..<300 179 | let acceptableContentTypes: [String] = { 180 | if let accept = request?.valueForHTTPHeaderField("Accept") { 181 | return accept.componentsSeparatedByString(",") 182 | } 183 | 184 | return ["*/*"] 185 | }() 186 | 187 | return validate(statusCode: acceptableStatusCodes).validate(contentType: acceptableContentTypes) 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Alamofire (3.1.3) 3 | - Moya (5.1.0): 4 | - Moya/Core (= 5.1.0) 5 | - Moya/Core (5.1.0): 6 | - Alamofire (~> 3.0) 7 | 8 | DEPENDENCIES: 9 | - Moya 10 | 11 | SPEC CHECKSUMS: 12 | Alamofire: 9f93b56389e48def9220dd57d1f44b1927229a5a 13 | Moya: 416bd447f66f1e4c31aabf5914edf221479bdc49 14 | 15 | COCOAPODS: 0.39.0 16 | -------------------------------------------------------------------------------- /Pods/Moya/License.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Artsy, Ash Furrow 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 | -------------------------------------------------------------------------------- /Pods/Moya/Readme.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/Moya/Moya.svg?branch=master)](https://travis-ci.org/Moya/Moya) [![codecov.io](https://codecov.io/github/Moya/Moya/coverage.svg?branch=master)](https://codecov.io/github/Moya/Moya?branch=master) 2 | 3 | ![Moya Logo](web/moya_logo_github.png) 4 | 5 | You're a smart developer. You probably use [Alamofire](https://github.com/Alamofire/Alamofire) to abstract away access to 6 | NSURLSession and all those nasty details you don't really care about. But then, 7 | like lots of smart developers, you write ad hoc network abstraction layers. They 8 | are probably called "APIManager" or "NetworkModel", and they always end in tears. 9 | 10 | ![Moya Overview](web/diagram.png) 11 | 12 | Ad hoc network layers are common in iOS apps. They're bad for a few reasons: 13 | 14 | - Makes it hard to write new apps ("where do I begin?") 15 | - Makes it hard to maintain existing apps ("oh my god, this mess...") 16 | - Makes it hard to write unit tests ("how do I do this again?") 17 | 18 | So the basic idea of Moya is that we want some network abstraction layer that 19 | sufficiently encapsulates actually calling Alamofire directly. It should be simple 20 | enough that common things are easy, but comprehensive enough that complicated things 21 | are also easy. 22 | 23 | > If you use Alamofire to abstract away `NSURLSession`, why not use something 24 | to abstract away the nitty gritty of URLs, parameters, etc? 25 | 26 | Some awesome features of Moya: 27 | 28 | - Compile-time checking for correct API endpoint accesses. 29 | - Lets you define a clear usage of different endpoints with associated enum values. 30 | - Treats test stubs as first-class citizens so unit testing is super-easy. 31 | 32 | Sample Project 33 | -------------- 34 | 35 | There's a sample project in the Demo directory. Have fun! 36 | 37 | Project Status 38 | -------------- 39 | 40 | This project is actively under development, and is being used in [Artsy's 41 | new auction app](https://github.com/Artsy/eidolon). We consider it 42 | ready for production use. 43 | 44 | Currently, we support Xcode 7 and Swift 2. 45 | 46 | Installation 47 | ------------ 48 | 49 | ### CocoaPods 50 | Just add `pod 'Moya'` to your Podfile and go! 51 | 52 | In any file you'd like to use Moya in, don't forget to 53 | import the framework with `import Moya`. 54 | 55 | For RxSwift or ReactiveCocoa extensions, this project will include 56 | them as dependencies. You can do this via CocoaPods subspecs. 57 | 58 | ```rb 59 | pod 'Moya/RxSwift' 60 | pod 'Moya/ReactiveCocoa' 61 | ``` 62 | 63 | Then run `pod install`. 64 | 65 | ### Carthage 66 | Carthage users can point to this repository and use whichever 67 | generated framework they'd like, `Moya`, `RxMoya`, or `ReactiveMoya`. 68 | The full Moya framework is bundled in each of those frameworks; 69 | importing more than one framework in a single file will result in 70 | ambiguous lookups at compile time. 71 | 72 | ``` 73 | github "Moya/Moya" 74 | ``` 75 | 76 | Use 77 | --- 78 | 79 | After [some setup](docs/Examples.md), using Moya is really simple. You can access an API like this: 80 | 81 | ```swift 82 | provider.request(.Zen) { (data, statusCode, response, error) in 83 | if let data = data { 84 | // do something with the data 85 | } 86 | } 87 | ``` 88 | 89 | That's a basic example. Many API requests need parameters. Moya encodes these 90 | into the enum you use to access the endpoint, like this: 91 | 92 | ```swift 93 | provider.request(.UserProfile("ashfurrow")) { (data, statusCode, response, error) in 94 | if let data = data { 95 | // do something with the data 96 | } 97 | } 98 | ``` 99 | 100 | No more typos in URLs. No more missing parameter values. No more messing with 101 | parameter encoding. 102 | 103 | For examples, see the [documentation](docs/). 104 | 105 | Reactive Extensions 106 | ------------------- 107 | 108 | Even cooler are the reactive extensions. Moya provides reactive extensions for 109 | [ReactiveCocoa](docs/ReactiveCocoa.md) and [RxSwift](docs/RxSwift.md). 110 | 111 | ## ReactiveCocoa 112 | 113 | For `ReactiveCocoa`, it immediately returns a `SignalProducer` (`RACSignal` 114 | is also available if needed) that you can start or bind or map or whatever 115 | you want to do. To handle errors, for instance, we could do the following: 116 | 117 | ```swift 118 | provider.request(.UserProfile("ashfurrow")).start { (event) -> Void in 119 | switch event { 120 | case .Next(let response): 121 | image = UIImage(data: response.data) 122 | case .Failed(let error): 123 | print(error) 124 | default: 125 | break 126 | } 127 | } 128 | ``` 129 | 130 | ##RxSwift 131 | 132 | For `RxSwift`, it immediately returns an `Observable` that you can subscribe to 133 | or bind or map or whatever you want to do. To handle errors, for instance, 134 | we could do the following: 135 | 136 | ```swift 137 | provider.request(.UserProfile("ashfurrow")).subscribe { (event) -> Void in 138 | switch event { 139 | case .Next(let response): 140 | image = UIImage(data: response.data) 141 | case .Error(let error): 142 | print(error) 143 | default: 144 | break 145 | } 146 | } 147 | ``` 148 | 149 | --- 150 | 151 | In addition to the option of using signals instead of callback blocks, there are 152 | also a series of signal operators for RxSwift and ReactiveCocoa that will attempt 153 | to map the data received from the network response into either an image, some JSON, 154 | or a string, with `mapImage()`, `mapJSON()`, and `mapString()`, respectively. If the mapping is unsuccessful, you'll get an error on the signal. You also get handy methods 155 | for filtering out certain status codes. This means that you can place your code for 156 | handling API errors like 400's in the same places as code for handling invalid 157 | responses. 158 | 159 | Contributing 160 | ------------ 161 | 162 | Hey! Like Moya? Awesome! We could actually really use your help! 163 | 164 | Open source isn't just writing code. Moya could use your help with any of the 165 | following: 166 | 167 | - Finding (and reporting!) bugs. 168 | - New feature suggestions. 169 | - Answering questions on issues. 170 | - Documentation improvements. 171 | - Reviewing pull requests. 172 | - Helping to manage issue priorities. 173 | - Fixing bugs/new features. 174 | 175 | If any of that sounds cool to you, send a pull request! After a few 176 | contributions, we'll add you as an admin to the repo so you can merge pull 177 | requests and help steer the ship :ship: 178 | 179 | Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by [its terms](https://github.com/Moya/contributors/blob/master/Code of Conduct.md). 180 | 181 | License 182 | ------- 183 | 184 | Moya is released under an MIT license. See LICENSE for more information. 185 | -------------------------------------------------------------------------------- /Pods/Moya/Source/Endpoint.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Alamofire 3 | 4 | /// Used for stubbing responses. 5 | public enum EndpointSampleResponse { 6 | 7 | /// The network returned a response, including status code and data. 8 | case NetworkResponse(Int, NSData) 9 | 10 | /// The network failed to send the request, or failed to retrieve a response (eg a timeout). 11 | case NetworkError(ErrorType) 12 | } 13 | 14 | 15 | /// Class for reifying a target of the Target enum unto a concrete Endpoint. 16 | public class Endpoint { 17 | public typealias SampleResponseClosure = () -> EndpointSampleResponse 18 | 19 | public let URL: String 20 | public let method: Moya.Method 21 | public let sampleResponseClosure: SampleResponseClosure 22 | public let parameters: [String: AnyObject]? 23 | public let parameterEncoding: Moya.ParameterEncoding 24 | public let httpHeaderFields: [String: String]? 25 | 26 | /// Main initializer for Endpoint. 27 | public init(URL: String, 28 | sampleResponseClosure: SampleResponseClosure, 29 | method: Moya.Method = Moya.Method.GET, 30 | parameters: [String: AnyObject]? = nil, 31 | parameterEncoding: Moya.ParameterEncoding = .URL, 32 | httpHeaderFields: [String: String]? = nil) { 33 | 34 | self.URL = URL 35 | self.sampleResponseClosure = sampleResponseClosure 36 | self.method = method 37 | self.parameters = parameters 38 | self.parameterEncoding = parameterEncoding 39 | self.httpHeaderFields = httpHeaderFields 40 | } 41 | 42 | /// Convenience method for creating a new Endpoint with the same properties as the receiver, but with added parameters. 43 | public func endpointByAddingParameters(parameters: [String: AnyObject]) -> Endpoint { 44 | var newParameters = self.parameters ?? [String: AnyObject]() 45 | for (key, value) in parameters { 46 | newParameters[key] = value 47 | } 48 | 49 | return Endpoint(URL: URL, sampleResponseClosure: sampleResponseClosure, method: method, parameters: newParameters, parameterEncoding: parameterEncoding, httpHeaderFields: httpHeaderFields) 50 | } 51 | 52 | /// Convenience method for creating a new Endpoint with the same properties as the receiver, but with added HTTP header fields. 53 | public func endpointByAddingHTTPHeaderFields(httpHeaderFields: [String: String]) -> Endpoint { 54 | var newHTTPHeaderFields = self.httpHeaderFields ?? [String: String]() 55 | for (key, value) in httpHeaderFields { 56 | newHTTPHeaderFields[key] = value 57 | } 58 | 59 | return Endpoint(URL: URL, sampleResponseClosure: sampleResponseClosure, method: method, parameters: parameters, parameterEncoding: parameterEncoding, httpHeaderFields: newHTTPHeaderFields) 60 | } 61 | 62 | /// Convenience method for creating a new Endpoint with the same properties as the receiver, but with another parameter encoding. 63 | public func endpointByAddingParameterEncoding(newParameterEncoding: Moya.ParameterEncoding) -> Endpoint { 64 | 65 | return Endpoint(URL: URL, sampleResponseClosure: sampleResponseClosure, method: method, parameters: parameters, parameterEncoding: newParameterEncoding, httpHeaderFields: httpHeaderFields) 66 | } 67 | } 68 | 69 | /// Extension for converting an Endpoint into an NSURLRequest. 70 | extension Endpoint { 71 | public var urlRequest: NSURLRequest { 72 | let request: NSMutableURLRequest = NSMutableURLRequest(URL: NSURL(string: URL)!) 73 | request.HTTPMethod = method.rawValue 74 | request.allHTTPHeaderFields = httpHeaderFields 75 | 76 | return parameterEncoding.toAlamofire.encode(request, parameters: parameters).0 77 | } 78 | } 79 | 80 | /// Required for making Endpoint conform to Equatable. 81 | public func ==(lhs: Endpoint, rhs: Endpoint) -> Bool { 82 | return lhs.urlRequest.isEqual(rhs.urlRequest) 83 | } 84 | 85 | /// Required for using Endpoint as a key type in a Dictionary. 86 | extension Endpoint: Equatable, Hashable { 87 | public var hashValue: Int { 88 | return urlRequest.hash 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /Pods/Moya/Source/Error.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public enum Error: ErrorType { 4 | case ImageMapping(Response) 5 | case JSONMapping(Response) 6 | case StringMapping(Response) 7 | case StatusCode(Response) 8 | case Data(Response) 9 | case Underlying(ErrorType) 10 | } 11 | 12 | @available(*, deprecated, message="This will be removed when ReactiveCocoa 4 becomes final. Please visit https://github.com/Moya/Moya/issues/298 for more information.") 13 | public let MoyaErrorDomain = "Moya" 14 | 15 | @available(*, deprecated, message="This will be removed when ReactiveCocoa 4 becomes final. Please visit https://github.com/Moya/Moya/issues/298 for more information.") 16 | public enum MoyaErrorCode: Int { 17 | case ImageMapping = 0 18 | case JSONMapping 19 | case StringMapping 20 | case StatusCode 21 | case Data 22 | } 23 | 24 | @available(*, deprecated, message="This will be removed when ReactiveCocoa 4 becomes final. Please visit https://github.com/Moya/Moya/issues/298 for more information.") 25 | public extension Error { 26 | 27 | // Used to convert MoyaError to NSError for RACSignal 28 | var nsError: NSError { 29 | switch self { 30 | case .ImageMapping(let response): 31 | return NSError(domain: MoyaErrorDomain, code: MoyaErrorCode.ImageMapping.rawValue, userInfo: ["data" : response]) 32 | case .JSONMapping(let response): 33 | return NSError(domain: MoyaErrorDomain, code: MoyaErrorCode.JSONMapping.rawValue, userInfo: ["data" : response]) 34 | case .StringMapping(let response): 35 | return NSError(domain: MoyaErrorDomain, code: MoyaErrorCode.StringMapping.rawValue, userInfo: ["data" : response]) 36 | case .StatusCode(let response): 37 | return NSError(domain: MoyaErrorDomain, code: MoyaErrorCode.StatusCode.rawValue, userInfo: ["data" : response]) 38 | case .Data(let response): 39 | return NSError(domain: MoyaErrorDomain, code: MoyaErrorCode.Data.rawValue, userInfo: ["data" : response]) 40 | case .Underlying(let error): 41 | return error as NSError 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Pods/Moya/Source/Image.swift: -------------------------------------------------------------------------------- 1 | #if os(iOS) || os(watchOS) || os(tvOS) 2 | import UIKit.UIImage 3 | public typealias ImageType = UIImage 4 | #elseif os(OSX) 5 | import AppKit.NSImage 6 | public typealias ImageType = NSImage 7 | #endif 8 | 9 | public typealias Image = ImageType 10 | -------------------------------------------------------------------------------- /Pods/Moya/Source/Moya.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Alamofire 3 | 4 | /// Closure to be executed when a request has completed. 5 | public typealias Completion = (result: Moya.Result) -> () 6 | 7 | /// Represents an HTTP method. 8 | public enum Method: String { 9 | case GET, POST, PUT, DELETE, OPTIONS, HEAD, PATCH, TRACE, CONNECT 10 | } 11 | 12 | /// Choice of parameter encoding. 13 | public enum ParameterEncoding { 14 | case URL 15 | case JSON 16 | case PropertyList(NSPropertyListFormat, NSPropertyListWriteOptions) 17 | case Custom((URLRequestConvertible, [String: AnyObject]?) -> (NSMutableURLRequest, NSError?)) 18 | 19 | internal var toAlamofire: Alamofire.ParameterEncoding { 20 | switch self { 21 | case .URL: 22 | return .URL 23 | case .JSON: 24 | return .JSON 25 | case .PropertyList(let format, let options): 26 | return .PropertyList(format, options) 27 | case .Custom(let closure): 28 | return .Custom(closure) 29 | } 30 | } 31 | } 32 | 33 | public enum StubBehavior { 34 | case Never 35 | case Immediate 36 | case Delayed(seconds: NSTimeInterval) 37 | } 38 | 39 | /// Protocol to define the base URL, path, method, parameters and sample data for a target. 40 | public protocol TargetType { 41 | var baseURL: NSURL { get } 42 | var path: String { get } 43 | var method: Moya.Method { get } 44 | var parameters: [String: AnyObject]? { get } 45 | var sampleData: NSData { get } 46 | } 47 | 48 | /// Protocol to define the opaque type returned from a request 49 | public protocol Cancellable { 50 | func cancel() 51 | } 52 | 53 | /// Request provider class. Requests should be made through this class only. 54 | public class MoyaProvider { 55 | 56 | /// Closure that defines the endpoints for the provider. 57 | public typealias EndpointClosure = Target -> Endpoint 58 | 59 | /// Closure that resolves an Endpoint into an NSURLRequest. 60 | public typealias RequestClosure = (Endpoint, NSURLRequest -> Void) -> Void 61 | 62 | /// Closure that decides if/how a request should be stubbed. 63 | public typealias StubClosure = Target -> Moya.StubBehavior 64 | 65 | public let endpointClosure: EndpointClosure 66 | public let requestClosure: RequestClosure 67 | public let stubClosure: StubClosure 68 | public let manager: Manager 69 | 70 | /// A list of plugins 71 | /// e.g. for logging, network activity indicator or credentials 72 | public let plugins: [PluginType] 73 | 74 | /// Initializes a provider. 75 | public init(endpointClosure: EndpointClosure = MoyaProvider.DefaultEndpointMapping, 76 | requestClosure: RequestClosure = MoyaProvider.DefaultRequestMapping, 77 | stubClosure: StubClosure = MoyaProvider.NeverStub, 78 | manager: Manager = Alamofire.Manager.sharedInstance, 79 | plugins: [PluginType] = []) { 80 | 81 | self.endpointClosure = endpointClosure 82 | self.requestClosure = requestClosure 83 | self.stubClosure = stubClosure 84 | self.manager = manager 85 | self.plugins = plugins 86 | } 87 | 88 | /// Returns an Endpoint based on the token, method, and parameters by invoking the endpointsClosure. 89 | public func endpoint(token: Target) -> Endpoint { 90 | return endpointClosure(token) 91 | } 92 | 93 | /// Designated request-making method. Returns a Cancellable token to cancel the request later. 94 | public func request(target: Target, completion: Moya.Completion) -> Cancellable { 95 | let endpoint = self.endpoint(target) 96 | let stubBehavior = self.stubClosure(target) 97 | var cancellableToken = CancellableWrapper() 98 | 99 | let performNetworking = { (request: NSURLRequest) in 100 | if cancellableToken.isCancelled { return } 101 | 102 | switch stubBehavior { 103 | case .Never: 104 | cancellableToken.innerCancellable = self.sendRequest(target, request: request, completion: completion) 105 | default: 106 | cancellableToken.innerCancellable = self.stubRequest(target, request: request, completion: completion, endpoint: endpoint, stubBehavior: stubBehavior) 107 | } 108 | } 109 | 110 | requestClosure(endpoint, performNetworking) 111 | 112 | return cancellableToken 113 | } 114 | 115 | /// When overriding this method, take care to `notifyPluginsOfImpendingStub` and to perform the stub using the `createStubFunction` method. 116 | /// Note: this was previously in an extension, however it must be in the original class declaration to allow subclasses to override. 117 | internal func stubRequest(target: Target, request: NSURLRequest, completion: Moya.Completion, endpoint: Endpoint, stubBehavior: Moya.StubBehavior) -> CancellableToken { 118 | let cancellableToken = CancellableToken { } 119 | notifyPluginsOfImpendingStub(request, target: target) 120 | let plugins = self.plugins 121 | let stub: () -> () = createStubFunction(cancellableToken, forTarget: target, withCompletion: completion, endpoint: endpoint, plugins: plugins) 122 | switch stubBehavior { 123 | case .Immediate: 124 | stub() 125 | case .Delayed(let delay): 126 | let killTimeOffset = Int64(CDouble(delay) * CDouble(NSEC_PER_SEC)) 127 | let killTime = dispatch_time(DISPATCH_TIME_NOW, killTimeOffset) 128 | dispatch_after(killTime, dispatch_get_main_queue()) { 129 | stub() 130 | } 131 | case .Never: 132 | fatalError("Method called to stub request when stubbing is disabled.") 133 | } 134 | 135 | return cancellableToken 136 | } 137 | } 138 | 139 | /// Mark: Defaults 140 | 141 | public extension MoyaProvider { 142 | 143 | // These functions are default mappings to endpoings and requests. 144 | 145 | public final class func DefaultEndpointMapping(target: Target) -> Endpoint { 146 | let url = target.baseURL.URLByAppendingPathComponent(target.path).absoluteString 147 | return Endpoint(URL: url, sampleResponseClosure: {.NetworkResponse(200, target.sampleData)}, method: target.method, parameters: target.parameters) 148 | } 149 | 150 | public final class func DefaultRequestMapping(endpoint: Endpoint, closure: NSURLRequest -> Void) { 151 | return closure(endpoint.urlRequest) 152 | } 153 | } 154 | 155 | /// Mark: Stubbing 156 | 157 | public extension MoyaProvider { 158 | 159 | // Swift won't let us put the StubBehavior enum inside the provider class, so we'll 160 | // at least add some class functions to allow easy access to common stubbing closures. 161 | 162 | public final class func NeverStub(_: Target) -> Moya.StubBehavior { 163 | return .Never 164 | } 165 | 166 | public final class func ImmediatelyStub(_: Target) -> Moya.StubBehavior { 167 | return .Immediate 168 | } 169 | 170 | public final class func DelayedStub(seconds: NSTimeInterval)(_: Target) -> Moya.StubBehavior { 171 | return .Delayed(seconds: seconds) 172 | } 173 | } 174 | 175 | internal extension MoyaProvider { 176 | 177 | func sendRequest(target: Target, request: NSURLRequest, completion: Moya.Completion) -> CancellableToken { 178 | let request = manager.request(request) 179 | let plugins = self.plugins 180 | 181 | // Give plugins the chance to alter the outgoing request 182 | plugins.forEach { $0.willSendRequest(request, target: target) } 183 | 184 | // Perform the actual request 185 | let alamoRequest = request.response { (_, response: NSHTTPURLResponse?, data: NSData?, error: NSError?) -> () in 186 | let result = convertResponseToResult(response, data: data, error: error) 187 | // Inform all plugins about the response 188 | plugins.forEach { $0.didReceiveResponse(result, target: target) } 189 | completion(result: result) 190 | } 191 | 192 | return CancellableToken(request: alamoRequest) 193 | } 194 | 195 | /// Creates a function which, when called, executes the appropriate stubbing behavior for the given parameters. 196 | internal final func createStubFunction(token: CancellableToken, forTarget target: Target, withCompletion completion: Moya.Completion, endpoint: Endpoint, plugins: [PluginType]) -> (() -> ()) { 197 | return { 198 | if (token.canceled) { 199 | let error = Moya.Error.Underlying(NSError(domain: NSURLErrorDomain, code: NSURLErrorCancelled, userInfo: nil)) 200 | plugins.forEach { $0.didReceiveResponse(Moya.Result(failure: error), target: target) } 201 | completion(result: Result(failure: error)) 202 | return 203 | } 204 | 205 | switch endpoint.sampleResponseClosure() { 206 | case .NetworkResponse(let statusCode, let data): 207 | let response = Moya.Response(statusCode: statusCode, data: data, response: nil) 208 | plugins.forEach { $0.didReceiveResponse(Moya.Result(success: response), target: target) } 209 | completion(result: Moya.Result(success: response)) 210 | case .NetworkError(let error): 211 | let error = Moya.Error.Underlying(error) 212 | plugins.forEach { $0.didReceiveResponse(Moya.Result(failure: error), target: target) } 213 | completion(result: Moya.Result(failure: error)) 214 | } 215 | } 216 | } 217 | 218 | /// Notify all plugins that a stub is about to be performed. You must call this if overriding `stubRequest`. 219 | internal final func notifyPluginsOfImpendingStub(request: NSURLRequest, target: Target) { 220 | let request = manager.request(request) 221 | plugins.forEach { $0.willSendRequest(request, target: target) } 222 | } 223 | } 224 | 225 | private func convertResponseToResult(response: NSHTTPURLResponse?, data: NSData?, error: NSError?) -> Moya.Result { 226 | switch (response, data, error) { 227 | case let (.Some(response), .Some(data), .None): 228 | let response = Moya.Response(statusCode: response.statusCode, data: data, response: response) 229 | return Moya.Result(success: response) 230 | case let (.None, .None, .Some(error)): 231 | let error = Moya.Error.Underlying(error) 232 | return Moya.Result(failure: error) 233 | default: 234 | let error = Moya.Error.Underlying(NSError(domain: NSURLErrorDomain, code: NSURLErrorUnknown, userInfo: nil)) 235 | return Moya.Result(failure: error) 236 | } 237 | } 238 | 239 | /// Internal token that can be used to cancel requests 240 | internal final class CancellableToken: Cancellable , CustomDebugStringConvertible{ 241 | let cancelAction: () -> Void 242 | let request : Request? 243 | private(set) var canceled: Bool = false 244 | 245 | private var lock: OSSpinLock = OS_SPINLOCK_INIT 246 | 247 | func cancel() { 248 | OSSpinLockLock(&lock) 249 | defer { OSSpinLockUnlock(&lock) } 250 | guard !canceled else { return } 251 | canceled = true 252 | cancelAction() 253 | } 254 | 255 | init(action: () -> Void){ 256 | self.cancelAction = action 257 | self.request = nil 258 | } 259 | 260 | init(request : Request){ 261 | self.request = request 262 | self.cancelAction = { 263 | request.cancel() 264 | } 265 | } 266 | 267 | var debugDescription: String { 268 | guard let request = self.request else { 269 | return "Empty Request" 270 | } 271 | return request.debugDescription 272 | } 273 | 274 | } 275 | 276 | private struct CancellableWrapper: Cancellable { 277 | var innerCancellable: CancellableToken? = nil 278 | 279 | private var isCancelled = false 280 | 281 | func cancel() { 282 | innerCancellable?.cancel() 283 | } 284 | } 285 | 286 | /// Make the Alamofire Request type conform to our type, to prevent leaking Alamofire to plugins. 287 | extension Request: RequestType { } 288 | -------------------------------------------------------------------------------- /Pods/Moya/Source/Plugin.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// A Moya Plugin receives callbacks to perform side effects wherever a request is sent or received. 4 | /// 5 | /// for example, a plugin may be used to 6 | /// - log network requests 7 | /// - hide and show a network avtivity indicator 8 | /// - inject additional information into a request 9 | public protocol PluginType { 10 | /// Called immediately before a request is sent over the network (or stubbed). 11 | func willSendRequest(request: RequestType, target: TargetType) 12 | 13 | // Called after a response has been received, but before the MoyaProvider has invoked its completion handler. 14 | func didReceiveResponse(result: Result, target: TargetType) 15 | } 16 | 17 | /// Request type used by willSendRequest plugin function. 18 | public protocol RequestType { 19 | 20 | // Note: 21 | // 22 | // We use this protocol instead of the Alamofire request to avoid leaking that abstraction. 23 | // A plugin should not know about Alamofire at all. 24 | 25 | /// Retrieve an NSURLRequest represetation. 26 | var request: NSURLRequest? { get } 27 | 28 | /// Authenticates the request with a username and password. 29 | func authenticate(user user: String, password: String, persistence: NSURLCredentialPersistence) -> Self 30 | 31 | /// Authnenticates the request with a NSURLCredential instance. 32 | func authenticate(usingCredential credential: NSURLCredential) -> Self 33 | } 34 | -------------------------------------------------------------------------------- /Pods/Moya/Source/Plugins/CredentialsPlugin.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// Provides each request with optional NSURLCredentials. 4 | public final class CredentialsPlugin: PluginType { 5 | 6 | public typealias CredentialClosure = TargetType -> NSURLCredential? 7 | let credentialsClosure: CredentialClosure 8 | 9 | public init(credentialsClosure: CredentialClosure) { 10 | self.credentialsClosure = credentialsClosure 11 | } 12 | 13 | // MARK: Plugin 14 | 15 | public func willSendRequest(request: RequestType, target: TargetType) { 16 | if let credentials = credentialsClosure(target) { 17 | request.authenticate(usingCredential: credentials) 18 | } 19 | } 20 | 21 | public func didReceiveResponse(result: Result, target: TargetType) { 22 | 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Pods/Moya/Source/Plugins/NetworkActivityPlugin.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// Network activity change notification type. 4 | public enum NetworkActivityChangeType { 5 | case Began, Ended 6 | } 7 | 8 | /// Provides each request with optional NSURLCredentials. 9 | public final class NetworkActivityPlugin: PluginType { 10 | 11 | public typealias NetworkActivityClosure = (change: NetworkActivityChangeType) -> () 12 | let networkActivityClosure: NetworkActivityClosure 13 | 14 | public init(networkActivityClosure: NetworkActivityClosure) { 15 | self.networkActivityClosure = networkActivityClosure 16 | } 17 | 18 | // MARK: Plugin 19 | 20 | /// Called by the provider as soon as the request is about to start 21 | public func willSendRequest(request: RequestType, target: TargetType) { 22 | networkActivityClosure(change: .Began) 23 | } 24 | 25 | /// Called by the provider as soon as a response arrives 26 | public func didReceiveResponse(result: Result, target: TargetType) { 27 | networkActivityClosure(change: .Ended) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Pods/Moya/Source/Plugins/NetworkLoggerPlugin.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// Logs network activity (outgoing requests and incoming responses). 4 | public final class NetworkLoggerPlugin: PluginType { 5 | private let loggerId = "Moya_Logger" 6 | private let dateFormatString = "dd/MM/yyyy HH:mm:ss" 7 | private let dateFormatter = NSDateFormatter() 8 | private let separator = ", " 9 | private let terminator = "\n" 10 | private let output: (items: Any..., separator: String, terminator: String) -> Void 11 | 12 | /// If true, also logs response body data. 13 | public let verbose: Bool 14 | 15 | public init(verbose: Bool = false, output: (items: Any..., separator: String, terminator: String) -> Void = print) { 16 | self.verbose = verbose 17 | self.output = output 18 | } 19 | 20 | public func willSendRequest(request: RequestType, target: TargetType) { 21 | output(items: logNetworkRequest(request.request), separator: separator, terminator: terminator) 22 | } 23 | 24 | public func didReceiveResponse(result: Result, target: TargetType) { 25 | if case .Success(let response) = result { 26 | output(items: logNetworkResponse(response.response, data: response.data, target: target), separator: separator, terminator: terminator) 27 | } else { 28 | output(items: logNetworkResponse(nil, data: nil, target: target), separator: separator, terminator: terminator) 29 | } 30 | } 31 | } 32 | 33 | private extension NetworkLoggerPlugin { 34 | 35 | private var date: String { 36 | dateFormatter.dateFormat = dateFormatString 37 | dateFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX") 38 | return dateFormatter.stringFromDate(NSDate()) 39 | } 40 | 41 | private func format(loggerId: String, date: String, identifier: String, message: String) -> String { 42 | return "\(loggerId): [\(date)] \(identifier): \(message)" 43 | } 44 | 45 | func logNetworkRequest(request: NSURLRequest?) -> [String] { 46 | 47 | var output = [String]() 48 | 49 | output += [format(loggerId, date: date, identifier: "Request", message: request?.description ?? "(invalid request)")] 50 | 51 | if let headers = request?.allHTTPHeaderFields { 52 | output += [format(loggerId, date: date, identifier: "Request Headers", message: headers.description)] 53 | } 54 | 55 | if let bodyStream = request?.HTTPBodyStream { 56 | output += [format(loggerId, date: date, identifier: "Request Body Stream", message: bodyStream.description)] 57 | } 58 | 59 | if let httpMethod = request?.HTTPMethod { 60 | output += [format(loggerId, date: date, identifier: "HTTP Request Method", message: httpMethod)] 61 | } 62 | 63 | if let body = request?.HTTPBody where verbose == true { 64 | if let stringOutput = NSString(data: body, encoding: NSUTF8StringEncoding) as? String { 65 | output += [format(loggerId, date: date, identifier: "Request Body", message: stringOutput)] 66 | } 67 | } 68 | 69 | return output 70 | } 71 | 72 | func logNetworkResponse(response: NSURLResponse?, data: NSData?, target: TargetType) -> [String] { 73 | guard let response = response else { 74 | return [format(loggerId, date: date, identifier: "Response", message: "Received empty network response for \(target).")] 75 | } 76 | 77 | var output = [String]() 78 | 79 | output += [format(loggerId, date: date, identifier: "Response", message: response.description)] 80 | 81 | if let data = data, let stringData = NSString(data: data, encoding: NSUTF8StringEncoding) as? String where verbose == true { 82 | output += [stringData] 83 | } 84 | 85 | return output 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /Pods/Moya/Source/Response.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public final class Response: CustomDebugStringConvertible, Equatable { 4 | public let statusCode: Int 5 | public let data: NSData 6 | public let response: NSURLResponse? 7 | 8 | public init(statusCode: Int, data: NSData, response: NSURLResponse? = nil) { 9 | self.statusCode = statusCode 10 | self.data = data 11 | self.response = response 12 | } 13 | 14 | public var description: String { 15 | return "Status Code: \(statusCode), Data Length: \(data.length)" 16 | } 17 | 18 | public var debugDescription: String { 19 | return description 20 | } 21 | } 22 | 23 | public func ==(lhs: Response, rhs: Response) -> Bool { 24 | return lhs.statusCode == rhs.statusCode 25 | && lhs.data == rhs.data 26 | && lhs.response == rhs.response 27 | } 28 | 29 | public extension Response { 30 | 31 | /// Filters out responses that don't fall within the given range, generating errors when others are encountered. 32 | public func filterStatusCodes(range: ClosedInterval) throws -> Response { 33 | guard range.contains(statusCode) else { 34 | throw Error.StatusCode(self) 35 | } 36 | return self 37 | } 38 | 39 | public func filterStatusCode(code: Int) throws -> Response { 40 | return try filterStatusCodes(code...code) 41 | } 42 | 43 | public func filterSuccessfulStatusCodes() throws -> Response { 44 | return try filterStatusCodes(200...299) 45 | } 46 | 47 | public func filterSuccessfulStatusAndRedirectCodes() throws -> Response { 48 | return try filterStatusCodes(200...399) 49 | } 50 | 51 | /// Maps data received from the signal into a UIImage. 52 | func mapImage() throws -> Image { 53 | guard let image = Image(data: data) else { 54 | throw Error.ImageMapping(self) 55 | } 56 | return image 57 | } 58 | 59 | /// Maps data received from the signal into a JSON object. 60 | func mapJSON() throws -> AnyObject { 61 | do { 62 | return try NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments) 63 | } catch { 64 | throw Error.Underlying(error) 65 | } 66 | } 67 | 68 | /// Maps data received from the signal into a String. 69 | func mapString() throws -> String { 70 | guard let string = NSString(data: data, encoding: NSUTF8StringEncoding) else { 71 | throw Error.StringMapping(self) 72 | } 73 | return string as String 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /Pods/Moya/Source/Result.swift: -------------------------------------------------------------------------------- 1 | 2 | public enum Result { 3 | case Success(T) 4 | case Failure(Error) 5 | 6 | public init(success: T){ 7 | self = .Success(success) 8 | } 9 | 10 | public init(failure: Error) { 11 | self = .Failure(failure) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Pods/Pods.xcodeproj/xcuserdata/songlijun.xcuserdatad/xcschemes/Alamofire.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 45 | 46 | 52 | 53 | 55 | 56 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /Pods/Pods.xcodeproj/xcuserdata/songlijun.xcuserdatad/xcschemes/Moya.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 45 | 46 | 52 | 53 | 55 | 56 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /Pods/Pods.xcodeproj/xcuserdata/songlijun.xcuserdatad/xcschemes/Pods.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 45 | 46 | 52 | 53 | 55 | 56 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /Pods/Pods.xcodeproj/xcuserdata/songlijun.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Alamofire.xcscheme 8 | 9 | isShown 10 | 11 | 12 | Moya.xcscheme 13 | 14 | isShown 15 | 16 | 17 | Pods.xcscheme 18 | 19 | isShown 20 | 21 | 22 | 23 | SuppressBuildableAutocreation 24 | 25 | 432ECC54282C84882B482CCB4CF227FC 26 | 27 | primary 28 | 29 | 30 | AEBE29623B164A9CA272FD8CEFEC6E68 31 | 32 | primary 33 | 34 | 35 | EEE395646B2272A13685536341A6F637 36 | 37 | primary 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Alamofire/Alamofire-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Alamofire : NSObject 3 | @end 4 | @implementation PodsDummy_Alamofire 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Alamofire/Alamofire-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Alamofire/Alamofire-umbrella.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | FOUNDATION_EXPORT double AlamofireVersionNumber; 5 | FOUNDATION_EXPORT const unsigned char AlamofireVersionString[]; 6 | 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Alamofire/Alamofire.modulemap: -------------------------------------------------------------------------------- 1 | framework module Alamofire { 2 | umbrella header "Alamofire-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Alamofire/Alamofire.xcconfig: -------------------------------------------------------------------------------- 1 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 2 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/Alamofire" "${PODS_ROOT}/Headers/Public" 3 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 4 | PODS_ROOT = ${SRCROOT} 5 | SKIP_INSTALL = YES -------------------------------------------------------------------------------- /Pods/Target Support Files/Alamofire/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 3.1.3 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Moya/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 5.1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Moya/Moya-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Moya : NSObject 3 | @end 4 | @implementation PodsDummy_Moya 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Moya/Moya-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Moya/Moya-umbrella.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | FOUNDATION_EXPORT double MoyaVersionNumber; 5 | FOUNDATION_EXPORT const unsigned char MoyaVersionString[]; 6 | 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Moya/Moya.modulemap: -------------------------------------------------------------------------------- 1 | framework module Moya { 2 | umbrella header "Moya-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Moya/Moya.xcconfig: -------------------------------------------------------------------------------- 1 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 2 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/Moya" "${PODS_ROOT}/Headers/Public" 3 | OTHER_LDFLAGS = -framework "Foundation" 4 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 5 | PODS_ROOT = ${SRCROOT} 6 | SKIP_INSTALL = YES -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## Alamofire 5 | 6 | Copyright (c) 2014–2015 Alamofire Software Foundation (http://alamofire.org/) 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in 16 | all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | THE SOFTWARE. 25 | 26 | 27 | ## Moya 28 | 29 | The MIT License (MIT) 30 | 31 | Copyright (c) 2015 Artsy, Ash Furrow 32 | 33 | Permission is hereby granted, free of charge, to any person obtaining a copy 34 | of this software and associated documentation files (the "Software"), to deal 35 | in the Software without restriction, including without limitation the rights 36 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 37 | copies of the Software, and to permit persons to whom the Software is 38 | furnished to do so, subject to the following conditions: 39 | 40 | The above copyright notice and this permission notice shall be included in all 41 | copies or substantial portions of the Software. 42 | 43 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 44 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 45 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 46 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 47 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 48 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 49 | SOFTWARE. 50 | 51 | Generated by CocoaPods - http://cocoapods.org 52 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | Copyright (c) 2014–2015 Alamofire Software Foundation (http://alamofire.org/) 18 | 19 | Permission is hereby granted, free of charge, to any person obtaining a copy 20 | of this software and associated documentation files (the "Software"), to deal 21 | in the Software without restriction, including without limitation the rights 22 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 23 | copies of the Software, and to permit persons to whom the Software is 24 | furnished to do so, subject to the following conditions: 25 | 26 | The above copyright notice and this permission notice shall be included in 27 | all copies or substantial portions of the Software. 28 | 29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 30 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 31 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 32 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 33 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 34 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 35 | THE SOFTWARE. 36 | 37 | Title 38 | Alamofire 39 | Type 40 | PSGroupSpecifier 41 | 42 | 43 | FooterText 44 | The MIT License (MIT) 45 | 46 | Copyright (c) 2015 Artsy, Ash Furrow 47 | 48 | Permission is hereby granted, free of charge, to any person obtaining a copy 49 | of this software and associated documentation files (the "Software"), to deal 50 | in the Software without restriction, including without limitation the rights 51 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 52 | copies of the Software, and to permit persons to whom the Software is 53 | furnished to do so, subject to the following conditions: 54 | 55 | The above copyright notice and this permission notice shall be included in all 56 | copies or substantial portions of the Software. 57 | 58 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 59 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 60 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 61 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 62 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 63 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 64 | SOFTWARE. 65 | 66 | Title 67 | Moya 68 | Type 69 | PSGroupSpecifier 70 | 71 | 72 | FooterText 73 | Generated by CocoaPods - http://cocoapods.org 74 | Title 75 | 76 | Type 77 | PSGroupSpecifier 78 | 79 | 80 | StringsTable 81 | Acknowledgements 82 | Title 83 | Acknowledgements 84 | 85 | 86 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods : NSObject 3 | @end 4 | @implementation PodsDummy_Pods 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 5 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 6 | 7 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 8 | 9 | install_framework() 10 | { 11 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 12 | local source="${BUILT_PRODUCTS_DIR}/$1" 13 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 14 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 15 | elif [ -r "$1" ]; then 16 | local source="$1" 17 | fi 18 | 19 | local destination="${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 20 | 21 | if [ -L "${source}" ]; then 22 | echo "Symlinked..." 23 | source="$(readlink "${source}")" 24 | fi 25 | 26 | # use filter instead of exclude so missing patterns dont' throw errors 27 | echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 28 | rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 29 | 30 | local basename 31 | basename="$(basename -s .framework "$1")" 32 | binary="${destination}/${basename}.framework/${basename}" 33 | if ! [ -r "$binary" ]; then 34 | binary="${destination}/${basename}" 35 | fi 36 | 37 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 38 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 39 | strip_invalid_archs "$binary" 40 | fi 41 | 42 | # Resign the code if required by the build settings to avoid unstable apps 43 | code_sign_if_enabled "${destination}/$(basename "$1")" 44 | 45 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 46 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 47 | local swift_runtime_libs 48 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 49 | for lib in $swift_runtime_libs; do 50 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 51 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 52 | code_sign_if_enabled "${destination}/${lib}" 53 | done 54 | fi 55 | } 56 | 57 | # Signs a framework with the provided identity 58 | code_sign_if_enabled() { 59 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 60 | # Use the current code_sign_identitiy 61 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 62 | echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements \"$1\"" 63 | /usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements "$1" 64 | fi 65 | } 66 | 67 | # Strip invalid architectures 68 | strip_invalid_archs() { 69 | binary="$1" 70 | # Get architectures for current file 71 | archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)" 72 | stripped="" 73 | for arch in $archs; do 74 | if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then 75 | # Strip non-valid architectures in-place 76 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 77 | stripped="$stripped $arch" 78 | fi 79 | done 80 | if [[ "$stripped" ]]; then 81 | echo "Stripped $binary of architectures:$stripped" 82 | fi 83 | } 84 | 85 | 86 | if [[ "$CONFIGURATION" == "Debug" ]]; then 87 | install_framework "Pods/Alamofire.framework" 88 | install_framework "Pods/Moya.framework" 89 | fi 90 | if [[ "$CONFIGURATION" == "Release" ]]; then 91 | install_framework "Pods/Alamofire.framework" 92 | install_framework "Pods/Moya.framework" 93 | fi 94 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 5 | 6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 7 | > "$RESOURCES_TO_COPY" 8 | 9 | XCASSET_FILES=() 10 | 11 | realpath() { 12 | DIRECTORY="$(cd "${1%/*}" && pwd)" 13 | FILENAME="${1##*/}" 14 | echo "$DIRECTORY/$FILENAME" 15 | } 16 | 17 | install_resource() 18 | { 19 | case $1 in 20 | *.storyboard) 21 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc ${PODS_ROOT}/$1 --sdk ${SDKROOT}" 22 | ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc" "${PODS_ROOT}/$1" --sdk "${SDKROOT}" 23 | ;; 24 | *.xib) 25 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib ${PODS_ROOT}/$1 --sdk ${SDKROOT}" 26 | ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib" "${PODS_ROOT}/$1" --sdk "${SDKROOT}" 27 | ;; 28 | *.framework) 29 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 30 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 31 | echo "rsync -av ${PODS_ROOT}/$1 ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 32 | rsync -av "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 33 | ;; 34 | *.xcdatamodel) 35 | echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1"`.mom\"" 36 | xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodel`.mom" 37 | ;; 38 | *.xcdatamodeld) 39 | echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd\"" 40 | xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd" 41 | ;; 42 | *.xcmappingmodel) 43 | echo "xcrun mapc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm\"" 44 | xcrun mapc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm" 45 | ;; 46 | *.xcassets) 47 | ABSOLUTE_XCASSET_FILE=$(realpath "${PODS_ROOT}/$1") 48 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 49 | ;; 50 | /*) 51 | echo "$1" 52 | echo "$1" >> "$RESOURCES_TO_COPY" 53 | ;; 54 | *) 55 | echo "${PODS_ROOT}/$1" 56 | echo "${PODS_ROOT}/$1" >> "$RESOURCES_TO_COPY" 57 | ;; 58 | esac 59 | } 60 | 61 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 62 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 63 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 64 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 65 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 66 | fi 67 | rm -f "$RESOURCES_TO_COPY" 68 | 69 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] 70 | then 71 | case "${TARGETED_DEVICE_FAMILY}" in 72 | 1,2) 73 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 74 | ;; 75 | 1) 76 | TARGET_DEVICE_ARGS="--target-device iphone" 77 | ;; 78 | 2) 79 | TARGET_DEVICE_ARGS="--target-device ipad" 80 | ;; 81 | *) 82 | TARGET_DEVICE_ARGS="--target-device mac" 83 | ;; 84 | esac 85 | 86 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 87 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 88 | while read line; do 89 | if [[ $line != "`realpath $PODS_ROOT`*" ]]; then 90 | XCASSET_FILES+=("$line") 91 | fi 92 | done <<<"$OTHER_XCASSETS" 93 | 94 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${IPHONEOS_DEPLOYMENT_TARGET}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 95 | fi 96 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods-umbrella.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | FOUNDATION_EXPORT double PodsVersionNumber; 5 | FOUNDATION_EXPORT const unsigned char PodsVersionString[]; 6 | 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods.debug.xcconfig: -------------------------------------------------------------------------------- 1 | EMBEDDED_CONTENT_CONTAINS_SWIFT = YES 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 4 | OTHER_CFLAGS = $(inherited) -iquote "$CONFIGURATION_BUILD_DIR/Alamofire.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Moya.framework/Headers" 5 | OTHER_LDFLAGS = $(inherited) -framework "Alamofire" -framework "Moya" 6 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 7 | PODS_FRAMEWORK_BUILD_PATH = $(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods 8 | PODS_ROOT = ${SRCROOT}/Pods -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods { 2 | umbrella header "Pods-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods.release.xcconfig: -------------------------------------------------------------------------------- 1 | EMBEDDED_CONTENT_CONTAINS_SWIFT = YES 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 4 | OTHER_CFLAGS = $(inherited) -iquote "$CONFIGURATION_BUILD_DIR/Alamofire.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Moya.framework/Headers" 5 | OTHER_LDFLAGS = $(inherited) -framework "Alamofire" -framework "Moya" 6 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 7 | PODS_FRAMEWORK_BUILD_PATH = $(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods 8 | PODS_ROOT = ${SRCROOT}/Pods -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 学习 Alamofire封装库Moya 2 | 3 | ##Moya 4 | moya 对Alamofire网络请求库进行了封装,开发不需要写网络模型,管理等。使代码更加简洁。详情访问 [Moya](https://github.com/Moya/Moya "moya") 项目主页 5 | 6 | ##1. 创建一个iOS Swift项目 (废话) 7 | 这里使用cocoapods 创建Podfile文件放在项目根目录下 8 | ```bash 9 | source 'https://github.com/CocoaPods/Specs.git' 10 | use_frameworks! 11 | pod 'Moya' 12 | ``` 13 | 在项目根目录运行 14 | ```bash 15 | pod install --verbose --no-repo-update // 不更新repo, 速度会快点 16 | ``` 17 | 安装成功 18 | 点击`.xcworkspace`文件。启动项目 19 | 20 | ## 2. 创建API管理文件 DSAPI.Swift 21 | 这里我们使用逗视的api 22 | 1.引入Moya头文件 23 | ```swift 24 | import Foundation 25 | import Moya 26 | ``` 27 | 2.创建DS的请求方法列表 enum 28 | 29 | ```swift 30 | /** 31 | MARK: 创建DS 请求方法列表 32 | - GetVideosByType 根据类型获取视频列表 33 | */ 34 | public enum DS { 35 | case GetVideosByType(Int,Int,Int,Int) //根据类型获取视频列表 36 | } 37 | ``` 38 | 3.创建 MoyaProvider 39 | ```swift 40 | // MARK: - Provider setup 41 | let DSProvider = MoyaProvider() 42 | ``` 43 | 4.通过Moya 定义的`baseUrl`、 请求路径(`path`)、 Http方法、 参数和目标的示例数据的协议。 44 | 扩展DS : TargetType 45 | ```swift 46 | extension DS: TargetType { 47 | // 逗视API地址 48 | public var baseURL: NSURL { return NSURL(string: "https://api.doushi.me/v1/rest/video/")! } 49 | /// 拼接请求字符串 50 | public var path: String { 51 | switch self { 52 | case .GetVideosByType(let vid, let count, let type,let userId): 53 | return ("getVideosByType/\(vid)/\(count)/\(type)/\(userId)") 54 | } 55 | } 56 | /// 请求方法 57 | public var method: Moya.Method { 58 | return .GET 59 | } 60 | /// 配置参数 61 | public var parameters: [String: AnyObject]? { 62 | switch self { 63 | default: 64 | return nil 65 | } 66 | } 67 | /// 数据 68 | public var sampleData: NSData { 69 | switch self { 70 | case .GetVideosByType: 71 | return "Half measures are as bad as nothing at all.".dataUsingEncoding(NSUTF8StringEncoding)! 72 | } 73 | } 74 | } 75 | ``` 76 | OK 这样创建好了DSAPI管理类,下面在tableView中实验一把 77 | 78 | ## 5.创建VideosTableViewController 79 | - 定义数据集合 80 | ```swift 81 | var repos = NSArray() 82 | ``` 83 | - 创建loadData()方法请求网络数据 84 | ```swift 85 | /** 86 | 请求数据 87 | */ 88 | func loadData() { 89 | DSProvider.request(DS.GetVideosByType(0, 12, 0, 1)) {(result) -> () in 90 | switch result { 91 | case let .Success(response): 92 | do { 93 | let json: Dictionary? = try response.mapJSON() as? Dictionary 94 | if let json = json { 95 | print(json["content"] as! Array) 96 | if let contents: Array = json["content"] as? Array { 97 | self.repos = contents 98 | } 99 | } 100 | self.tableView.reloadData() 101 | } catch { 102 | } 103 | case let .Failure(error): 104 | print(error) 105 | break 106 | } 107 | } 108 | } 109 | ``` 110 | - 扩展VideosTableViewController Cell增添数据 111 | ```swift 112 | extension VideosTableViewController { 113 | override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 114 | let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath) 115 | // Configure the cell... 116 | let contentDic = repos[indexPath.row] as? Dictionary 117 | cell.textLabel?.text = contentDic!["title"] as? String 118 | return cell 119 | } 120 | override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 121 | return repos.count 122 | } 123 | } 124 | ``` 125 | OK,点击`Run`看一下效果吧 126 | 127 | [![](http://img.itjh.com.cn/moyas11.png)](http://img.itjh.com.cn/moyas11.png) 128 | 129 | 正确获取到 [逗视](https://itunes.apple.com/us/app/dou-shi-gao-xiao-shi-pin-ju-ji-de/id1044917946?l=zh&ls=1&mt=8 "逗视")app的视频列表了 130 | 131 | ------------ 132 | 有没有发现这样写网络请求很爽,我们只维护`DSAPI`就可以了,添加请求方法,处理数据等。 133 | 本文例子已经上传到github,有问题可以发送邮件iosdev#itjh.com.cn 134 | -------------------------------------------------------------------------------- /study_Moya.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | AB7ABDE01C327AB200EB851D /* VideosTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB7ABDDF1C327AB200EB851D /* VideosTableViewController.swift */; }; 11 | ABC916F11C32700F00705777 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC916F01C32700F00705777 /* AppDelegate.swift */; }; 12 | ABC916F31C32700F00705777 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC916F21C32700F00705777 /* ViewController.swift */; }; 13 | ABC916F61C32700F00705777 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = ABC916F41C32700F00705777 /* Main.storyboard */; }; 14 | ABC916F81C32700F00705777 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = ABC916F71C32700F00705777 /* Assets.xcassets */; }; 15 | ABC916FB1C32700F00705777 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = ABC916F91C32700F00705777 /* LaunchScreen.storyboard */; }; 16 | ABC917041C3270AA00705777 /* DSAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC917031C3270AA00705777 /* DSAPI.swift */; }; 17 | AC6AD8B5477B7CFA0CAE0CDE /* Pods.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3C90B183E76E03042D1888EC /* Pods.framework */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXFileReference section */ 21 | 1F699F21CEAD9E0813C68203 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = ""; }; 22 | 3C90B183E76E03042D1888EC /* Pods.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 23 | AB7ABDDF1C327AB200EB851D /* VideosTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VideosTableViewController.swift; sourceTree = ""; }; 24 | ABC916ED1C32700F00705777 /* study_Moya.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = study_Moya.app; sourceTree = BUILT_PRODUCTS_DIR; }; 25 | ABC916F01C32700F00705777 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 26 | ABC916F21C32700F00705777 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 27 | ABC916F51C32700F00705777 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 28 | ABC916F71C32700F00705777 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 29 | ABC916FA1C32700F00705777 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 30 | ABC916FC1C32700F00705777 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 31 | ABC917031C3270AA00705777 /* DSAPI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DSAPI.swift; sourceTree = ""; }; 32 | FA98D249088777BE4690C453 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = ""; }; 33 | /* End PBXFileReference section */ 34 | 35 | /* Begin PBXFrameworksBuildPhase section */ 36 | ABC916EA1C32700F00705777 /* Frameworks */ = { 37 | isa = PBXFrameworksBuildPhase; 38 | buildActionMask = 2147483647; 39 | files = ( 40 | AC6AD8B5477B7CFA0CAE0CDE /* Pods.framework in Frameworks */, 41 | ); 42 | runOnlyForDeploymentPostprocessing = 0; 43 | }; 44 | /* End PBXFrameworksBuildPhase section */ 45 | 46 | /* Begin PBXGroup section */ 47 | 1F07FC105C76A35FE8EFC47A /* Frameworks */ = { 48 | isa = PBXGroup; 49 | children = ( 50 | 3C90B183E76E03042D1888EC /* Pods.framework */, 51 | ); 52 | name = Frameworks; 53 | sourceTree = ""; 54 | }; 55 | 9BD5FBDAA680DA155D60D971 /* Pods */ = { 56 | isa = PBXGroup; 57 | children = ( 58 | 1F699F21CEAD9E0813C68203 /* Pods.debug.xcconfig */, 59 | FA98D249088777BE4690C453 /* Pods.release.xcconfig */, 60 | ); 61 | name = Pods; 62 | sourceTree = ""; 63 | }; 64 | ABC916E41C32700F00705777 = { 65 | isa = PBXGroup; 66 | children = ( 67 | ABC916EF1C32700F00705777 /* study_Moya */, 68 | ABC916EE1C32700F00705777 /* Products */, 69 | 9BD5FBDAA680DA155D60D971 /* Pods */, 70 | 1F07FC105C76A35FE8EFC47A /* Frameworks */, 71 | ); 72 | sourceTree = ""; 73 | }; 74 | ABC916EE1C32700F00705777 /* Products */ = { 75 | isa = PBXGroup; 76 | children = ( 77 | ABC916ED1C32700F00705777 /* study_Moya.app */, 78 | ); 79 | name = Products; 80 | sourceTree = ""; 81 | }; 82 | ABC916EF1C32700F00705777 /* study_Moya */ = { 83 | isa = PBXGroup; 84 | children = ( 85 | ABC917021C32703300705777 /* Network */, 86 | ABC916F01C32700F00705777 /* AppDelegate.swift */, 87 | ABC916F21C32700F00705777 /* ViewController.swift */, 88 | ABC916F41C32700F00705777 /* Main.storyboard */, 89 | ABC916F71C32700F00705777 /* Assets.xcassets */, 90 | ABC916F91C32700F00705777 /* LaunchScreen.storyboard */, 91 | ABC916FC1C32700F00705777 /* Info.plist */, 92 | AB7ABDDF1C327AB200EB851D /* VideosTableViewController.swift */, 93 | ); 94 | path = study_Moya; 95 | sourceTree = ""; 96 | }; 97 | ABC917021C32703300705777 /* Network */ = { 98 | isa = PBXGroup; 99 | children = ( 100 | ABC917031C3270AA00705777 /* DSAPI.swift */, 101 | ); 102 | name = Network; 103 | sourceTree = ""; 104 | }; 105 | /* End PBXGroup section */ 106 | 107 | /* Begin PBXNativeTarget section */ 108 | ABC916EC1C32700F00705777 /* study_Moya */ = { 109 | isa = PBXNativeTarget; 110 | buildConfigurationList = ABC916FF1C32700F00705777 /* Build configuration list for PBXNativeTarget "study_Moya" */; 111 | buildPhases = ( 112 | 8D511D27996E5788A91D27D6 /* Check Pods Manifest.lock */, 113 | ABC916E91C32700F00705777 /* Sources */, 114 | ABC916EA1C32700F00705777 /* Frameworks */, 115 | ABC916EB1C32700F00705777 /* Resources */, 116 | 41B2F9EF820585C9B33C1C83 /* Embed Pods Frameworks */, 117 | 1AB832F39CC52F5918F194C8 /* Copy Pods Resources */, 118 | ); 119 | buildRules = ( 120 | ); 121 | dependencies = ( 122 | ); 123 | name = study_Moya; 124 | productName = study_Moya; 125 | productReference = ABC916ED1C32700F00705777 /* study_Moya.app */; 126 | productType = "com.apple.product-type.application"; 127 | }; 128 | /* End PBXNativeTarget section */ 129 | 130 | /* Begin PBXProject section */ 131 | ABC916E51C32700F00705777 /* Project object */ = { 132 | isa = PBXProject; 133 | attributes = { 134 | LastSwiftUpdateCheck = 0720; 135 | LastUpgradeCheck = 0720; 136 | ORGANIZATIONNAME = "宋立君"; 137 | TargetAttributes = { 138 | ABC916EC1C32700F00705777 = { 139 | CreatedOnToolsVersion = 7.2; 140 | }; 141 | }; 142 | }; 143 | buildConfigurationList = ABC916E81C32700F00705777 /* Build configuration list for PBXProject "study_Moya" */; 144 | compatibilityVersion = "Xcode 3.2"; 145 | developmentRegion = English; 146 | hasScannedForEncodings = 0; 147 | knownRegions = ( 148 | en, 149 | Base, 150 | ); 151 | mainGroup = ABC916E41C32700F00705777; 152 | productRefGroup = ABC916EE1C32700F00705777 /* Products */; 153 | projectDirPath = ""; 154 | projectRoot = ""; 155 | targets = ( 156 | ABC916EC1C32700F00705777 /* study_Moya */, 157 | ); 158 | }; 159 | /* End PBXProject section */ 160 | 161 | /* Begin PBXResourcesBuildPhase section */ 162 | ABC916EB1C32700F00705777 /* Resources */ = { 163 | isa = PBXResourcesBuildPhase; 164 | buildActionMask = 2147483647; 165 | files = ( 166 | ABC916FB1C32700F00705777 /* LaunchScreen.storyboard in Resources */, 167 | ABC916F81C32700F00705777 /* Assets.xcassets in Resources */, 168 | ABC916F61C32700F00705777 /* Main.storyboard in Resources */, 169 | ); 170 | runOnlyForDeploymentPostprocessing = 0; 171 | }; 172 | /* End PBXResourcesBuildPhase section */ 173 | 174 | /* Begin PBXShellScriptBuildPhase section */ 175 | 1AB832F39CC52F5918F194C8 /* Copy Pods Resources */ = { 176 | isa = PBXShellScriptBuildPhase; 177 | buildActionMask = 2147483647; 178 | files = ( 179 | ); 180 | inputPaths = ( 181 | ); 182 | name = "Copy Pods Resources"; 183 | outputPaths = ( 184 | ); 185 | runOnlyForDeploymentPostprocessing = 0; 186 | shellPath = /bin/sh; 187 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n"; 188 | showEnvVarsInLog = 0; 189 | }; 190 | 41B2F9EF820585C9B33C1C83 /* Embed Pods Frameworks */ = { 191 | isa = PBXShellScriptBuildPhase; 192 | buildActionMask = 2147483647; 193 | files = ( 194 | ); 195 | inputPaths = ( 196 | ); 197 | name = "Embed Pods Frameworks"; 198 | outputPaths = ( 199 | ); 200 | runOnlyForDeploymentPostprocessing = 0; 201 | shellPath = /bin/sh; 202 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-frameworks.sh\"\n"; 203 | showEnvVarsInLog = 0; 204 | }; 205 | 8D511D27996E5788A91D27D6 /* Check Pods Manifest.lock */ = { 206 | isa = PBXShellScriptBuildPhase; 207 | buildActionMask = 2147483647; 208 | files = ( 209 | ); 210 | inputPaths = ( 211 | ); 212 | name = "Check Pods Manifest.lock"; 213 | outputPaths = ( 214 | ); 215 | runOnlyForDeploymentPostprocessing = 0; 216 | shellPath = /bin/sh; 217 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; 218 | showEnvVarsInLog = 0; 219 | }; 220 | /* End PBXShellScriptBuildPhase section */ 221 | 222 | /* Begin PBXSourcesBuildPhase section */ 223 | ABC916E91C32700F00705777 /* Sources */ = { 224 | isa = PBXSourcesBuildPhase; 225 | buildActionMask = 2147483647; 226 | files = ( 227 | ABC917041C3270AA00705777 /* DSAPI.swift in Sources */, 228 | ABC916F31C32700F00705777 /* ViewController.swift in Sources */, 229 | ABC916F11C32700F00705777 /* AppDelegate.swift in Sources */, 230 | AB7ABDE01C327AB200EB851D /* VideosTableViewController.swift in Sources */, 231 | ); 232 | runOnlyForDeploymentPostprocessing = 0; 233 | }; 234 | /* End PBXSourcesBuildPhase section */ 235 | 236 | /* Begin PBXVariantGroup section */ 237 | ABC916F41C32700F00705777 /* Main.storyboard */ = { 238 | isa = PBXVariantGroup; 239 | children = ( 240 | ABC916F51C32700F00705777 /* Base */, 241 | ); 242 | name = Main.storyboard; 243 | sourceTree = ""; 244 | }; 245 | ABC916F91C32700F00705777 /* LaunchScreen.storyboard */ = { 246 | isa = PBXVariantGroup; 247 | children = ( 248 | ABC916FA1C32700F00705777 /* Base */, 249 | ); 250 | name = LaunchScreen.storyboard; 251 | sourceTree = ""; 252 | }; 253 | /* End PBXVariantGroup section */ 254 | 255 | /* Begin XCBuildConfiguration section */ 256 | ABC916FD1C32700F00705777 /* Debug */ = { 257 | isa = XCBuildConfiguration; 258 | buildSettings = { 259 | ALWAYS_SEARCH_USER_PATHS = NO; 260 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 261 | CLANG_CXX_LIBRARY = "libc++"; 262 | CLANG_ENABLE_MODULES = YES; 263 | CLANG_ENABLE_OBJC_ARC = YES; 264 | CLANG_WARN_BOOL_CONVERSION = YES; 265 | CLANG_WARN_CONSTANT_CONVERSION = YES; 266 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 267 | CLANG_WARN_EMPTY_BODY = YES; 268 | CLANG_WARN_ENUM_CONVERSION = YES; 269 | CLANG_WARN_INT_CONVERSION = YES; 270 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 271 | CLANG_WARN_UNREACHABLE_CODE = YES; 272 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 273 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 274 | COPY_PHASE_STRIP = NO; 275 | DEBUG_INFORMATION_FORMAT = dwarf; 276 | ENABLE_STRICT_OBJC_MSGSEND = YES; 277 | ENABLE_TESTABILITY = YES; 278 | GCC_C_LANGUAGE_STANDARD = gnu99; 279 | GCC_DYNAMIC_NO_PIC = NO; 280 | GCC_NO_COMMON_BLOCKS = YES; 281 | GCC_OPTIMIZATION_LEVEL = 0; 282 | GCC_PREPROCESSOR_DEFINITIONS = ( 283 | "DEBUG=1", 284 | "$(inherited)", 285 | ); 286 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 287 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 288 | GCC_WARN_UNDECLARED_SELECTOR = YES; 289 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 290 | GCC_WARN_UNUSED_FUNCTION = YES; 291 | GCC_WARN_UNUSED_VARIABLE = YES; 292 | IPHONEOS_DEPLOYMENT_TARGET = 9.2; 293 | MTL_ENABLE_DEBUG_INFO = YES; 294 | ONLY_ACTIVE_ARCH = YES; 295 | SDKROOT = iphoneos; 296 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 297 | }; 298 | name = Debug; 299 | }; 300 | ABC916FE1C32700F00705777 /* Release */ = { 301 | isa = XCBuildConfiguration; 302 | buildSettings = { 303 | ALWAYS_SEARCH_USER_PATHS = NO; 304 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 305 | CLANG_CXX_LIBRARY = "libc++"; 306 | CLANG_ENABLE_MODULES = YES; 307 | CLANG_ENABLE_OBJC_ARC = YES; 308 | CLANG_WARN_BOOL_CONVERSION = YES; 309 | CLANG_WARN_CONSTANT_CONVERSION = YES; 310 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 311 | CLANG_WARN_EMPTY_BODY = YES; 312 | CLANG_WARN_ENUM_CONVERSION = YES; 313 | CLANG_WARN_INT_CONVERSION = YES; 314 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 315 | CLANG_WARN_UNREACHABLE_CODE = YES; 316 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 317 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 318 | COPY_PHASE_STRIP = NO; 319 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 320 | ENABLE_NS_ASSERTIONS = NO; 321 | ENABLE_STRICT_OBJC_MSGSEND = YES; 322 | GCC_C_LANGUAGE_STANDARD = gnu99; 323 | GCC_NO_COMMON_BLOCKS = YES; 324 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 325 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 326 | GCC_WARN_UNDECLARED_SELECTOR = YES; 327 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 328 | GCC_WARN_UNUSED_FUNCTION = YES; 329 | GCC_WARN_UNUSED_VARIABLE = YES; 330 | IPHONEOS_DEPLOYMENT_TARGET = 9.2; 331 | MTL_ENABLE_DEBUG_INFO = NO; 332 | SDKROOT = iphoneos; 333 | VALIDATE_PRODUCT = YES; 334 | }; 335 | name = Release; 336 | }; 337 | ABC917001C32700F00705777 /* Debug */ = { 338 | isa = XCBuildConfiguration; 339 | baseConfigurationReference = 1F699F21CEAD9E0813C68203 /* Pods.debug.xcconfig */; 340 | buildSettings = { 341 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 342 | INFOPLIST_FILE = study_Moya/Info.plist; 343 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 344 | PRODUCT_BUNDLE_IDENTIFIER = "net.itjh.study-Moya"; 345 | PRODUCT_NAME = "$(TARGET_NAME)"; 346 | }; 347 | name = Debug; 348 | }; 349 | ABC917011C32700F00705777 /* Release */ = { 350 | isa = XCBuildConfiguration; 351 | baseConfigurationReference = FA98D249088777BE4690C453 /* Pods.release.xcconfig */; 352 | buildSettings = { 353 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 354 | INFOPLIST_FILE = study_Moya/Info.plist; 355 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 356 | PRODUCT_BUNDLE_IDENTIFIER = "net.itjh.study-Moya"; 357 | PRODUCT_NAME = "$(TARGET_NAME)"; 358 | }; 359 | name = Release; 360 | }; 361 | /* End XCBuildConfiguration section */ 362 | 363 | /* Begin XCConfigurationList section */ 364 | ABC916E81C32700F00705777 /* Build configuration list for PBXProject "study_Moya" */ = { 365 | isa = XCConfigurationList; 366 | buildConfigurations = ( 367 | ABC916FD1C32700F00705777 /* Debug */, 368 | ABC916FE1C32700F00705777 /* Release */, 369 | ); 370 | defaultConfigurationIsVisible = 0; 371 | defaultConfigurationName = Release; 372 | }; 373 | ABC916FF1C32700F00705777 /* Build configuration list for PBXNativeTarget "study_Moya" */ = { 374 | isa = XCConfigurationList; 375 | buildConfigurations = ( 376 | ABC917001C32700F00705777 /* Debug */, 377 | ABC917011C32700F00705777 /* Release */, 378 | ); 379 | defaultConfigurationIsVisible = 0; 380 | defaultConfigurationName = Release; 381 | }; 382 | /* End XCConfigurationList section */ 383 | }; 384 | rootObject = ABC916E51C32700F00705777 /* Project object */; 385 | } 386 | -------------------------------------------------------------------------------- /study_Moya.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /study_Moya.xcodeproj/project.xcworkspace/xcuserdata/songlijun.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sljstudy/study_Moya/1f53c0f92e82b3a487935885e040075fbcc995c8/study_Moya.xcodeproj/project.xcworkspace/xcuserdata/songlijun.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /study_Moya.xcodeproj/xcuserdata/songlijun.xcuserdatad/xcschemes/study_Moya.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /study_Moya.xcodeproj/xcuserdata/songlijun.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | study_Moya.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | ABC916EC1C32700F00705777 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /study_Moya.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /study_Moya.xcworkspace/xcuserdata/songlijun.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sljstudy/study_Moya/1f53c0f92e82b3a487935885e040075fbcc995c8/study_Moya.xcworkspace/xcuserdata/songlijun.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /study_Moya.xcworkspace/xcuserdata/songlijun.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /study_Moya/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // study_Moya 4 | // 5 | // Created by 宋立君 on 15/12/29. 6 | // Copyright © 2015年 宋立君. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(application: UIApplication) { 33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /study_Moya/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /study_Moya/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /study_Moya/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /study_Moya/DSAPI.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DSApi.swift 3 | // study_Moya 逗视API 4 | // 5 | // Created by 宋立君 on 15/12/29. 6 | // Copyright © 2015年 宋立君. All rights reserved. 7 | // 8 | 9 | /** 10 | * DS 逗视API 11 | */ 12 | 13 | import Foundation 14 | import Moya 15 | 16 | // MARK: - Provider setup 17 | let DSProvider = MoyaProvider() 18 | 19 | 20 | /** 21 | 22 | MARK: 创建DS 请求 23 | - GetVideosByType 根据类型获取视频列表 24 | */ 25 | public enum DS { 26 | case GetVideosByType(Int,Int,Int,Int) //根据类型获取视频列表 27 | } 28 | 29 | 30 | extension DS: TargetType { 31 | // 逗视API地址 32 | public var baseURL: NSURL { return NSURL(string: "https://api.doushi.me/v1/rest/video/")! } 33 | 34 | /// 拼接请求字符串 35 | public var path: String { 36 | switch self { 37 | case .GetVideosByType(let vid, let count, let type,let userId): 38 | return ("getVideosByType/\(vid)/\(count)/\(type)/\(userId)") 39 | } 40 | } 41 | /// 请求方法 42 | public var method: Moya.Method { 43 | return .GET 44 | } 45 | 46 | /// 配置参数 47 | public var parameters: [String: AnyObject]? { 48 | switch self { 49 | 50 | default: 51 | return nil 52 | } 53 | } 54 | 55 | /// 数据 56 | public var sampleData: NSData { 57 | switch self { 58 | case .GetVideosByType: 59 | return "Half measures are as bad as nothing at all.".dataUsingEncoding(NSUTF8StringEncoding)! 60 | } 61 | } 62 | 63 | 64 | } 65 | 66 | //public func url(route: TargetType) -> String { 67 | // return route.baseURL.URLByAppendingPathComponent(route.path).absoluteString 68 | //} 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /study_Moya/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 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /study_Moya/VideosTableViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // VideosTableViewController.swift 3 | // study_Moya 4 | // 5 | // Created by 宋立君 on 15/12/29. 6 | // Copyright © 2015年 宋立君. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class VideosTableViewController: UITableViewController { 12 | 13 | 14 | var repos = NSArray() 15 | 16 | 17 | override func viewDidLoad() { 18 | super.viewDidLoad() 19 | loadData() 20 | } 21 | 22 | override func didReceiveMemoryWarning() { 23 | super.didReceiveMemoryWarning() 24 | } 25 | 26 | // MARK: - Table view data source 27 | 28 | override func numberOfSectionsInTableView(tableView: UITableView) -> Int { 29 | return 1 30 | } 31 | 32 | 33 | 34 | /** 35 | 请求数据 36 | */ 37 | func loadData() { 38 | 39 | DSProvider.request(DS.GetVideosByType(0, 12, 0, 1)) {(result) -> () in 40 | 41 | switch result { 42 | 43 | case let .Success(response): 44 | do { 45 | let json: Dictionary? = try response.mapJSON() as? Dictionary 46 | 47 | if let json = json { 48 | 49 | // print(json) 50 | print(json["content"] as! Array) 51 | 52 | if let contents: Array = json["content"] as? Array { 53 | self.repos = contents 54 | } 55 | 56 | } 57 | self.tableView.reloadData() 58 | } catch { 59 | } 60 | 61 | case let .Failure(error): 62 | print(error) 63 | break 64 | } 65 | 66 | 67 | } 68 | 69 | 70 | 71 | } 72 | 73 | /* 74 | override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 75 | let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath) 76 | 77 | // Configure the cell... 78 | 79 | return cell 80 | } 81 | */ 82 | 83 | /* 84 | // Override to support conditional editing of the table view. 85 | override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool { 86 | // Return false if you do not want the specified item to be editable. 87 | return true 88 | } 89 | */ 90 | 91 | /* 92 | // Override to support editing the table view. 93 | override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) { 94 | if editingStyle == .Delete { 95 | // Delete the row from the data source 96 | tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade) 97 | } else if editingStyle == .Insert { 98 | // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view 99 | } 100 | } 101 | */ 102 | 103 | /* 104 | // Override to support rearranging the table view. 105 | override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) { 106 | 107 | } 108 | */ 109 | 110 | /* 111 | // Override to support conditional rearranging of the table view. 112 | override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool { 113 | // Return false if you do not want the item to be re-orderable. 114 | return true 115 | } 116 | */ 117 | 118 | /* 119 | // MARK: - Navigation 120 | 121 | // In a storyboard-based application, you will often want to do a little preparation before navigation 122 | override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { 123 | // Get the new view controller using segue.destinationViewController. 124 | // Pass the selected object to the new view controller. 125 | } 126 | */ 127 | 128 | } 129 | 130 | 131 | extension VideosTableViewController { 132 | 133 | 134 | override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 135 | let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath) 136 | 137 | // Configure the cell... 138 | 139 | let contentDic = repos[indexPath.row] as? Dictionary 140 | 141 | cell.textLabel?.text = contentDic!["title"] as? String 142 | 143 | return cell 144 | } 145 | 146 | override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 147 | return repos.count 148 | } 149 | 150 | 151 | 152 | } 153 | 154 | -------------------------------------------------------------------------------- /study_Moya/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // study_Moya 4 | // 5 | // Created by 宋立君 on 15/12/29. 6 | // Copyright © 2015年 宋立君. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | // Do any additional setup after loading the view, typically from a nib. 16 | } 17 | 18 | override func didReceiveMemoryWarning() { 19 | super.didReceiveMemoryWarning() 20 | // Dispose of any resources that can be recreated. 21 | } 22 | 23 | 24 | } 25 | 26 | --------------------------------------------------------------------------------