├── Pods ├── Target Support Files │ ├── Alamofire │ │ ├── Alamofire-prefix.pch │ │ ├── Alamofire.modulemap │ │ ├── Alamofire-dummy.m │ │ ├── Alamofire-umbrella.h │ │ ├── Alamofire.xcconfig │ │ └── Info.plist │ └── Pods-XHNetworkSwiftExample │ │ ├── Pods-XHNetworkSwiftExample.modulemap │ │ ├── Pods-XHNetworkSwiftExample-dummy.m │ │ ├── Pods-XHNetworkSwiftExample-umbrella.h │ │ ├── Pods-XHNetworkSwiftExample.debug.xcconfig │ │ ├── Pods-XHNetworkSwiftExample.release.xcconfig │ │ ├── Info.plist │ │ ├── Pods-XHNetworkSwiftExample-acknowledgements.markdown │ │ ├── Pods-XHNetworkSwiftExample-acknowledgements.plist │ │ ├── Pods-XHNetworkSwiftExample-frameworks.sh │ │ └── Pods-XHNetworkSwiftExample-resources.sh ├── Manifest.lock ├── Pods.xcodeproj │ └── xcuserdata │ │ └── xiaohui.xcuserdatad │ │ └── xcschemes │ │ ├── xcschememanagement.plist │ │ ├── Alamofire.xcscheme │ │ └── Pods-XHNetworkSwiftExample.xcscheme └── Alamofire │ ├── LICENSE │ └── Source │ ├── Notifications.swift │ ├── Result.swift │ ├── Response.swift │ ├── Error.swift │ ├── Stream.swift │ ├── Timeline.swift │ ├── Validation.swift │ ├── NetworkReachabilityManager.swift │ ├── Download.swift │ ├── ParameterEncoding.swift │ ├── Alamofire.swift │ ├── ServerTrustPolicy.swift │ ├── ResponseSerialization.swift │ └── Upload.swift ├── Podfile ├── XHNetworkSwiftExample.xcworkspace ├── xcuserdata │ └── xiaohui.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── contents.xcworkspacedata ├── XHNetworkSwiftExample.xcodeproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── xiaohui.xcuserdatad │ │ └── UserInterfaceState.xcuserstate ├── xcuserdata │ └── xiaohui.xcuserdatad │ │ └── xcschemes │ │ ├── xcschememanagement.plist │ │ └── XHNetworkSwiftExample.xcscheme └── project.pbxproj ├── Podfile.lock ├── XHNetworkSwiftExample ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Info.plist ├── AppDelegate.swift ├── ViewController.xib ├── Base.lproj │ └── LaunchScreen.storyboard └── ViewController.swift ├── LICENSE ├── README.md └── XHNetworkSwift └── XHNetwork.swift /Pods/Target Support Files/Alamofire/Alamofire-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | -------------------------------------------------------------------------------- /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-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Alamofire : NSObject 3 | @end 4 | @implementation PodsDummy_Alamofire 5 | @end 6 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | 2 | platform :ios, '8.0' 3 | 4 | inhibit_all_warnings! 5 | 6 | use_frameworks! 7 | 8 | target "XHNetworkSwiftExample" do 9 | 10 | pod 'Alamofire', '~> 3.4.1' 11 | 12 | end 13 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /XHNetworkSwiftExample.xcworkspace/xcuserdata/xiaohui.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CoderZhuXH/XHNetworkSwift/HEAD/XHNetworkSwiftExample.xcworkspace/xcuserdata/xiaohui.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-XHNetworkSwiftExample/Pods-XHNetworkSwiftExample.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_XHNetworkSwiftExample { 2 | umbrella header "Pods-XHNetworkSwiftExample-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-XHNetworkSwiftExample/Pods-XHNetworkSwiftExample-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_XHNetworkSwiftExample : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_XHNetworkSwiftExample 5 | @end 6 | -------------------------------------------------------------------------------- /XHNetworkSwiftExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-XHNetworkSwiftExample/Pods-XHNetworkSwiftExample-umbrella.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | FOUNDATION_EXPORT double Pods_XHNetworkSwiftExampleVersionNumber; 5 | FOUNDATION_EXPORT const unsigned char Pods_XHNetworkSwiftExampleVersionString[]; 6 | 7 | -------------------------------------------------------------------------------- /XHNetworkSwiftExample.xcodeproj/project.xcworkspace/xcuserdata/xiaohui.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CoderZhuXH/XHNetworkSwift/HEAD/XHNetworkSwiftExample.xcodeproj/project.xcworkspace/xcuserdata/xiaohui.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Alamofire (3.4.1) 3 | 4 | DEPENDENCIES: 5 | - Alamofire (~> 3.4.1) 6 | 7 | SPEC CHECKSUMS: 8 | Alamofire: 01a82e2f6c0f860ade35534c8dd88be61bdef40c 9 | 10 | PODFILE CHECKSUM: 8cc23ec9ca3e8c605863e41f2824c2a2a61dee66 11 | 12 | COCOAPODS: 1.1.0.beta.1 13 | -------------------------------------------------------------------------------- /Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Alamofire (3.4.1) 3 | 4 | DEPENDENCIES: 5 | - Alamofire (~> 3.4.1) 6 | 7 | SPEC CHECKSUMS: 8 | Alamofire: 01a82e2f6c0f860ade35534c8dd88be61bdef40c 9 | 10 | PODFILE CHECKSUM: 8cc23ec9ca3e8c605863e41f2824c2a2a61dee66 11 | 12 | COCOAPODS: 1.1.0.beta.1 13 | -------------------------------------------------------------------------------- /XHNetworkSwiftExample.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Alamofire/Alamofire.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/Alamofire 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" 4 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" "-suppress-warnings" 5 | PODS_BUILD_DIR = $BUILD_DIR 6 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_ROOT = ${SRCROOT} 8 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 9 | SKIP_INSTALL = YES 10 | -------------------------------------------------------------------------------- /XHNetworkSwiftExample.xcodeproj/xcuserdata/xiaohui.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | XHNetworkSwiftExample.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 4B2F7EA61D69928A00BD070E 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-XHNetworkSwiftExample/Pods-XHNetworkSwiftExample.debug.xcconfig: -------------------------------------------------------------------------------- 1 | EMBEDDED_CONTENT_CONTAINS_SWIFT = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/Alamofire" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 5 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/Alamofire/Alamofire.framework/Headers" 6 | OTHER_LDFLAGS = $(inherited) -framework "Alamofire" 7 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 8 | PODS_BUILD_DIR = $BUILD_DIR 9 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_ROOT = ${SRCROOT}/Pods 11 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-XHNetworkSwiftExample/Pods-XHNetworkSwiftExample.release.xcconfig: -------------------------------------------------------------------------------- 1 | EMBEDDED_CONTENT_CONTAINS_SWIFT = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/Alamofire" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 5 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/Alamofire/Alamofire.framework/Headers" 6 | OTHER_LDFLAGS = $(inherited) -framework "Alamofire" 7 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 8 | PODS_BUILD_DIR = $BUILD_DIR 9 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_ROOT = ${SRCROOT}/Pods 11 | -------------------------------------------------------------------------------- /XHNetworkSwiftExample/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 | } -------------------------------------------------------------------------------- /Pods/Pods.xcodeproj/xcuserdata/xiaohui.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Alamofire.xcscheme 8 | 9 | isShown 10 | 11 | 12 | Pods-XHNetworkSwiftExample.xcscheme 13 | 14 | isShown 15 | 16 | 17 | 18 | SuppressBuildableAutocreation 19 | 20 | 79C040AFDDCE1BCBF6D8B5EB0B85887F 21 | 22 | primary 23 | 24 | 25 | E90DADFF9BA114CD3C16080105BDADFD 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Alamofire/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 3.4.1 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-XHNetworkSwiftExample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Pods/Alamofire/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014-2016 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 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 XHNetworkSwift (https://github.com/CoderZhuXH/XHNetworkSwift) 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 | -------------------------------------------------------------------------------- /XHNetworkSwiftExample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSAppTransportSecurity 6 | 7 | NSAllowsArbitraryLoads 8 | 9 | 10 | CFBundleDevelopmentRegion 11 | en 12 | CFBundleExecutable 13 | $(EXECUTABLE_NAME) 14 | CFBundleIdentifier 15 | $(PRODUCT_BUNDLE_IDENTIFIER) 16 | CFBundleInfoDictionaryVersion 17 | 6.0 18 | CFBundleName 19 | $(PRODUCT_NAME) 20 | CFBundlePackageType 21 | APPL 22 | CFBundleShortVersionString 23 | 1.0 24 | CFBundleSignature 25 | ???? 26 | CFBundleVersion 27 | 1 28 | LSRequiresIPhoneOS 29 | 30 | UILaunchStoryboardName 31 | LaunchScreen 32 | UIRequiredDeviceCapabilities 33 | 34 | armv7 35 | 36 | UISupportedInterfaceOrientations 37 | 38 | UIInterfaceOrientationPortrait 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-XHNetworkSwiftExample/Pods-XHNetworkSwiftExample-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## Alamofire 5 | 6 | Copyright (c) 2014-2016 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 | Generated by CocoaPods - https://cocoapods.org 27 | -------------------------------------------------------------------------------- /Pods/Pods.xcodeproj/xcuserdata/xiaohui.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/Target Support Files/Pods-XHNetworkSwiftExample/Pods-XHNetworkSwiftExample-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-2016 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 | License 38 | MIT 39 | Title 40 | Alamofire 41 | Type 42 | PSGroupSpecifier 43 | 44 | 45 | FooterText 46 | Generated by CocoaPods - https://cocoapods.org 47 | Title 48 | 49 | Type 50 | PSGroupSpecifier 51 | 52 | 53 | StringsTable 54 | Acknowledgements 55 | Title 56 | Acknowledgements 57 | 58 | 59 | -------------------------------------------------------------------------------- /Pods/Alamofire/Source/Notifications.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Notifications.swift 3 | // 4 | // Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | import Foundation 26 | 27 | /// Contains all the `NSNotification` names posted by Alamofire with descriptions of each notification's payload. 28 | public struct Notifications { 29 | /// Used as a namespace for all `NSURLSessionTask` related notifications. 30 | public struct Task { 31 | /// Notification posted when an `NSURLSessionTask` is resumed. The notification `object` contains the resumed 32 | /// `NSURLSessionTask`. 33 | public static let DidResume = "com.alamofire.notifications.task.didResume" 34 | 35 | /// Notification posted when an `NSURLSessionTask` is suspended. The notification `object` contains the 36 | /// suspended `NSURLSessionTask`. 37 | public static let DidSuspend = "com.alamofire.notifications.task.didSuspend" 38 | 39 | /// Notification posted when an `NSURLSessionTask` is cancelled. The notification `object` contains the 40 | /// cancelled `NSURLSessionTask`. 41 | public static let DidCancel = "com.alamofire.notifications.task.didCancel" 42 | 43 | /// Notification posted when an `NSURLSessionTask` is completed. The notification `object` contains the 44 | /// completed `NSURLSessionTask`. 45 | public static let DidComplete = "com.alamofire.notifications.task.didComplete" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /XHNetworkSwiftExample/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // XHNetworkSwiftExample 4 | // 5 | // Created by xiaohui on 16/8/21. 6 | // Copyright © 2016年 returnoc.com. All rights reserved. 7 | // 代码地址:https://github.com/CoderZhuXH/XHNetworkSwift 8 | 9 | import UIKit 10 | 11 | 12 | @UIApplicationMain 13 | class AppDelegate: UIResponder, UIApplicationDelegate { 14 | 15 | var window: UIWindow? 16 | 17 | 18 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 19 | 20 | window = UIWindow(frame:UIScreen.mainScreen().bounds) 21 | window?.backgroundColor = UIColor.whiteColor() 22 | 23 | 24 | window?.rootViewController = UINavigationController(rootViewController:ViewController()) 25 | 26 | 27 | window?.makeKeyAndVisible() 28 | // Override point for customization after application launch. 29 | return true 30 | } 31 | 32 | func applicationWillResignActive(application: UIApplication) { 33 | // 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. 34 | // 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. 35 | } 36 | 37 | func applicationDidEnterBackground(application: UIApplication) { 38 | // 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. 39 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 40 | } 41 | 42 | func applicationWillEnterForeground(application: UIApplication) { 43 | // 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. 44 | } 45 | 46 | func applicationDidBecomeActive(application: UIApplication) { 47 | // 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. 48 | } 49 | 50 | func applicationWillTerminate(application: UIApplication) { 51 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 52 | } 53 | 54 | 55 | } 56 | 57 | -------------------------------------------------------------------------------- /Pods/Pods.xcodeproj/xcuserdata/xiaohui.xcuserdatad/xcschemes/Pods-XHNetworkSwiftExample.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 66 | 67 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /XHNetworkSwiftExample/ViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /XHNetworkSwiftExample/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 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /XHNetworkSwiftExample.xcodeproj/xcuserdata/xiaohui.xcuserdatad/xcschemes/XHNetworkSwiftExample.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 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-XHNetworkSwiftExample/Pods-XHNetworkSwiftExample-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="${TARGET_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} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements \"$1\"" 63 | /usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --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 "$BUILT_PRODUCTS_DIR/Alamofire/Alamofire.framework" 88 | fi 89 | if [[ "$CONFIGURATION" == "Release" ]]; then 90 | install_framework "$BUILT_PRODUCTS_DIR/Alamofire/Alamofire.framework" 91 | fi 92 | -------------------------------------------------------------------------------- /XHNetworkSwiftExample/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // XHNetworkSwiftExample 4 | // 5 | // Created by xiaohui on 16/8/21. 6 | // Copyright © 2016年 returnoc.com. All rights reserved. 7 | // 代码地址:https://github.com/CoderZhuXH/XHNetworkSwift 8 | 9 | import UIKit 10 | 11 | let SERVE = "http://aotuyuan.qinto.com/wl/Api.php/" 12 | //GET,POST测试URL 13 | let URL_TEST = SERVE + "Api/indexInformation" 14 | 15 | //下载测试URL 16 | let URL_DOWN = "http://120.25.226.186:32812/resources/videos/minion_01.mp4" 17 | 18 | 19 | class ViewController: UIViewController { 20 | 21 | @IBOutlet weak var textLab: UILabel! 22 | 23 | override func viewDidLoad() { 24 | super.viewDidLoad() 25 | 26 | textLab.text = "返回数据请看控制台打印, \n 详情见Github: https://github.com/CoderZhuXH/XHNetworkSwift" 27 | 28 | 29 | //MARK: - GET请求 30 | XHNetwork.shareNetwork.GET(URL_TEST, parameters: nil, success: { (response) in 31 | 32 | debugPrint(response) 33 | 34 | }) { (error) in 35 | 36 | debugPrint(error) 37 | } 38 | 39 | //MARK: - POST请求 40 | let dic = ["name":"zhang","phone":"10010"] 41 | XHNetwork.shareNetwork.POST(URL_TEST, parameters: dic, success: { (response) in 42 | 43 | debugPrint(response) 44 | 45 | }) { (error) in 46 | 47 | debugPrint(error) 48 | } 49 | 50 | 51 | //MARK: - 下载 52 | let savePathURL = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0] 53 | XHNetwork.shareNetwork.download(URL_DOWN, savePathURL: savePathURL 54 | , downloadProgress: { (bytesRead, totalBytesRead, totalBytesExpectedToRead) in 55 | 56 | /** 57 | * 子线程回调下载进度 58 | */ 59 | debugPrint("单次下载大小:\(bytesRead)___一共下载大小:\(totalBytesRead)___总大小:\(totalBytesExpectedToRead)") 60 | 61 | /** 62 | * 如需进行UI处理,请到主线程操作 63 | */ 64 | 65 | /* 66 | dispatch_async(dispatch_get_main_queue()) { 67 | 68 | //处理UI 69 | } 70 | */ 71 | 72 | }, success: { (response) in 73 | 74 | debugPrint(response) 75 | 76 | }) { (error) in 77 | 78 | debugPrint(error) 79 | } 80 | 81 | /* 82 | //MARK : - 文件上传 83 | 84 | XHNetwork.shareNetwork.upload(传上传URLString, fileURL: 传文件完整路径URL, uploadProgress: { (bytesWritten, totalBytesWritten, totalBytesExpectedToWrite) in 85 | 86 | /** 87 | * 子线程回调上传进度 88 | */ 89 | debugPrint("单次上传大小:\(bytesWritten)___一共上传大小:\(totalBytesWritten)___总大小:\(totalBytesExpectedToWrite)") 90 | 91 | /** 92 | * 如需进行UI处理,请到主线程操作 93 | */ 94 | 95 | /* 96 | dispatch_async(dispatch_get_main_queue()) { 97 | 98 | //处理UI 99 | } 100 | */ 101 | 102 | }, success: { (response) in 103 | 104 | debugPrint(response) 105 | 106 | }) { (error) in 107 | 108 | debugPrint(error) 109 | } 110 | 111 | 112 | */ 113 | // Do any additional setup after loading the view, typically from a nib. 114 | } 115 | 116 | 117 | 118 | 119 | override func didReceiveMemoryWarning() { 120 | super.didReceiveMemoryWarning() 121 | // Dispose of any resources that can be recreated. 122 | } 123 | 124 | 125 | } 126 | 127 | -------------------------------------------------------------------------------- /Pods/Alamofire/Source/Result.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Result.swift 3 | // 4 | // Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | import Foundation 26 | 27 | /** 28 | Used to represent whether a request was successful or encountered an error. 29 | 30 | - Success: The request and all post processing operations were successful resulting in the serialization of the 31 | provided associated value. 32 | - Failure: The request encountered an error resulting in a failure. The associated values are the original data 33 | provided by the server as well as the error that caused the failure. 34 | */ 35 | public enum Result { 36 | case Success(Value) 37 | case Failure(Error) 38 | 39 | /// Returns `true` if the result is a success, `false` otherwise. 40 | public var isSuccess: Bool { 41 | switch self { 42 | case .Success: 43 | return true 44 | case .Failure: 45 | return false 46 | } 47 | } 48 | 49 | /// Returns `true` if the result is a failure, `false` otherwise. 50 | public var isFailure: Bool { 51 | return !isSuccess 52 | } 53 | 54 | /// Returns the associated value if the result is a success, `nil` otherwise. 55 | public var value: Value? { 56 | switch self { 57 | case .Success(let value): 58 | return value 59 | case .Failure: 60 | return nil 61 | } 62 | } 63 | 64 | /// Returns the associated error value if the result is a failure, `nil` otherwise. 65 | public var error: Error? { 66 | switch self { 67 | case .Success: 68 | return nil 69 | case .Failure(let error): 70 | return error 71 | } 72 | } 73 | } 74 | 75 | // MARK: - CustomStringConvertible 76 | 77 | extension Result: CustomStringConvertible { 78 | /// The textual representation used when written to an output stream, which includes whether the result was a 79 | /// success or failure. 80 | public var description: String { 81 | switch self { 82 | case .Success: 83 | return "SUCCESS" 84 | case .Failure: 85 | return "FAILURE" 86 | } 87 | } 88 | } 89 | 90 | // MARK: - CustomDebugStringConvertible 91 | 92 | extension Result: CustomDebugStringConvertible { 93 | /// The debug textual representation used when written to an output stream, which includes whether the result was a 94 | /// success or failure in addition to the value or error. 95 | public var debugDescription: String { 96 | switch self { 97 | case .Success(let value): 98 | return "SUCCESS: \(value)" 99 | case .Failure(let error): 100 | return "FAILURE: \(error)" 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /Pods/Alamofire/Source/Response.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Response.swift 3 | // 4 | // Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | import Foundation 26 | 27 | /// Used to store all response data returned from a completed `Request`. 28 | public struct Response { 29 | /// The URL request sent to the server. 30 | public let request: NSURLRequest? 31 | 32 | /// The server's response to the URL request. 33 | public let response: NSHTTPURLResponse? 34 | 35 | /// The data returned by the server. 36 | public let data: NSData? 37 | 38 | /// The result of response serialization. 39 | public let result: Result 40 | 41 | /// The timeline of the complete lifecycle of the `Request`. 42 | public let timeline: Timeline 43 | 44 | /** 45 | Initializes the `Response` instance with the specified URL request, URL response, server data and response 46 | serialization result. 47 | 48 | - parameter request: The URL request sent to the server. 49 | - parameter response: The server's response to the URL request. 50 | - parameter data: The data returned by the server. 51 | - parameter result: The result of response serialization. 52 | - parameter timeline: The timeline of the complete lifecycle of the `Request`. Defaults to `Timeline()`. 53 | 54 | - returns: the new `Response` instance. 55 | */ 56 | public init( 57 | request: NSURLRequest?, 58 | response: NSHTTPURLResponse?, 59 | data: NSData?, 60 | result: Result, 61 | timeline: Timeline = Timeline()) 62 | { 63 | self.request = request 64 | self.response = response 65 | self.data = data 66 | self.result = result 67 | self.timeline = timeline 68 | } 69 | } 70 | 71 | // MARK: - CustomStringConvertible 72 | 73 | extension Response: CustomStringConvertible { 74 | /// The textual representation used when written to an output stream, which includes whether the result was a 75 | /// success or failure. 76 | public var description: String { 77 | return result.debugDescription 78 | } 79 | } 80 | 81 | // MARK: - CustomDebugStringConvertible 82 | 83 | extension Response: CustomDebugStringConvertible { 84 | /// The debug textual representation used when written to an output stream, which includes the URL request, the URL 85 | /// response, the server data and the response serialization result. 86 | public var debugDescription: String { 87 | var output: [String] = [] 88 | 89 | output.append(request != nil ? "[Request]: \(request!)" : "[Request]: nil") 90 | output.append(response != nil ? "[Response]: \(response!)" : "[Response]: nil") 91 | output.append("[Data]: \(data?.length ?? 0) bytes") 92 | output.append("[Result]: \(result.debugDescription)") 93 | output.append("[Timeline]: \(timeline.debugDescription)") 94 | 95 | return output.joinWithSeparator("\n") 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /Pods/Alamofire/Source/Error.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Error.swift 3 | // 4 | // Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | import Foundation 26 | 27 | /// The `Error` struct provides a convenience for creating custom Alamofire NSErrors. 28 | public struct Error { 29 | /// The domain used for creating all Alamofire errors. 30 | public static let Domain = "com.alamofire.error" 31 | 32 | /// The custom error codes generated by Alamofire. 33 | public enum Code: Int { 34 | case InputStreamReadFailed = -6000 35 | case OutputStreamWriteFailed = -6001 36 | case ContentTypeValidationFailed = -6002 37 | case StatusCodeValidationFailed = -6003 38 | case DataSerializationFailed = -6004 39 | case StringSerializationFailed = -6005 40 | case JSONSerializationFailed = -6006 41 | case PropertyListSerializationFailed = -6007 42 | } 43 | 44 | /// Custom keys contained within certain NSError `userInfo` dictionaries generated by Alamofire. 45 | public struct UserInfoKeys { 46 | /// The content type user info key for a `.ContentTypeValidationFailed` error stored as a `String` value. 47 | public static let ContentType = "ContentType" 48 | 49 | /// The status code user info key for a `.StatusCodeValidationFailed` error stored as an `Int` value. 50 | public static let StatusCode = "StatusCode" 51 | } 52 | 53 | /** 54 | Creates an `NSError` with the given error code and failure reason. 55 | 56 | - parameter code: The error code. 57 | - parameter failureReason: The failure reason. 58 | 59 | - returns: An `NSError` with the given error code and failure reason. 60 | */ 61 | @available(*, deprecated=3.4.0) 62 | public static func errorWithCode(code: Code, failureReason: String) -> NSError { 63 | return errorWithCode(code.rawValue, failureReason: failureReason) 64 | } 65 | 66 | /** 67 | Creates an `NSError` with the given error code and failure reason. 68 | 69 | - parameter code: The error code. 70 | - parameter failureReason: The failure reason. 71 | 72 | - returns: An `NSError` with the given error code and failure reason. 73 | */ 74 | @available(*, deprecated=3.4.0) 75 | public static func errorWithCode(code: Int, failureReason: String) -> NSError { 76 | let userInfo = [NSLocalizedFailureReasonErrorKey: failureReason] 77 | return NSError(domain: Domain, code: code, userInfo: userInfo) 78 | } 79 | 80 | static func error(domain domain: String = Error.Domain, code: Code, failureReason: String) -> NSError { 81 | return error(domain: domain, code: code.rawValue, failureReason: failureReason) 82 | } 83 | 84 | static func error(domain domain: String = Error.Domain, code: Int, failureReason: String) -> NSError { 85 | let userInfo = [NSLocalizedFailureReasonErrorKey: failureReason] 86 | return NSError(domain: domain, code: code, userInfo: userInfo) 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # XHNetworkSwift 2 | ### swift,基于Alamofire数据请求封装 3 | 4 | ###技术交流群(群号:537476189) 5 | 6 | ##API 7 | ```swift 8 | 9 | /** 10 | GET 请求 11 | 12 | - parameter urlString: 请求URL 13 | - parameter parameters: 请求参数 14 | - parameter success: 成功回调 15 | - parameter failure: 失败回调 16 | */ 17 | func GET(urlString: String ,parameters: [String : AnyObject]? ,success: NetworkSuccess, failure: NetworkFailure) 18 | 19 | 20 | /** 21 | POST请求 22 | 23 | - parameter urlString: 请求URL 24 | - parameter parameters: 请求参数 25 | - parameter success: 成功回调 26 | - parameter failure: 失败回调 27 | */ 28 | func POST(urlString: String ,parameters: [String : AnyObject]? ,success: NetworkSuccess, failure: NetworkFailure) 29 | 30 | 31 | /** 32 | 文件上传 33 | 34 | - parameter urlString: URL 35 | - parameter fileURL: 要上传文件路径URL(包含文件名) 36 | - parameter uploadProgress: 上传进度回调(子线程) 37 | - parameter success: 成功回调 38 | - parameter failure: 失败回调 39 | */ 40 | func upload(urlString: String ,fileURL:NSURL ,uploadProgress:UploadProgress, success: XHNetworkSuccess, failure: XHNetworkFailure) 41 | 42 | 43 | /** 44 | 文件下载 45 | 46 | - parameter urlString: 下载URL 47 | - parameter downloadProgress: 下载进度回调(子线程) 48 | - parameter fileSavePathURL: 文件存储路径URL(不含文件名) 49 | - parameter success: 成功回调 50 | - parameter failure: 失败回调 51 | */ 52 | func download(urlString: String ,savePathURL:NSURL ,downloadProgress: DownloadProgress, success: XHNetworkSuccess, failure: XHNetworkFailure) 53 | 54 | 55 | ``` 56 | ## 使用方法: 57 | ### 1.GET请求 58 | ```swift 59 | 60 | //MARK: - GET请求 61 | XHNetwork.shareNetwork.GET(URL_TEST, parameters: nil, success: { (response) in 62 | 63 | debugPrint(response) 64 | 65 | }) { (error) in 66 | 67 | debugPrint(error) 68 | } 69 | 70 | ``` 71 | ### 2.POST请求 72 | ```swift 73 | 74 | //MARK: - POST请求 75 | let dic = ["name":"zhang","phone":"10010"] 76 | XHNetwork.shareNetwork.POST(URL_TEST, parameters: dic, success: { (response) in 77 | 78 | debugPrint(response) 79 | 80 | }) { (error) in 81 | 82 | debugPrint(error) 83 | } 84 | 85 | ``` 86 | 87 | ### 3.文件下载 88 | ```swift 89 | 90 | //MARK: - 文件下载 91 | //文件保存路径 92 | let savePathURL = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0] 93 | XHNetwork.shareNetwork.download(URL_DOWN, savePathURL: savePathURL 94 | , downloadProgress: { (bytesRead, totalBytesRead, totalBytesExpectedToRead) in 95 | 96 | /** 97 | * 子线程回调下载进度 98 | */ 99 | debugPrint("单次下载大小:\(bytesRead)___一共下载大小:\(totalBytesRead)___总大小:\(totalBytesExpectedToRead)") 100 | 101 | /** 102 | * 如需进行UI处理,请到主线程操作 103 | */ 104 | dispatch_async(dispatch_get_main_queue()) { 105 | 106 | //处理UI 107 | } 108 | 109 | }, success: { (response) in 110 | 111 | /* 112 | 成功(回调文件存储路劲) 113 | */ 114 | 115 | debugPrint(response) 116 | 117 | }) { (error) in 118 | 119 | /* 120 | 失败 121 | */ 122 | 123 | debugPrint(error) 124 | } 125 | 126 | 127 | ``` 128 | 129 | ### 4.文件上传 130 | ```swift 131 | 132 | //MARK : - 文件上传 133 | XHNetwork.shareNetwork.upload(上传URLString , fileURL: 文件完整路径URL, uploadProgress: { (bytesWritten, totalBytesWritten, totalBytesExpectedToWrite) in 134 | 135 | /** 136 | * 子线程回调上传进度 137 | */ 138 | debugPrint("单次上传大小:\(bytesWritten)___一共上传大小:\(totalBytesWritten)___总大小:\(totalBytesExpectedToWrite)") 139 | 140 | /** 141 | * 如需进行UI处理,请到主线程操作 142 | */ 143 | dispatch_async(dispatch_get_main_queue()) { 144 | 145 | //处理UI 146 | } 147 | 148 | }, success: { (response) in 149 | 150 | /* 151 | 成功 152 | */ 153 | debugPrint(response) 154 | 155 | }) { (error) in 156 | 157 | /* 158 | 失败 159 | */ 160 | 161 | debugPrint(error) 162 | } 163 | 164 | ``` 165 | 166 | ## 安装 167 | ### 手动添加:
168 | * 1.将 XHNetworkSwift 文件夹添加到工程目录中即可
169 | 170 | ## 系统要求 171 | * 该项目最低支持 iOS 8.0 和 Xcode 7.3 172 | 173 | ## 许可证 174 | XHNetworkSwift 使用 MIT 许可证,详情见 LICENSE 文件 175 | ## 传送门: 176 | [Swift网络编程(一)数据请求](http://www.jianshu.com/p/f8643477e690)
177 | [Swift网络编程(二)文件上传/下载](http://www.jianshu.com/p/13e2dbc07481) -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-XHNetworkSwiftExample/Pods-XHNetworkSwiftExample-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | mkdir -p "${TARGET_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 | case "${TARGETED_DEVICE_FAMILY}" in 12 | 1,2) 13 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 14 | ;; 15 | 1) 16 | TARGET_DEVICE_ARGS="--target-device iphone" 17 | ;; 18 | 2) 19 | TARGET_DEVICE_ARGS="--target-device ipad" 20 | ;; 21 | *) 22 | TARGET_DEVICE_ARGS="--target-device mac" 23 | ;; 24 | esac 25 | 26 | realpath() { 27 | DIRECTORY="$(cd "${1%/*}" && pwd)" 28 | FILENAME="${1##*/}" 29 | echo "$DIRECTORY/$FILENAME" 30 | } 31 | 32 | install_resource() 33 | { 34 | if [[ "$1" = /* ]] ; then 35 | RESOURCE_PATH="$1" 36 | else 37 | RESOURCE_PATH="${PODS_ROOT}/$1" 38 | fi 39 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 40 | cat << EOM 41 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 42 | EOM 43 | exit 1 44 | fi 45 | case $RESOURCE_PATH in 46 | *.storyboard) 47 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" 48 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 49 | ;; 50 | *.xib) 51 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" 52 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 53 | ;; 54 | *.framework) 55 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 56 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 57 | echo "rsync -av $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 58 | rsync -av "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 59 | ;; 60 | *.xcdatamodel) 61 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" 62 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 63 | ;; 64 | *.xcdatamodeld) 65 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" 66 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 67 | ;; 68 | *.xcmappingmodel) 69 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" 70 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 71 | ;; 72 | *.xcassets) 73 | ABSOLUTE_XCASSET_FILE=$(realpath "$RESOURCE_PATH") 74 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 75 | ;; 76 | *) 77 | echo "$RESOURCE_PATH" 78 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 79 | ;; 80 | esac 81 | } 82 | 83 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 84 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 85 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 86 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 87 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 88 | fi 89 | rm -f "$RESOURCES_TO_COPY" 90 | 91 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] 92 | then 93 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 94 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 95 | while read line; do 96 | if [[ $line != "`realpath $PODS_ROOT`*" ]]; then 97 | XCASSET_FILES+=("$line") 98 | fi 99 | done <<<"$OTHER_XCASSETS" 100 | 101 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 102 | fi 103 | -------------------------------------------------------------------------------- /XHNetworkSwift/XHNetwork.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XHNetwork.swift 3 | // XHNetworkSwiftExample 4 | // 5 | // Created by xiaohui on 16/8/21. 6 | // Copyright © 2016年 returnoc.com. All rights reserved. 7 | // 代码地址:https://github.com/CoderZhuXH/XHNetworkSwift 8 | 9 | import UIKit 10 | import Alamofire 11 | 12 | class XHNetwork: NSObject { 13 | 14 | /** 15 | * 网络请求成功闭包: 16 | */ 17 | typealias XHNetworkSuccess = (response:AnyObject) -> () 18 | 19 | /** 20 | * 网络请求失败闭包: 21 | */ 22 | typealias XHNetworkFailure = (error:NSError) -> () 23 | 24 | /** 25 | * 上传进度闭包:(回调:1.单次上传大小 2.已经上传大小,3.文件总大小) 26 | */ 27 | typealias UploadProgress = (bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) -> () 28 | 29 | /** 30 | * 下载进度闭包:(回调:1.单次写入大小 2.已经写入大小,3.文件总大小) 31 | */ 32 | typealias DownloadProgress = (bytesRead:Int64, totalBytesRead:Int64, totalBytesExpectedToRead:Int64) -> () 33 | 34 | /** 35 | * 网络请求单例 36 | */ 37 | static let shareNetwork = XHNetwork() 38 | 39 | } 40 | //MARK: - 网络请求 41 | extension XHNetwork 42 | { 43 | 44 | /** 45 | GET 请求 46 | 47 | - parameter urlString: 请求URL 48 | - parameter parameters: 请求参数 49 | - parameter success: 成功回调 50 | - parameter failure: 失败回调 51 | */ 52 | func GET(urlString: String ,parameters: [String : AnyObject]? ,success: XHNetworkSuccess, failure: XHNetworkFailure){ 53 | 54 | /* 55 | responseJSON:申明返回JSON类型数据 56 | 你也可以根据实际需求,修改返回下列类型 57 | response 58 | responseData 59 | responseString 60 | responsePropertyList 61 | */ 62 | Alamofire.request(.GET, urlString, parameters: parameters).responseJSON { response in 63 | 64 | switch response.result { 65 | 66 | case .Success(let value): 67 | 68 | /** 69 | * 成功 70 | */ 71 | success(response:value) 72 | 73 | case .Failure(let error): 74 | 75 | /** 76 | * 失败 77 | */ 78 | failure(error:error) 79 | debugPrint(error) 80 | 81 | } 82 | } 83 | } 84 | 85 | /** 86 | POST请求 87 | 88 | - parameter urlString: 请求URL 89 | - parameter parameters: 请求参数 90 | - parameter success: 成功回调 91 | - parameter failure: 失败回调 92 | */ 93 | func POST(urlString: String ,parameters: [String : AnyObject]? ,success: XHNetworkSuccess, failure: XHNetworkFailure) { 94 | 95 | Alamofire.request(.POST, urlString, parameters: parameters).responseJSON { response in 96 | 97 | switch response.result { 98 | 99 | case .Success(let value): 100 | 101 | /** 102 | * 成功 103 | */ 104 | success(response: value) 105 | 106 | case .Failure(let error): 107 | 108 | /** 109 | * 失败 110 | */ 111 | failure(error: error) 112 | debugPrint(error) 113 | 114 | } 115 | } 116 | } 117 | 118 | /** 119 | 文件上传 120 | 121 | - parameter urlString: URL 122 | - parameter fileURL: 要上传文件路径URL(包含文件名) 123 | - parameter uploadProgress: 上传进度回调(子线程) 124 | - parameter success: 成功回调 125 | - parameter failure: 失败回调 126 | */ 127 | func upload(urlString: String ,fileURL:NSURL ,uploadProgress:UploadProgress, success: XHNetworkSuccess, failure: XHNetworkFailure){ 128 | 129 | Alamofire.upload(.POST,urlString, file: fileURL) 130 | .progress { bytesWritten, totalBytesWritten, totalBytesExpectedToWrite in 131 | 132 | /* 133 | bytesWritten 单次上传大小 134 | totalBytesWritten 已经上传了大小 135 | totalBytesExpectedToWrite 文件总大小 136 | */ 137 | 138 | /** 139 | * 子线程回调上传进度 140 | */ 141 | uploadProgress(bytesWritten:bytesWritten,totalBytesWritten:totalBytesWritten,totalBytesExpectedToWrite:totalBytesExpectedToWrite) 142 | 143 | } 144 | .validate() 145 | .responseJSON { response in 146 | 147 | switch response.result { 148 | 149 | case .Success(let value): 150 | 151 | /** 152 | * 成功 153 | */ 154 | success(response: value) 155 | 156 | case .Failure(let error): 157 | 158 | /** 159 | * 失败 160 | */ 161 | failure(error: error) 162 | debugPrint(error) 163 | 164 | } 165 | } 166 | 167 | } 168 | 169 | /** 170 | 文件下载 171 | 172 | - parameter urlString: 下载URL 173 | - parameter downloadProgress: 下载进度回调(子线程) 174 | - parameter fileSavePathURL: 文件存储路径URL(不含文件名) 175 | - parameter success: 成功回调 176 | - parameter failure: 失败回调 177 | */ 178 | func download(urlString: String ,savePathURL:NSURL ,downloadProgress: DownloadProgress, success: XHNetworkSuccess, failure: XHNetworkFailure){ 179 | 180 | Alamofire.download(.GET, urlString) { temporaryURL, response in 181 | 182 | let pathComponent = response.suggestedFilename//建议文件名 183 | return savePathURL.URLByAppendingPathComponent(pathComponent!) 184 | 185 | }.progress { bytesRead, totalBytesRead, totalBytesExpectedToRead in 186 | print(totalBytesRead) 187 | 188 | /* 189 | bytesRead 单次下载大小 190 | totalBytesRead 已经下载大小 191 | totalBytesExpectedToRead 文件总大小 192 | */ 193 | 194 | /** 195 | * 子线程回调下载进度 196 | */ 197 | downloadProgress(bytesRead:bytesRead,totalBytesRead:totalBytesRead,totalBytesExpectedToRead:totalBytesExpectedToRead) 198 | 199 | } 200 | .response { _, _, _, error in 201 | if let error = error { 202 | 203 | /** 204 | * 失败 205 | */ 206 | failure(error:error) 207 | debugPrint("Failed with error: \(error)") 208 | 209 | } else { 210 | 211 | /** 212 | * 成功 213 | */ 214 | success(response: savePathURL.absoluteString) 215 | 216 | } 217 | } 218 | } 219 | 220 | } 221 | -------------------------------------------------------------------------------- /Pods/Alamofire/Source/Stream.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Stream.swift 3 | // 4 | // Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | import Foundation 26 | 27 | #if !os(watchOS) 28 | 29 | @available(iOS 9.0, OSX 10.11, tvOS 9.0, *) 30 | extension Manager { 31 | private enum Streamable { 32 | case Stream(String, Int) 33 | case NetService(NSNetService) 34 | } 35 | 36 | private func stream(streamable: Streamable) -> Request { 37 | var streamTask: NSURLSessionStreamTask! 38 | 39 | switch streamable { 40 | case .Stream(let hostName, let port): 41 | dispatch_sync(queue) { 42 | streamTask = self.session.streamTaskWithHostName(hostName, port: port) 43 | } 44 | case .NetService(let netService): 45 | dispatch_sync(queue) { 46 | streamTask = self.session.streamTaskWithNetService(netService) 47 | } 48 | } 49 | 50 | let request = Request(session: session, task: streamTask) 51 | 52 | delegate[request.delegate.task] = request.delegate 53 | 54 | if startRequestsImmediately { 55 | request.resume() 56 | } 57 | 58 | return request 59 | } 60 | 61 | /** 62 | Creates a request for bidirectional streaming with the given hostname and port. 63 | 64 | - parameter hostName: The hostname of the server to connect to. 65 | - parameter port: The port of the server to connect to. 66 | 67 | :returns: The created stream request. 68 | */ 69 | public func stream(hostName hostName: String, port: Int) -> Request { 70 | return stream(.Stream(hostName, port)) 71 | } 72 | 73 | /** 74 | Creates a request for bidirectional streaming with the given `NSNetService`. 75 | 76 | - parameter netService: The net service used to identify the endpoint. 77 | 78 | - returns: The created stream request. 79 | */ 80 | public func stream(netService netService: NSNetService) -> Request { 81 | return stream(.NetService(netService)) 82 | } 83 | } 84 | 85 | // MARK: - 86 | 87 | @available(iOS 9.0, OSX 10.11, tvOS 9.0, *) 88 | extension Manager.SessionDelegate: NSURLSessionStreamDelegate { 89 | 90 | // MARK: Override Closures 91 | 92 | /// Overrides default behavior for NSURLSessionStreamDelegate method `URLSession:readClosedForStreamTask:`. 93 | public var streamTaskReadClosed: ((NSURLSession, NSURLSessionStreamTask) -> Void)? { 94 | get { 95 | return _streamTaskReadClosed as? (NSURLSession, NSURLSessionStreamTask) -> Void 96 | } 97 | set { 98 | _streamTaskReadClosed = newValue 99 | } 100 | } 101 | 102 | /// Overrides default behavior for NSURLSessionStreamDelegate method `URLSession:writeClosedForStreamTask:`. 103 | public var streamTaskWriteClosed: ((NSURLSession, NSURLSessionStreamTask) -> Void)? { 104 | get { 105 | return _streamTaskWriteClosed as? (NSURLSession, NSURLSessionStreamTask) -> Void 106 | } 107 | set { 108 | _streamTaskWriteClosed = newValue 109 | } 110 | } 111 | 112 | /// Overrides default behavior for NSURLSessionStreamDelegate method `URLSession:betterRouteDiscoveredForStreamTask:`. 113 | public var streamTaskBetterRouteDiscovered: ((NSURLSession, NSURLSessionStreamTask) -> Void)? { 114 | get { 115 | return _streamTaskBetterRouteDiscovered as? (NSURLSession, NSURLSessionStreamTask) -> Void 116 | } 117 | set { 118 | _streamTaskBetterRouteDiscovered = newValue 119 | } 120 | } 121 | 122 | /// Overrides default behavior for NSURLSessionStreamDelegate method `URLSession:streamTask:didBecomeInputStream:outputStream:`. 123 | public var streamTaskDidBecomeInputStream: ((NSURLSession, NSURLSessionStreamTask, NSInputStream, NSOutputStream) -> Void)? { 124 | get { 125 | return _streamTaskDidBecomeInputStream as? (NSURLSession, NSURLSessionStreamTask, NSInputStream, NSOutputStream) -> Void 126 | } 127 | set { 128 | _streamTaskDidBecomeInputStream = newValue 129 | } 130 | } 131 | 132 | // MARK: Delegate Methods 133 | 134 | /** 135 | Tells the delegate that the read side of the connection has been closed. 136 | 137 | - parameter session: The session. 138 | - parameter streamTask: The stream task. 139 | */ 140 | public func URLSession(session: NSURLSession, readClosedForStreamTask streamTask: NSURLSessionStreamTask) { 141 | streamTaskReadClosed?(session, streamTask) 142 | } 143 | 144 | /** 145 | Tells the delegate that the write side of the connection has been closed. 146 | 147 | - parameter session: The session. 148 | - parameter streamTask: The stream task. 149 | */ 150 | public func URLSession(session: NSURLSession, writeClosedForStreamTask streamTask: NSURLSessionStreamTask) { 151 | streamTaskWriteClosed?(session, streamTask) 152 | } 153 | 154 | /** 155 | Tells the delegate that the system has determined that a better route to the host is available. 156 | 157 | - parameter session: The session. 158 | - parameter streamTask: The stream task. 159 | */ 160 | public func URLSession(session: NSURLSession, betterRouteDiscoveredForStreamTask streamTask: NSURLSessionStreamTask) { 161 | streamTaskBetterRouteDiscovered?(session, streamTask) 162 | } 163 | 164 | /** 165 | Tells the delegate that the stream task has been completed and provides the unopened stream objects. 166 | 167 | - parameter session: The session. 168 | - parameter streamTask: The stream task. 169 | - parameter inputStream: The new input stream. 170 | - parameter outputStream: The new output stream. 171 | */ 172 | public func URLSession( 173 | session: NSURLSession, 174 | streamTask: NSURLSessionStreamTask, 175 | didBecomeInputStream inputStream: NSInputStream, 176 | outputStream: NSOutputStream) 177 | { 178 | streamTaskDidBecomeInputStream?(session, streamTask, inputStream, outputStream) 179 | } 180 | } 181 | 182 | #endif 183 | -------------------------------------------------------------------------------- /Pods/Alamofire/Source/Timeline.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Timeline.swift 3 | // 4 | // Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | import Foundation 26 | 27 | /// Responsible for computing the timing metrics for the complete lifecycle of a `Request`. 28 | public struct Timeline { 29 | /// The time the request was initialized. 30 | public let requestStartTime: CFAbsoluteTime 31 | 32 | /// The time the first bytes were received from or sent to the server. 33 | public let initialResponseTime: CFAbsoluteTime 34 | 35 | /// The time when the request was completed. 36 | public let requestCompletedTime: CFAbsoluteTime 37 | 38 | /// The time when the response serialization was completed. 39 | public let serializationCompletedTime: CFAbsoluteTime 40 | 41 | /// The time interval in seconds from the time the request started to the initial response from the server. 42 | public let latency: NSTimeInterval 43 | 44 | /// The time interval in seconds from the time the request started to the time the request completed. 45 | public let requestDuration: NSTimeInterval 46 | 47 | /// The time interval in seconds from the time the request completed to the time response serialization completed. 48 | public let serializationDuration: NSTimeInterval 49 | 50 | /// The time interval in seconds from the time the request started to the time response serialization completed. 51 | public let totalDuration: NSTimeInterval 52 | 53 | /** 54 | Creates a new `Timeline` instance with the specified request times. 55 | 56 | - parameter requestStartTime: The time the request was initialized. Defaults to `0.0`. 57 | - parameter initialResponseTime: The time the first bytes were received from or sent to the server. 58 | Defaults to `0.0`. 59 | - parameter requestCompletedTime: The time when the request was completed. Defaults to `0.0`. 60 | - parameter serializationCompletedTime: The time when the response serialization was completed. Defaults 61 | to `0.0`. 62 | 63 | - returns: The new `Timeline` instance. 64 | */ 65 | public init( 66 | requestStartTime: CFAbsoluteTime = 0.0, 67 | initialResponseTime: CFAbsoluteTime = 0.0, 68 | requestCompletedTime: CFAbsoluteTime = 0.0, 69 | serializationCompletedTime: CFAbsoluteTime = 0.0) 70 | { 71 | self.requestStartTime = requestStartTime 72 | self.initialResponseTime = initialResponseTime 73 | self.requestCompletedTime = requestCompletedTime 74 | self.serializationCompletedTime = serializationCompletedTime 75 | 76 | self.latency = initialResponseTime - requestStartTime 77 | self.requestDuration = requestCompletedTime - requestStartTime 78 | self.serializationDuration = serializationCompletedTime - requestCompletedTime 79 | self.totalDuration = serializationCompletedTime - requestStartTime 80 | } 81 | } 82 | 83 | // MARK: - CustomStringConvertible 84 | 85 | extension Timeline: CustomStringConvertible { 86 | /// The textual representation used when written to an output stream, which includes the latency, the request 87 | /// duration and the total duration. 88 | public var description: String { 89 | let latency = String(format: "%.3f", self.latency) 90 | let requestDuration = String(format: "%.3f", self.requestDuration) 91 | let serializationDuration = String(format: "%.3f", self.serializationDuration) 92 | let totalDuration = String(format: "%.3f", self.totalDuration) 93 | 94 | // NOTE: Had to move to string concatenation due to memory leak filed as rdar://26761490. Once memory leak is 95 | // fixed, we should move back to string interpolation by reverting commit 7d4a43b1. 96 | let timings = [ 97 | "\"Latency\": " + latency + " secs", 98 | "\"Request Duration\": " + requestDuration + " secs", 99 | "\"Serialization Duration\": " + serializationDuration + " secs", 100 | "\"Total Duration\": " + totalDuration + " secs" 101 | ] 102 | 103 | return "Timeline: { " + timings.joinWithSeparator(", ") + " }" 104 | } 105 | } 106 | 107 | // MARK: - CustomDebugStringConvertible 108 | 109 | extension Timeline: CustomDebugStringConvertible { 110 | /// The textual representation used when written to an output stream, which includes the request start time, the 111 | /// initial response time, the request completed time, the serialization completed time, the latency, the request 112 | /// duration and the total duration. 113 | public var debugDescription: String { 114 | let requestStartTime = String(format: "%.3f", self.requestStartTime) 115 | let initialResponseTime = String(format: "%.3f", self.initialResponseTime) 116 | let requestCompletedTime = String(format: "%.3f", self.requestCompletedTime) 117 | let serializationCompletedTime = String(format: "%.3f", self.serializationCompletedTime) 118 | let latency = String(format: "%.3f", self.latency) 119 | let requestDuration = String(format: "%.3f", self.requestDuration) 120 | let serializationDuration = String(format: "%.3f", self.serializationDuration) 121 | let totalDuration = String(format: "%.3f", self.totalDuration) 122 | 123 | // NOTE: Had to move to string concatenation due to memory leak filed as rdar://26761490. Once memory leak is 124 | // fixed, we should move back to string interpolation by reverting commit 7d4a43b1. 125 | let timings = [ 126 | "\"Request Start Time\": " + requestStartTime, 127 | "\"Initial Response Time\": " + initialResponseTime, 128 | "\"Request Completed Time\": " + requestCompletedTime, 129 | "\"Serialization Completed Time\": " + serializationCompletedTime, 130 | "\"Latency\": " + latency + " secs", 131 | "\"Request Duration\": " + requestDuration + " secs", 132 | "\"Serialization Duration\": " + serializationDuration + " secs", 133 | "\"Total Duration\": " + totalDuration + " secs" 134 | ] 135 | 136 | return "Timeline: { " + timings.joinWithSeparator(", ") + " }" 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /Pods/Alamofire/Source/Validation.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Validation.swift 3 | // 4 | // Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | import Foundation 26 | 27 | extension Request { 28 | 29 | /** 30 | Used to represent whether validation was successful or encountered an error resulting in a failure. 31 | 32 | - Success: The validation was successful. 33 | - Failure: The validation failed encountering the provided error. 34 | */ 35 | public enum ValidationResult { 36 | case Success 37 | case Failure(NSError) 38 | } 39 | 40 | /** 41 | A closure used to validate a request that takes a URL request and URL response, and returns whether the 42 | request was valid. 43 | */ 44 | public typealias Validation = (NSURLRequest?, NSHTTPURLResponse) -> ValidationResult 45 | 46 | /** 47 | Validates the request, using the specified closure. 48 | 49 | If validation fails, subsequent calls to response handlers will have an associated error. 50 | 51 | - parameter validation: A closure to validate the request. 52 | 53 | - returns: The request. 54 | */ 55 | public func validate(validation: Validation) -> Self { 56 | delegate.queue.addOperationWithBlock { 57 | if let 58 | response = self.response where self.delegate.error == nil, 59 | case let .Failure(error) = validation(self.request, response) 60 | { 61 | self.delegate.error = error 62 | } 63 | } 64 | 65 | return self 66 | } 67 | 68 | // MARK: - Status Code 69 | 70 | /** 71 | Validates that the response has a status code in the specified range. 72 | 73 | If validation fails, subsequent calls to response handlers will have an associated error. 74 | 75 | - parameter range: The range of acceptable status codes. 76 | 77 | - returns: The request. 78 | */ 79 | public func validate(statusCode acceptableStatusCode: S) -> Self { 80 | return validate { _, response in 81 | if acceptableStatusCode.contains(response.statusCode) { 82 | return .Success 83 | } else { 84 | let failureReason = "Response status code was unacceptable: \(response.statusCode)" 85 | 86 | let error = NSError( 87 | domain: Error.Domain, 88 | code: Error.Code.StatusCodeValidationFailed.rawValue, 89 | userInfo: [ 90 | NSLocalizedFailureReasonErrorKey: failureReason, 91 | Error.UserInfoKeys.StatusCode: response.statusCode 92 | ] 93 | ) 94 | 95 | return .Failure(error) 96 | } 97 | } 98 | } 99 | 100 | // MARK: - Content-Type 101 | 102 | private struct MIMEType { 103 | let type: String 104 | let subtype: String 105 | 106 | init?(_ string: String) { 107 | let components: [String] = { 108 | let stripped = string.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()) 109 | let split = stripped.substringToIndex(stripped.rangeOfString(";")?.startIndex ?? stripped.endIndex) 110 | return split.componentsSeparatedByString("/") 111 | }() 112 | 113 | if let 114 | type = components.first, 115 | subtype = components.last 116 | { 117 | self.type = type 118 | self.subtype = subtype 119 | } else { 120 | return nil 121 | } 122 | } 123 | 124 | func matches(MIME: MIMEType) -> Bool { 125 | switch (type, subtype) { 126 | case (MIME.type, MIME.subtype), (MIME.type, "*"), ("*", MIME.subtype), ("*", "*"): 127 | return true 128 | default: 129 | return false 130 | } 131 | } 132 | } 133 | 134 | /** 135 | Validates that the response has a content type in the specified array. 136 | 137 | If validation fails, subsequent calls to response handlers will have an associated error. 138 | 139 | - parameter contentType: The acceptable content types, which may specify wildcard types and/or subtypes. 140 | 141 | - returns: The request. 142 | */ 143 | public func validate(contentType acceptableContentTypes: S) -> Self { 144 | return validate { _, response in 145 | guard let validData = self.delegate.data where validData.length > 0 else { return .Success } 146 | 147 | if let 148 | responseContentType = response.MIMEType, 149 | responseMIMEType = MIMEType(responseContentType) 150 | { 151 | for contentType in acceptableContentTypes { 152 | if let acceptableMIMEType = MIMEType(contentType) where acceptableMIMEType.matches(responseMIMEType) { 153 | return .Success 154 | } 155 | } 156 | } else { 157 | for contentType in acceptableContentTypes { 158 | if let MIMEType = MIMEType(contentType) where MIMEType.type == "*" && MIMEType.subtype == "*" { 159 | return .Success 160 | } 161 | } 162 | } 163 | 164 | let contentType: String 165 | let failureReason: String 166 | 167 | if let responseContentType = response.MIMEType { 168 | contentType = responseContentType 169 | 170 | failureReason = ( 171 | "Response content type \"\(responseContentType)\" does not match any acceptable " + 172 | "content types: \(acceptableContentTypes)" 173 | ) 174 | } else { 175 | contentType = "" 176 | failureReason = "Response content type was missing and acceptable content type does not match \"*/*\"" 177 | } 178 | 179 | let error = NSError( 180 | domain: Error.Domain, 181 | code: Error.Code.ContentTypeValidationFailed.rawValue, 182 | userInfo: [ 183 | NSLocalizedFailureReasonErrorKey: failureReason, 184 | Error.UserInfoKeys.ContentType: contentType 185 | ] 186 | ) 187 | 188 | return .Failure(error) 189 | } 190 | } 191 | 192 | // MARK: - Automatic 193 | 194 | /** 195 | Validates that the response has a status code in the default acceptable range of 200...299, and that the content 196 | type matches any specified in the Accept HTTP header field. 197 | 198 | If validation fails, subsequent calls to response handlers will have an associated error. 199 | 200 | - returns: The request. 201 | */ 202 | public func validate() -> Self { 203 | let acceptableStatusCodes: Range = 200..<300 204 | let acceptableContentTypes: [String] = { 205 | if let accept = request?.valueForHTTPHeaderField("Accept") { 206 | return accept.componentsSeparatedByString(",") 207 | } 208 | 209 | return ["*/*"] 210 | }() 211 | 212 | return validate(statusCode: acceptableStatusCodes).validate(contentType: acceptableContentTypes) 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /Pods/Alamofire/Source/NetworkReachabilityManager.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NetworkReachabilityManager.swift 3 | // 4 | // Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | #if !os(watchOS) 26 | 27 | import Foundation 28 | import SystemConfiguration 29 | 30 | /** 31 | The `NetworkReachabilityManager` class listens for reachability changes of hosts and addresses for both WWAN and 32 | WiFi network interfaces. 33 | 34 | Reachability can be used to determine background information about why a network operation failed, or to retry 35 | network requests when a connection is established. It should not be used to prevent a user from initiating a network 36 | request, as it's possible that an initial request may be required to establish reachability. 37 | */ 38 | public class NetworkReachabilityManager { 39 | /** 40 | Defines the various states of network reachability. 41 | 42 | - Unknown: It is unknown whether the network is reachable. 43 | - NotReachable: The network is not reachable. 44 | - ReachableOnWWAN: The network is reachable over the WWAN connection. 45 | - ReachableOnWiFi: The network is reachable over the WiFi connection. 46 | */ 47 | public enum NetworkReachabilityStatus { 48 | case Unknown 49 | case NotReachable 50 | case Reachable(ConnectionType) 51 | } 52 | 53 | /** 54 | Defines the various connection types detected by reachability flags. 55 | 56 | - EthernetOrWiFi: The connection type is either over Ethernet or WiFi. 57 | - WWAN: The connection type is a WWAN connection. 58 | */ 59 | public enum ConnectionType { 60 | case EthernetOrWiFi 61 | case WWAN 62 | } 63 | 64 | /// A closure executed when the network reachability status changes. The closure takes a single argument: the 65 | /// network reachability status. 66 | public typealias Listener = NetworkReachabilityStatus -> Void 67 | 68 | // MARK: - Properties 69 | 70 | /// Whether the network is currently reachable. 71 | public var isReachable: Bool { return isReachableOnWWAN || isReachableOnEthernetOrWiFi } 72 | 73 | /// Whether the network is currently reachable over the WWAN interface. 74 | public var isReachableOnWWAN: Bool { return networkReachabilityStatus == .Reachable(.WWAN) } 75 | 76 | /// Whether the network is currently reachable over Ethernet or WiFi interface. 77 | public var isReachableOnEthernetOrWiFi: Bool { return networkReachabilityStatus == .Reachable(.EthernetOrWiFi) } 78 | 79 | /// The current network reachability status. 80 | public var networkReachabilityStatus: NetworkReachabilityStatus { 81 | guard let flags = self.flags else { return .Unknown } 82 | return networkReachabilityStatusForFlags(flags) 83 | } 84 | 85 | /// The dispatch queue to execute the `listener` closure on. 86 | public var listenerQueue: dispatch_queue_t = dispatch_get_main_queue() 87 | 88 | /// A closure executed when the network reachability status changes. 89 | public var listener: Listener? 90 | 91 | private var flags: SCNetworkReachabilityFlags? { 92 | var flags = SCNetworkReachabilityFlags() 93 | 94 | if SCNetworkReachabilityGetFlags(reachability, &flags) { 95 | return flags 96 | } 97 | 98 | return nil 99 | } 100 | 101 | private let reachability: SCNetworkReachability 102 | private var previousFlags: SCNetworkReachabilityFlags 103 | 104 | // MARK: - Initialization 105 | 106 | /** 107 | Creates a `NetworkReachabilityManager` instance with the specified host. 108 | 109 | - parameter host: The host used to evaluate network reachability. 110 | 111 | - returns: The new `NetworkReachabilityManager` instance. 112 | */ 113 | public convenience init?(host: String) { 114 | guard let reachability = SCNetworkReachabilityCreateWithName(nil, host) else { return nil } 115 | self.init(reachability: reachability) 116 | } 117 | 118 | /** 119 | Creates a `NetworkReachabilityManager` instance that monitors the address 0.0.0.0. 120 | 121 | Reachability treats the 0.0.0.0 address as a special token that causes it to monitor the general routing 122 | status of the device, both IPv4 and IPv6. 123 | 124 | - returns: The new `NetworkReachabilityManager` instance. 125 | */ 126 | public convenience init?() { 127 | var address = sockaddr_in() 128 | address.sin_len = UInt8(sizeofValue(address)) 129 | address.sin_family = sa_family_t(AF_INET) 130 | 131 | guard let reachability = withUnsafePointer(&address, { 132 | SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0)) 133 | }) else { return nil } 134 | 135 | self.init(reachability: reachability) 136 | } 137 | 138 | private init(reachability: SCNetworkReachability) { 139 | self.reachability = reachability 140 | self.previousFlags = SCNetworkReachabilityFlags() 141 | } 142 | 143 | deinit { 144 | stopListening() 145 | } 146 | 147 | // MARK: - Listening 148 | 149 | /** 150 | Starts listening for changes in network reachability status. 151 | 152 | - returns: `true` if listening was started successfully, `false` otherwise. 153 | */ 154 | public func startListening() -> Bool { 155 | var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil) 156 | context.info = UnsafeMutablePointer(Unmanaged.passUnretained(self).toOpaque()) 157 | 158 | let callbackEnabled = SCNetworkReachabilitySetCallback( 159 | reachability, 160 | { (_, flags, info) in 161 | let reachability = Unmanaged.fromOpaque(COpaquePointer(info)).takeUnretainedValue() 162 | reachability.notifyListener(flags) 163 | }, 164 | &context 165 | ) 166 | 167 | let queueEnabled = SCNetworkReachabilitySetDispatchQueue(reachability, listenerQueue) 168 | 169 | dispatch_async(listenerQueue) { 170 | self.previousFlags = SCNetworkReachabilityFlags() 171 | self.notifyListener(self.flags ?? SCNetworkReachabilityFlags()) 172 | } 173 | 174 | return callbackEnabled && queueEnabled 175 | } 176 | 177 | /** 178 | Stops listening for changes in network reachability status. 179 | */ 180 | public func stopListening() { 181 | SCNetworkReachabilitySetCallback(reachability, nil, nil) 182 | SCNetworkReachabilitySetDispatchQueue(reachability, nil) 183 | } 184 | 185 | // MARK: - Internal - Listener Notification 186 | 187 | func notifyListener(flags: SCNetworkReachabilityFlags) { 188 | guard previousFlags != flags else { return } 189 | previousFlags = flags 190 | 191 | listener?(networkReachabilityStatusForFlags(flags)) 192 | } 193 | 194 | // MARK: - Internal - Network Reachability Status 195 | 196 | func networkReachabilityStatusForFlags(flags: SCNetworkReachabilityFlags) -> NetworkReachabilityStatus { 197 | guard flags.contains(.Reachable) else { return .NotReachable } 198 | 199 | var networkStatus: NetworkReachabilityStatus = .NotReachable 200 | 201 | if !flags.contains(.ConnectionRequired) { networkStatus = .Reachable(.EthernetOrWiFi) } 202 | 203 | if flags.contains(.ConnectionOnDemand) || flags.contains(.ConnectionOnTraffic) { 204 | if !flags.contains(.InterventionRequired) { networkStatus = .Reachable(.EthernetOrWiFi) } 205 | } 206 | 207 | #if os(iOS) 208 | if flags.contains(.IsWWAN) { networkStatus = .Reachable(.WWAN) } 209 | #endif 210 | 211 | return networkStatus 212 | } 213 | } 214 | 215 | // MARK: - 216 | 217 | extension NetworkReachabilityManager.NetworkReachabilityStatus: Equatable {} 218 | 219 | /** 220 | Returns whether the two network reachability status values are equal. 221 | 222 | - parameter lhs: The left-hand side value to compare. 223 | - parameter rhs: The right-hand side value to compare. 224 | 225 | - returns: `true` if the two values are equal, `false` otherwise. 226 | */ 227 | public func ==( 228 | lhs: NetworkReachabilityManager.NetworkReachabilityStatus, 229 | rhs: NetworkReachabilityManager.NetworkReachabilityStatus) 230 | -> Bool 231 | { 232 | switch (lhs, rhs) { 233 | case (.Unknown, .Unknown): 234 | return true 235 | case (.NotReachable, .NotReachable): 236 | return true 237 | case let (.Reachable(lhsConnectionType), .Reachable(rhsConnectionType)): 238 | return lhsConnectionType == rhsConnectionType 239 | default: 240 | return false 241 | } 242 | } 243 | 244 | #endif 245 | -------------------------------------------------------------------------------- /Pods/Alamofire/Source/Download.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Download.swift 3 | // 4 | // Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | import Foundation 26 | 27 | extension Manager { 28 | private enum Downloadable { 29 | case Request(NSURLRequest) 30 | case ResumeData(NSData) 31 | } 32 | 33 | private func download(downloadable: Downloadable, destination: Request.DownloadFileDestination) -> Request { 34 | var downloadTask: NSURLSessionDownloadTask! 35 | 36 | switch downloadable { 37 | case .Request(let request): 38 | dispatch_sync(queue) { 39 | downloadTask = self.session.downloadTaskWithRequest(request) 40 | } 41 | case .ResumeData(let resumeData): 42 | dispatch_sync(queue) { 43 | downloadTask = self.session.downloadTaskWithResumeData(resumeData) 44 | } 45 | } 46 | 47 | let request = Request(session: session, task: downloadTask) 48 | 49 | if let downloadDelegate = request.delegate as? Request.DownloadTaskDelegate { 50 | downloadDelegate.downloadTaskDidFinishDownloadingToURL = { session, downloadTask, URL in 51 | return destination(URL, downloadTask.response as! NSHTTPURLResponse) 52 | } 53 | } 54 | 55 | delegate[request.delegate.task] = request.delegate 56 | 57 | if startRequestsImmediately { 58 | request.resume() 59 | } 60 | 61 | return request 62 | } 63 | 64 | // MARK: Request 65 | 66 | /** 67 | Creates a download request for the specified method, URL string, parameters, parameter encoding, headers 68 | and destination. 69 | 70 | If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. 71 | 72 | - parameter method: The HTTP method. 73 | - parameter URLString: The URL string. 74 | - parameter parameters: The parameters. `nil` by default. 75 | - parameter encoding: The parameter encoding. `.URL` by default. 76 | - parameter headers: The HTTP headers. `nil` by default. 77 | - parameter destination: The closure used to determine the destination of the downloaded file. 78 | 79 | - returns: The created download request. 80 | */ 81 | public func download( 82 | method: Method, 83 | _ URLString: URLStringConvertible, 84 | parameters: [String: AnyObject]? = nil, 85 | encoding: ParameterEncoding = .URL, 86 | headers: [String: String]? = nil, 87 | destination: Request.DownloadFileDestination) 88 | -> Request 89 | { 90 | let mutableURLRequest = URLRequest(method, URLString, headers: headers) 91 | let encodedURLRequest = encoding.encode(mutableURLRequest, parameters: parameters).0 92 | 93 | return download(encodedURLRequest, destination: destination) 94 | } 95 | 96 | /** 97 | Creates a request for downloading from the specified URL request. 98 | 99 | If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. 100 | 101 | - parameter URLRequest: The URL request 102 | - parameter destination: The closure used to determine the destination of the downloaded file. 103 | 104 | - returns: The created download request. 105 | */ 106 | public func download(URLRequest: URLRequestConvertible, destination: Request.DownloadFileDestination) -> Request { 107 | return download(.Request(URLRequest.URLRequest), destination: destination) 108 | } 109 | 110 | // MARK: Resume Data 111 | 112 | /** 113 | Creates a request for downloading from the resume data produced from a previous request cancellation. 114 | 115 | If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. 116 | 117 | - parameter resumeData: The resume data. This is an opaque data blob produced by `NSURLSessionDownloadTask` 118 | when a task is cancelled. See `NSURLSession -downloadTaskWithResumeData:` for 119 | additional information. 120 | - parameter destination: The closure used to determine the destination of the downloaded file. 121 | 122 | - returns: The created download request. 123 | */ 124 | public func download(resumeData: NSData, destination: Request.DownloadFileDestination) -> Request { 125 | return download(.ResumeData(resumeData), destination: destination) 126 | } 127 | } 128 | 129 | // MARK: - 130 | 131 | extension Request { 132 | /** 133 | A closure executed once a request has successfully completed in order to determine where to move the temporary 134 | file written to during the download process. The closure takes two arguments: the temporary file URL and the URL 135 | response, and returns a single argument: the file URL where the temporary file should be moved. 136 | */ 137 | public typealias DownloadFileDestination = (NSURL, NSHTTPURLResponse) -> NSURL 138 | 139 | /** 140 | Creates a download file destination closure which uses the default file manager to move the temporary file to a 141 | file URL in the first available directory with the specified search path directory and search path domain mask. 142 | 143 | - parameter directory: The search path directory. `.DocumentDirectory` by default. 144 | - parameter domain: The search path domain mask. `.UserDomainMask` by default. 145 | 146 | - returns: A download file destination closure. 147 | */ 148 | public class func suggestedDownloadDestination( 149 | directory directory: NSSearchPathDirectory = .DocumentDirectory, 150 | domain: NSSearchPathDomainMask = .UserDomainMask) 151 | -> DownloadFileDestination 152 | { 153 | return { temporaryURL, response -> NSURL in 154 | let directoryURLs = NSFileManager.defaultManager().URLsForDirectory(directory, inDomains: domain) 155 | 156 | if !directoryURLs.isEmpty { 157 | return directoryURLs[0].URLByAppendingPathComponent(response.suggestedFilename!) 158 | } 159 | 160 | return temporaryURL 161 | } 162 | } 163 | 164 | /// The resume data of the underlying download task if available after a failure. 165 | public var resumeData: NSData? { 166 | var data: NSData? 167 | 168 | if let delegate = delegate as? DownloadTaskDelegate { 169 | data = delegate.resumeData 170 | } 171 | 172 | return data 173 | } 174 | 175 | // MARK: - DownloadTaskDelegate 176 | 177 | class DownloadTaskDelegate: TaskDelegate, NSURLSessionDownloadDelegate { 178 | var downloadTask: NSURLSessionDownloadTask? { return task as? NSURLSessionDownloadTask } 179 | var downloadProgress: ((Int64, Int64, Int64) -> Void)? 180 | 181 | var resumeData: NSData? 182 | override var data: NSData? { return resumeData } 183 | 184 | // MARK: - NSURLSessionDownloadDelegate 185 | 186 | // MARK: Override Closures 187 | 188 | var downloadTaskDidFinishDownloadingToURL: ((NSURLSession, NSURLSessionDownloadTask, NSURL) -> NSURL)? 189 | var downloadTaskDidWriteData: ((NSURLSession, NSURLSessionDownloadTask, Int64, Int64, Int64) -> Void)? 190 | var downloadTaskDidResumeAtOffset: ((NSURLSession, NSURLSessionDownloadTask, Int64, Int64) -> Void)? 191 | 192 | // MARK: Delegate Methods 193 | 194 | func URLSession( 195 | session: NSURLSession, 196 | downloadTask: NSURLSessionDownloadTask, 197 | didFinishDownloadingToURL location: NSURL) 198 | { 199 | if let downloadTaskDidFinishDownloadingToURL = downloadTaskDidFinishDownloadingToURL { 200 | do { 201 | let destination = downloadTaskDidFinishDownloadingToURL(session, downloadTask, location) 202 | try NSFileManager.defaultManager().moveItemAtURL(location, toURL: destination) 203 | } catch { 204 | self.error = error as NSError 205 | } 206 | } 207 | } 208 | 209 | func URLSession( 210 | session: NSURLSession, 211 | downloadTask: NSURLSessionDownloadTask, 212 | didWriteData bytesWritten: Int64, 213 | totalBytesWritten: Int64, 214 | totalBytesExpectedToWrite: Int64) 215 | { 216 | if initialResponseTime == nil { initialResponseTime = CFAbsoluteTimeGetCurrent() } 217 | 218 | if let downloadTaskDidWriteData = downloadTaskDidWriteData { 219 | downloadTaskDidWriteData( 220 | session, 221 | downloadTask, 222 | bytesWritten, 223 | totalBytesWritten, 224 | totalBytesExpectedToWrite 225 | ) 226 | } else { 227 | progress.totalUnitCount = totalBytesExpectedToWrite 228 | progress.completedUnitCount = totalBytesWritten 229 | 230 | downloadProgress?(bytesWritten, totalBytesWritten, totalBytesExpectedToWrite) 231 | } 232 | } 233 | 234 | func URLSession( 235 | session: NSURLSession, 236 | downloadTask: NSURLSessionDownloadTask, 237 | didResumeAtOffset fileOffset: Int64, 238 | expectedTotalBytes: Int64) 239 | { 240 | if let downloadTaskDidResumeAtOffset = downloadTaskDidResumeAtOffset { 241 | downloadTaskDidResumeAtOffset(session, downloadTask, fileOffset, expectedTotalBytes) 242 | } else { 243 | progress.totalUnitCount = expectedTotalBytes 244 | progress.completedUnitCount = fileOffset 245 | } 246 | } 247 | } 248 | } 249 | -------------------------------------------------------------------------------- /Pods/Alamofire/Source/ParameterEncoding.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ParameterEncoding.swift 3 | // 4 | // Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | import Foundation 26 | 27 | /** 28 | HTTP method definitions. 29 | 30 | See https://tools.ietf.org/html/rfc7231#section-4.3 31 | */ 32 | public enum Method: String { 33 | case OPTIONS, GET, HEAD, POST, PUT, PATCH, DELETE, TRACE, CONNECT 34 | } 35 | 36 | // MARK: ParameterEncoding 37 | 38 | /** 39 | Used to specify the way in which a set of parameters are applied to a URL request. 40 | 41 | - `URL`: Creates a query string to be set as or appended to any existing URL query for `GET`, `HEAD`, 42 | and `DELETE` requests, or set as the body for requests with any other HTTP method. The 43 | `Content-Type` HTTP header field of an encoded request with HTTP body is set to 44 | `application/x-www-form-urlencoded; charset=utf-8`. Since there is no published specification 45 | for how to encode collection types, the convention of appending `[]` to the key for array 46 | values (`foo[]=1&foo[]=2`), and appending the key surrounded by square brackets for nested 47 | dictionary values (`foo[bar]=baz`). 48 | 49 | - `URLEncodedInURL`: Creates query string to be set as or appended to any existing URL query. Uses the same 50 | implementation as the `.URL` case, but always applies the encoded result to the URL. 51 | 52 | - `JSON`: Uses `NSJSONSerialization` to create a JSON representation of the parameters object, which is 53 | set as the body of the request. The `Content-Type` HTTP header field of an encoded request is 54 | set to `application/json`. 55 | 56 | - `PropertyList`: Uses `NSPropertyListSerialization` to create a plist representation of the parameters object, 57 | according to the associated format and write options values, which is set as the body of the 58 | request. The `Content-Type` HTTP header field of an encoded request is set to 59 | `application/x-plist`. 60 | 61 | - `Custom`: Uses the associated closure value to construct a new request given an existing request and 62 | parameters. 63 | */ 64 | public enum ParameterEncoding { 65 | case URL 66 | case URLEncodedInURL 67 | case JSON 68 | case PropertyList(NSPropertyListFormat, NSPropertyListWriteOptions) 69 | case Custom((URLRequestConvertible, [String: AnyObject]?) -> (NSMutableURLRequest, NSError?)) 70 | 71 | /** 72 | Creates a URL request by encoding parameters and applying them onto an existing request. 73 | 74 | - parameter URLRequest: The request to have parameters applied. 75 | - parameter parameters: The parameters to apply. 76 | 77 | - returns: A tuple containing the constructed request and the error that occurred during parameter encoding, 78 | if any. 79 | */ 80 | public func encode( 81 | URLRequest: URLRequestConvertible, 82 | parameters: [String: AnyObject]?) 83 | -> (NSMutableURLRequest, NSError?) 84 | { 85 | var mutableURLRequest = URLRequest.URLRequest 86 | 87 | guard let parameters = parameters else { return (mutableURLRequest, nil) } 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 122 | URLComponents = NSURLComponents(URL: mutableURLRequest.URL!, resolvingAgainstBaseURL: false) 123 | where !parameters.isEmpty 124 | { 125 | let percentEncodedQuery = (URLComponents.percentEncodedQuery.map { $0 + "&" } ?? "") + query(parameters) 126 | URLComponents.percentEncodedQuery = percentEncodedQuery 127 | mutableURLRequest.URL = URLComponents.URL 128 | } 129 | } else { 130 | if mutableURLRequest.valueForHTTPHeaderField("Content-Type") == nil { 131 | mutableURLRequest.setValue( 132 | "application/x-www-form-urlencoded; charset=utf-8", 133 | forHTTPHeaderField: "Content-Type" 134 | ) 135 | } 136 | 137 | mutableURLRequest.HTTPBody = query(parameters).dataUsingEncoding( 138 | NSUTF8StringEncoding, 139 | allowLossyConversion: false 140 | ) 141 | } 142 | case .JSON: 143 | do { 144 | let options = NSJSONWritingOptions() 145 | let data = try NSJSONSerialization.dataWithJSONObject(parameters, options: options) 146 | 147 | if mutableURLRequest.valueForHTTPHeaderField("Content-Type") == nil { 148 | mutableURLRequest.setValue("application/json", forHTTPHeaderField: "Content-Type") 149 | } 150 | 151 | mutableURLRequest.HTTPBody = data 152 | } catch { 153 | encodingError = error as NSError 154 | } 155 | case .PropertyList(let format, let options): 156 | do { 157 | let data = try NSPropertyListSerialization.dataWithPropertyList( 158 | parameters, 159 | format: format, 160 | options: options 161 | ) 162 | 163 | if mutableURLRequest.valueForHTTPHeaderField("Content-Type") == nil { 164 | mutableURLRequest.setValue("application/x-plist", forHTTPHeaderField: "Content-Type") 165 | } 166 | 167 | mutableURLRequest.HTTPBody = data 168 | } catch { 169 | encodingError = error as NSError 170 | } 171 | case .Custom(let closure): 172 | (mutableURLRequest, encodingError) = closure(mutableURLRequest, parameters) 173 | } 174 | 175 | return (mutableURLRequest, encodingError) 176 | } 177 | 178 | /** 179 | Creates percent-escaped, URL encoded query string components from the given key-value pair using recursion. 180 | 181 | - parameter key: The key of the query component. 182 | - parameter value: The value of the query component. 183 | 184 | - returns: The percent-escaped, URL encoded query string components. 185 | */ 186 | public func queryComponents(key: String, _ value: AnyObject) -> [(String, String)] { 187 | var components: [(String, String)] = [] 188 | 189 | if let dictionary = value as? [String: AnyObject] { 190 | for (nestedKey, value) in dictionary { 191 | components += queryComponents("\(key)[\(nestedKey)]", value) 192 | } 193 | } else if let array = value as? [AnyObject] { 194 | for value in array { 195 | components += queryComponents("\(key)[]", value) 196 | } 197 | } else { 198 | components.append((escape(key), escape("\(value)"))) 199 | } 200 | 201 | return components 202 | } 203 | 204 | /** 205 | Returns a percent-escaped string following RFC 3986 for a query string key or value. 206 | 207 | RFC 3986 states that the following characters are "reserved" characters. 208 | 209 | - General Delimiters: ":", "#", "[", "]", "@", "?", "/" 210 | - Sub-Delimiters: "!", "$", "&", "'", "(", ")", "*", "+", ",", ";", "=" 211 | 212 | In RFC 3986 - Section 3.4, it states that the "?" and "/" characters should not be escaped to allow 213 | query strings to include a URL. Therefore, all "reserved" characters with the exception of "?" and "/" 214 | should be percent-escaped in the query string. 215 | 216 | - parameter string: The string to be percent-escaped. 217 | 218 | - returns: The percent-escaped string. 219 | */ 220 | public func escape(string: String) -> String { 221 | let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4 222 | let subDelimitersToEncode = "!$&'()*+,;=" 223 | 224 | let allowedCharacterSet = NSCharacterSet.URLQueryAllowedCharacterSet().mutableCopy() as! NSMutableCharacterSet 225 | allowedCharacterSet.removeCharactersInString(generalDelimitersToEncode + subDelimitersToEncode) 226 | 227 | var escaped = "" 228 | 229 | //========================================================================================================== 230 | // 231 | // Batching is required for escaping due to an internal bug in iOS 8.1 and 8.2. Encoding more than a few 232 | // hundred Chinese characters causes various malloc error crashes. To avoid this issue until iOS 8 is no 233 | // longer supported, batching MUST be used for encoding. This introduces roughly a 20% overhead. For more 234 | // info, please refer to: 235 | // 236 | // - https://github.com/Alamofire/Alamofire/issues/206 237 | // 238 | //========================================================================================================== 239 | 240 | if #available(iOS 8.3, OSX 10.10, *) { 241 | escaped = string.stringByAddingPercentEncodingWithAllowedCharacters(allowedCharacterSet) ?? string 242 | } else { 243 | let batchSize = 50 244 | var index = string.startIndex 245 | 246 | while index != string.endIndex { 247 | let startIndex = index 248 | let endIndex = index.advancedBy(batchSize, limit: string.endIndex) 249 | let range = startIndex.. NSMutableURLRequest 93 | { 94 | let mutableURLRequest = NSMutableURLRequest(URL: NSURL(string: URLString.URLString)!) 95 | mutableURLRequest.HTTPMethod = method.rawValue 96 | 97 | if let headers = headers { 98 | for (headerField, headerValue) in headers { 99 | mutableURLRequest.setValue(headerValue, forHTTPHeaderField: headerField) 100 | } 101 | } 102 | 103 | return mutableURLRequest 104 | } 105 | 106 | // MARK: - Request Methods 107 | 108 | /** 109 | Creates a request using the shared manager instance for the specified method, URL string, parameters, and 110 | parameter encoding. 111 | 112 | - parameter method: The HTTP method. 113 | - parameter URLString: The URL string. 114 | - parameter parameters: The parameters. `nil` by default. 115 | - parameter encoding: The parameter encoding. `.URL` by default. 116 | - parameter headers: The HTTP headers. `nil` by default. 117 | 118 | - returns: The created request. 119 | */ 120 | public func request( 121 | method: Method, 122 | _ URLString: URLStringConvertible, 123 | parameters: [String: AnyObject]? = nil, 124 | encoding: ParameterEncoding = .URL, 125 | headers: [String: String]? = nil) 126 | -> Request 127 | { 128 | return Manager.sharedInstance.request( 129 | method, 130 | URLString, 131 | parameters: parameters, 132 | encoding: encoding, 133 | headers: headers 134 | ) 135 | } 136 | 137 | /** 138 | Creates a request using the shared manager instance for the specified URL request. 139 | 140 | If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. 141 | 142 | - parameter URLRequest: The URL request 143 | 144 | - returns: The created request. 145 | */ 146 | public func request(URLRequest: URLRequestConvertible) -> Request { 147 | return Manager.sharedInstance.request(URLRequest.URLRequest) 148 | } 149 | 150 | // MARK: - Upload Methods 151 | 152 | // MARK: File 153 | 154 | /** 155 | Creates an upload request using the shared manager instance for the specified method, URL string, and file. 156 | 157 | - parameter method: The HTTP method. 158 | - parameter URLString: The URL string. 159 | - parameter headers: The HTTP headers. `nil` by default. 160 | - parameter file: The file to upload. 161 | 162 | - returns: The created upload request. 163 | */ 164 | public func upload( 165 | method: Method, 166 | _ URLString: URLStringConvertible, 167 | headers: [String: String]? = nil, 168 | file: NSURL) 169 | -> Request 170 | { 171 | return Manager.sharedInstance.upload(method, URLString, headers: headers, file: file) 172 | } 173 | 174 | /** 175 | Creates an upload request using the shared manager instance for the specified URL request and file. 176 | 177 | - parameter URLRequest: The URL request. 178 | - parameter file: The file to upload. 179 | 180 | - returns: The created upload request. 181 | */ 182 | public func upload(URLRequest: URLRequestConvertible, file: NSURL) -> Request { 183 | return Manager.sharedInstance.upload(URLRequest, file: file) 184 | } 185 | 186 | // MARK: Data 187 | 188 | /** 189 | Creates an upload request using the shared manager instance for the specified method, URL string, and data. 190 | 191 | - parameter method: The HTTP method. 192 | - parameter URLString: The URL string. 193 | - parameter headers: The HTTP headers. `nil` by default. 194 | - parameter data: The data to upload. 195 | 196 | - returns: The created upload request. 197 | */ 198 | public func upload( 199 | method: Method, 200 | _ URLString: URLStringConvertible, 201 | headers: [String: String]? = nil, 202 | data: NSData) 203 | -> Request 204 | { 205 | return Manager.sharedInstance.upload(method, URLString, headers: headers, data: data) 206 | } 207 | 208 | /** 209 | Creates an upload request using the shared manager instance for the specified URL request and data. 210 | 211 | - parameter URLRequest: The URL request. 212 | - parameter data: The data to upload. 213 | 214 | - returns: The created upload request. 215 | */ 216 | public func upload(URLRequest: URLRequestConvertible, data: NSData) -> Request { 217 | return Manager.sharedInstance.upload(URLRequest, data: data) 218 | } 219 | 220 | // MARK: Stream 221 | 222 | /** 223 | Creates an upload request using the shared manager instance for the specified method, URL string, and stream. 224 | 225 | - parameter method: The HTTP method. 226 | - parameter URLString: The URL string. 227 | - parameter headers: The HTTP headers. `nil` by default. 228 | - parameter stream: The stream to upload. 229 | 230 | - returns: The created upload request. 231 | */ 232 | public func upload( 233 | method: Method, 234 | _ URLString: URLStringConvertible, 235 | headers: [String: String]? = nil, 236 | stream: NSInputStream) 237 | -> Request 238 | { 239 | return Manager.sharedInstance.upload(method, URLString, headers: headers, stream: stream) 240 | } 241 | 242 | /** 243 | Creates an upload request using the shared manager instance for the specified URL request and stream. 244 | 245 | - parameter URLRequest: The URL request. 246 | - parameter stream: The stream to upload. 247 | 248 | - returns: The created upload request. 249 | */ 250 | public func upload(URLRequest: URLRequestConvertible, stream: NSInputStream) -> Request { 251 | return Manager.sharedInstance.upload(URLRequest, stream: stream) 252 | } 253 | 254 | // MARK: MultipartFormData 255 | 256 | /** 257 | Creates an upload request using the shared manager instance for the specified method and URL string. 258 | 259 | - parameter method: The HTTP method. 260 | - parameter URLString: The URL string. 261 | - parameter headers: The HTTP headers. `nil` by default. 262 | - parameter multipartFormData: The closure used to append body parts to the `MultipartFormData`. 263 | - parameter encodingMemoryThreshold: The encoding memory threshold in bytes. 264 | `MultipartFormDataEncodingMemoryThreshold` by default. 265 | - parameter encodingCompletion: The closure called when the `MultipartFormData` encoding is complete. 266 | */ 267 | public func upload( 268 | method: Method, 269 | _ URLString: URLStringConvertible, 270 | headers: [String: String]? = nil, 271 | multipartFormData: MultipartFormData -> Void, 272 | encodingMemoryThreshold: UInt64 = Manager.MultipartFormDataEncodingMemoryThreshold, 273 | encodingCompletion: (Manager.MultipartFormDataEncodingResult -> Void)?) 274 | { 275 | return Manager.sharedInstance.upload( 276 | method, 277 | URLString, 278 | headers: headers, 279 | multipartFormData: multipartFormData, 280 | encodingMemoryThreshold: encodingMemoryThreshold, 281 | encodingCompletion: encodingCompletion 282 | ) 283 | } 284 | 285 | /** 286 | Creates an upload request using the shared manager instance for the specified method and URL string. 287 | 288 | - parameter URLRequest: The URL request. 289 | - parameter multipartFormData: The closure used to append body parts to the `MultipartFormData`. 290 | - parameter encodingMemoryThreshold: The encoding memory threshold in bytes. 291 | `MultipartFormDataEncodingMemoryThreshold` by default. 292 | - parameter encodingCompletion: The closure called when the `MultipartFormData` encoding is complete. 293 | */ 294 | public func upload( 295 | URLRequest: URLRequestConvertible, 296 | multipartFormData: MultipartFormData -> Void, 297 | encodingMemoryThreshold: UInt64 = Manager.MultipartFormDataEncodingMemoryThreshold, 298 | encodingCompletion: (Manager.MultipartFormDataEncodingResult -> Void)?) 299 | { 300 | return Manager.sharedInstance.upload( 301 | URLRequest, 302 | multipartFormData: multipartFormData, 303 | encodingMemoryThreshold: encodingMemoryThreshold, 304 | encodingCompletion: encodingCompletion 305 | ) 306 | } 307 | 308 | // MARK: - Download Methods 309 | 310 | // MARK: URL Request 311 | 312 | /** 313 | Creates a download request using the shared manager instance for the specified method and URL string. 314 | 315 | - parameter method: The HTTP method. 316 | - parameter URLString: The URL string. 317 | - parameter parameters: The parameters. `nil` by default. 318 | - parameter encoding: The parameter encoding. `.URL` by default. 319 | - parameter headers: The HTTP headers. `nil` by default. 320 | - parameter destination: The closure used to determine the destination of the downloaded file. 321 | 322 | - returns: The created download request. 323 | */ 324 | public func download( 325 | method: Method, 326 | _ URLString: URLStringConvertible, 327 | parameters: [String: AnyObject]? = nil, 328 | encoding: ParameterEncoding = .URL, 329 | headers: [String: String]? = nil, 330 | destination: Request.DownloadFileDestination) 331 | -> Request 332 | { 333 | return Manager.sharedInstance.download( 334 | method, 335 | URLString, 336 | parameters: parameters, 337 | encoding: encoding, 338 | headers: headers, 339 | destination: destination 340 | ) 341 | } 342 | 343 | /** 344 | Creates a download request using the shared manager instance for the specified URL request. 345 | 346 | - parameter URLRequest: The URL request. 347 | - parameter destination: The closure used to determine the destination of the downloaded file. 348 | 349 | - returns: The created download request. 350 | */ 351 | public func download(URLRequest: URLRequestConvertible, destination: Request.DownloadFileDestination) -> Request { 352 | return Manager.sharedInstance.download(URLRequest, destination: destination) 353 | } 354 | 355 | // MARK: Resume Data 356 | 357 | /** 358 | Creates a request using the shared manager instance for downloading from the resume data produced from a 359 | previous request cancellation. 360 | 361 | - parameter resumeData: The resume data. This is an opaque data blob produced by `NSURLSessionDownloadTask` 362 | when a task is cancelled. See `NSURLSession -downloadTaskWithResumeData:` for additional 363 | information. 364 | - parameter destination: The closure used to determine the destination of the downloaded file. 365 | 366 | - returns: The created download request. 367 | */ 368 | public func download(resumeData data: NSData, destination: Request.DownloadFileDestination) -> Request { 369 | return Manager.sharedInstance.download(data, destination: destination) 370 | } 371 | -------------------------------------------------------------------------------- /Pods/Alamofire/Source/ServerTrustPolicy.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ServerTrustPolicy.swift 3 | // 4 | // Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | import Foundation 26 | 27 | /// Responsible for managing the mapping of `ServerTrustPolicy` objects to a given host. 28 | public class ServerTrustPolicyManager { 29 | /// The dictionary of policies mapped to a particular host. 30 | public let policies: [String: ServerTrustPolicy] 31 | 32 | /** 33 | Initializes the `ServerTrustPolicyManager` instance with the given policies. 34 | 35 | Since different servers and web services can have different leaf certificates, intermediate and even root 36 | certficates, it is important to have the flexibility to specify evaluation policies on a per host basis. This 37 | allows for scenarios such as using default evaluation for host1, certificate pinning for host2, public key 38 | pinning for host3 and disabling evaluation for host4. 39 | 40 | - parameter policies: A dictionary of all policies mapped to a particular host. 41 | 42 | - returns: The new `ServerTrustPolicyManager` instance. 43 | */ 44 | public init(policies: [String: ServerTrustPolicy]) { 45 | self.policies = policies 46 | } 47 | 48 | /** 49 | Returns the `ServerTrustPolicy` for the given host if applicable. 50 | 51 | By default, this method will return the policy that perfectly matches the given host. Subclasses could override 52 | this method and implement more complex mapping implementations such as wildcards. 53 | 54 | - parameter host: The host to use when searching for a matching policy. 55 | 56 | - returns: The server trust policy for the given host if found. 57 | */ 58 | public func serverTrustPolicyForHost(host: String) -> ServerTrustPolicy? { 59 | return policies[host] 60 | } 61 | } 62 | 63 | // MARK: - 64 | 65 | extension NSURLSession { 66 | private struct AssociatedKeys { 67 | static var ManagerKey = "NSURLSession.ServerTrustPolicyManager" 68 | } 69 | 70 | var serverTrustPolicyManager: ServerTrustPolicyManager? { 71 | get { 72 | return objc_getAssociatedObject(self, &AssociatedKeys.ManagerKey) as? ServerTrustPolicyManager 73 | } 74 | set (manager) { 75 | objc_setAssociatedObject(self, &AssociatedKeys.ManagerKey, manager, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) 76 | } 77 | } 78 | } 79 | 80 | // MARK: - ServerTrustPolicy 81 | 82 | /** 83 | The `ServerTrustPolicy` evaluates the server trust generally provided by an `NSURLAuthenticationChallenge` when 84 | connecting to a server over a secure HTTPS connection. The policy configuration then evaluates the server trust 85 | with a given set of criteria to determine whether the server trust is valid and the connection should be made. 86 | 87 | Using pinned certificates or public keys for evaluation helps prevent man-in-the-middle (MITM) attacks and other 88 | vulnerabilities. Applications dealing with sensitive customer data or financial information are strongly encouraged 89 | to route all communication over an HTTPS connection with pinning enabled. 90 | 91 | - PerformDefaultEvaluation: Uses the default server trust evaluation while allowing you to control whether to 92 | validate the host provided by the challenge. Applications are encouraged to always 93 | validate the host in production environments to guarantee the validity of the server's 94 | certificate chain. 95 | 96 | - PinCertificates: Uses the pinned certificates to validate the server trust. The server trust is 97 | considered valid if one of the pinned certificates match one of the server certificates. 98 | By validating both the certificate chain and host, certificate pinning provides a very 99 | secure form of server trust validation mitigating most, if not all, MITM attacks. 100 | Applications are encouraged to always validate the host and require a valid certificate 101 | chain in production environments. 102 | 103 | - PinPublicKeys: Uses the pinned public keys to validate the server trust. The server trust is considered 104 | valid if one of the pinned public keys match one of the server certificate public keys. 105 | By validating both the certificate chain and host, public key pinning provides a very 106 | secure form of server trust validation mitigating most, if not all, MITM attacks. 107 | Applications are encouraged to always validate the host and require a valid certificate 108 | chain in production environments. 109 | 110 | - DisableEvaluation: Disables all evaluation which in turn will always consider any server trust as valid. 111 | 112 | - CustomEvaluation: Uses the associated closure to evaluate the validity of the server trust. 113 | */ 114 | public enum ServerTrustPolicy { 115 | case PerformDefaultEvaluation(validateHost: Bool) 116 | case PinCertificates(certificates: [SecCertificate], validateCertificateChain: Bool, validateHost: Bool) 117 | case PinPublicKeys(publicKeys: [SecKey], validateCertificateChain: Bool, validateHost: Bool) 118 | case DisableEvaluation 119 | case CustomEvaluation((serverTrust: SecTrust, host: String) -> Bool) 120 | 121 | // MARK: - Bundle Location 122 | 123 | /** 124 | Returns all certificates within the given bundle with a `.cer` file extension. 125 | 126 | - parameter bundle: The bundle to search for all `.cer` files. 127 | 128 | - returns: All certificates within the given bundle. 129 | */ 130 | public static func certificatesInBundle(bundle: NSBundle = NSBundle.mainBundle()) -> [SecCertificate] { 131 | var certificates: [SecCertificate] = [] 132 | 133 | let paths = Set([".cer", ".CER", ".crt", ".CRT", ".der", ".DER"].map { fileExtension in 134 | bundle.pathsForResourcesOfType(fileExtension, inDirectory: nil) 135 | }.flatten()) 136 | 137 | for path in paths { 138 | if let 139 | certificateData = NSData(contentsOfFile: path), 140 | certificate = SecCertificateCreateWithData(nil, certificateData) 141 | { 142 | certificates.append(certificate) 143 | } 144 | } 145 | 146 | return certificates 147 | } 148 | 149 | /** 150 | Returns all public keys within the given bundle with a `.cer` file extension. 151 | 152 | - parameter bundle: The bundle to search for all `*.cer` files. 153 | 154 | - returns: All public keys within the given bundle. 155 | */ 156 | public static func publicKeysInBundle(bundle: NSBundle = NSBundle.mainBundle()) -> [SecKey] { 157 | var publicKeys: [SecKey] = [] 158 | 159 | for certificate in certificatesInBundle(bundle) { 160 | if let publicKey = publicKeyForCertificate(certificate) { 161 | publicKeys.append(publicKey) 162 | } 163 | } 164 | 165 | return publicKeys 166 | } 167 | 168 | // MARK: - Evaluation 169 | 170 | /** 171 | Evaluates whether the server trust is valid for the given host. 172 | 173 | - parameter serverTrust: The server trust to evaluate. 174 | - parameter host: The host of the challenge protection space. 175 | 176 | - returns: Whether the server trust is valid. 177 | */ 178 | public func evaluateServerTrust(serverTrust: SecTrust, isValidForHost host: String) -> Bool { 179 | var serverTrustIsValid = false 180 | 181 | switch self { 182 | case let .PerformDefaultEvaluation(validateHost): 183 | let policy = SecPolicyCreateSSL(true, validateHost ? host as CFString : nil) 184 | SecTrustSetPolicies(serverTrust, [policy]) 185 | 186 | serverTrustIsValid = trustIsValid(serverTrust) 187 | case let .PinCertificates(pinnedCertificates, validateCertificateChain, validateHost): 188 | if validateCertificateChain { 189 | let policy = SecPolicyCreateSSL(true, validateHost ? host as CFString : nil) 190 | SecTrustSetPolicies(serverTrust, [policy]) 191 | 192 | SecTrustSetAnchorCertificates(serverTrust, pinnedCertificates) 193 | SecTrustSetAnchorCertificatesOnly(serverTrust, true) 194 | 195 | serverTrustIsValid = trustIsValid(serverTrust) 196 | } else { 197 | let serverCertificatesDataArray = certificateDataForTrust(serverTrust) 198 | let pinnedCertificatesDataArray = certificateDataForCertificates(pinnedCertificates) 199 | 200 | outerLoop: for serverCertificateData in serverCertificatesDataArray { 201 | for pinnedCertificateData in pinnedCertificatesDataArray { 202 | if serverCertificateData.isEqualToData(pinnedCertificateData) { 203 | serverTrustIsValid = true 204 | break outerLoop 205 | } 206 | } 207 | } 208 | } 209 | case let .PinPublicKeys(pinnedPublicKeys, validateCertificateChain, validateHost): 210 | var certificateChainEvaluationPassed = true 211 | 212 | if validateCertificateChain { 213 | let policy = SecPolicyCreateSSL(true, validateHost ? host as CFString : nil) 214 | SecTrustSetPolicies(serverTrust, [policy]) 215 | 216 | certificateChainEvaluationPassed = trustIsValid(serverTrust) 217 | } 218 | 219 | if certificateChainEvaluationPassed { 220 | outerLoop: for serverPublicKey in ServerTrustPolicy.publicKeysForTrust(serverTrust) as [AnyObject] { 221 | for pinnedPublicKey in pinnedPublicKeys as [AnyObject] { 222 | if serverPublicKey.isEqual(pinnedPublicKey) { 223 | serverTrustIsValid = true 224 | break outerLoop 225 | } 226 | } 227 | } 228 | } 229 | case .DisableEvaluation: 230 | serverTrustIsValid = true 231 | case let .CustomEvaluation(closure): 232 | serverTrustIsValid = closure(serverTrust: serverTrust, host: host) 233 | } 234 | 235 | return serverTrustIsValid 236 | } 237 | 238 | // MARK: - Private - Trust Validation 239 | 240 | private func trustIsValid(trust: SecTrust) -> Bool { 241 | var isValid = false 242 | 243 | var result = SecTrustResultType(kSecTrustResultInvalid) 244 | let status = SecTrustEvaluate(trust, &result) 245 | 246 | if status == errSecSuccess { 247 | let unspecified = SecTrustResultType(kSecTrustResultUnspecified) 248 | let proceed = SecTrustResultType(kSecTrustResultProceed) 249 | 250 | isValid = result == unspecified || result == proceed 251 | } 252 | 253 | return isValid 254 | } 255 | 256 | // MARK: - Private - Certificate Data 257 | 258 | private func certificateDataForTrust(trust: SecTrust) -> [NSData] { 259 | var certificates: [SecCertificate] = [] 260 | 261 | for index in 0.. [NSData] { 271 | return certificates.map { SecCertificateCopyData($0) as NSData } 272 | } 273 | 274 | // MARK: - Private - Public Key Extraction 275 | 276 | private static func publicKeysForTrust(trust: SecTrust) -> [SecKey] { 277 | var publicKeys: [SecKey] = [] 278 | 279 | for index in 0.. SecKey? { 292 | var publicKey: SecKey? 293 | 294 | let policy = SecPolicyCreateBasicX509() 295 | var trust: SecTrust? 296 | let trustCreationStatus = SecTrustCreateWithCertificates(certificate, policy, &trust) 297 | 298 | if let trust = trust where trustCreationStatus == errSecSuccess { 299 | publicKey = SecTrustCopyPublicKey(trust) 300 | } 301 | 302 | return publicKey 303 | } 304 | } 305 | -------------------------------------------------------------------------------- /Pods/Alamofire/Source/ResponseSerialization.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ResponseSerialization.swift 3 | // 4 | // Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | import Foundation 26 | 27 | // MARK: ResponseSerializer 28 | 29 | /** 30 | The type in which all response serializers must conform to in order to serialize a response. 31 | */ 32 | public protocol ResponseSerializerType { 33 | /// The type of serialized object to be created by this `ResponseSerializerType`. 34 | associatedtype SerializedObject 35 | 36 | /// The type of error to be created by this `ResponseSerializer` if serialization fails. 37 | associatedtype ErrorObject: ErrorType 38 | 39 | /** 40 | A closure used by response handlers that takes a request, response, data and error and returns a result. 41 | */ 42 | var serializeResponse: (NSURLRequest?, NSHTTPURLResponse?, NSData?, NSError?) -> Result { get } 43 | } 44 | 45 | // MARK: - 46 | 47 | /** 48 | A generic `ResponseSerializerType` used to serialize a request, response, and data into a serialized object. 49 | */ 50 | public struct ResponseSerializer: ResponseSerializerType { 51 | /// The type of serialized object to be created by this `ResponseSerializer`. 52 | public typealias SerializedObject = Value 53 | 54 | /// The type of error to be created by this `ResponseSerializer` if serialization fails. 55 | public typealias ErrorObject = Error 56 | 57 | /** 58 | A closure used by response handlers that takes a request, response, data and error and returns a result. 59 | */ 60 | public var serializeResponse: (NSURLRequest?, NSHTTPURLResponse?, NSData?, NSError?) -> Result 61 | 62 | /** 63 | Initializes the `ResponseSerializer` instance with the given serialize response closure. 64 | 65 | - parameter serializeResponse: The closure used to serialize the response. 66 | 67 | - returns: The new generic response serializer instance. 68 | */ 69 | public init(serializeResponse: (NSURLRequest?, NSHTTPURLResponse?, NSData?, NSError?) -> Result) { 70 | self.serializeResponse = serializeResponse 71 | } 72 | } 73 | 74 | // MARK: - Default 75 | 76 | extension Request { 77 | 78 | /** 79 | Adds a handler to be called once the request has finished. 80 | 81 | - parameter queue: The queue on which the completion handler is dispatched. 82 | - parameter completionHandler: The code to be executed once the request has finished. 83 | 84 | - returns: The request. 85 | */ 86 | public func response( 87 | queue queue: dispatch_queue_t? = nil, 88 | completionHandler: (NSURLRequest?, NSHTTPURLResponse?, NSData?, NSError?) -> Void) 89 | -> Self 90 | { 91 | delegate.queue.addOperationWithBlock { 92 | dispatch_async(queue ?? dispatch_get_main_queue()) { 93 | completionHandler(self.request, self.response, self.delegate.data, self.delegate.error) 94 | } 95 | } 96 | 97 | return self 98 | } 99 | 100 | /** 101 | Adds a handler to be called once the request has finished. 102 | 103 | - parameter queue: The queue on which the completion handler is dispatched. 104 | - parameter responseSerializer: The response serializer responsible for serializing the request, response, 105 | and data. 106 | - parameter completionHandler: The code to be executed once the request has finished. 107 | 108 | - returns: The request. 109 | */ 110 | public func response( 111 | queue queue: dispatch_queue_t? = nil, 112 | responseSerializer: T, 113 | completionHandler: Response -> Void) 114 | -> Self 115 | { 116 | delegate.queue.addOperationWithBlock { 117 | let result = responseSerializer.serializeResponse( 118 | self.request, 119 | self.response, 120 | self.delegate.data, 121 | self.delegate.error 122 | ) 123 | 124 | let requestCompletedTime = self.endTime ?? CFAbsoluteTimeGetCurrent() 125 | let initialResponseTime = self.delegate.initialResponseTime ?? requestCompletedTime 126 | 127 | let timeline = Timeline( 128 | requestStartTime: self.startTime ?? CFAbsoluteTimeGetCurrent(), 129 | initialResponseTime: initialResponseTime, 130 | requestCompletedTime: requestCompletedTime, 131 | serializationCompletedTime: CFAbsoluteTimeGetCurrent() 132 | ) 133 | 134 | let response = Response( 135 | request: self.request, 136 | response: self.response, 137 | data: self.delegate.data, 138 | result: result, 139 | timeline: timeline 140 | ) 141 | 142 | dispatch_async(queue ?? dispatch_get_main_queue()) { completionHandler(response) } 143 | } 144 | 145 | return self 146 | } 147 | } 148 | 149 | // MARK: - Data 150 | 151 | extension Request { 152 | 153 | /** 154 | Creates a response serializer that returns the associated data as-is. 155 | 156 | - returns: A data response serializer. 157 | */ 158 | public static func dataResponseSerializer() -> ResponseSerializer { 159 | return ResponseSerializer { _, response, data, error in 160 | guard error == nil else { return .Failure(error!) } 161 | 162 | if let response = response where response.statusCode == 204 { return .Success(NSData()) } 163 | 164 | guard let validData = data else { 165 | let failureReason = "Data could not be serialized. Input data was nil." 166 | let error = Error.error(code: .DataSerializationFailed, failureReason: failureReason) 167 | return .Failure(error) 168 | } 169 | 170 | return .Success(validData) 171 | } 172 | } 173 | 174 | /** 175 | Adds a handler to be called once the request has finished. 176 | 177 | - parameter completionHandler: The code to be executed once the request has finished. 178 | 179 | - returns: The request. 180 | */ 181 | public func responseData( 182 | queue queue: dispatch_queue_t? = nil, 183 | completionHandler: Response -> Void) 184 | -> Self 185 | { 186 | return response(queue: queue, responseSerializer: Request.dataResponseSerializer(), completionHandler: completionHandler) 187 | } 188 | } 189 | 190 | // MARK: - String 191 | 192 | extension Request { 193 | 194 | /** 195 | Creates a response serializer that returns a string initialized from the response data with the specified 196 | string encoding. 197 | 198 | - parameter encoding: The string encoding. If `nil`, the string encoding will be determined from the server 199 | response, falling back to the default HTTP default character set, ISO-8859-1. 200 | 201 | - returns: A string response serializer. 202 | */ 203 | public static func stringResponseSerializer( 204 | encoding encoding: NSStringEncoding? = nil) 205 | -> ResponseSerializer 206 | { 207 | return ResponseSerializer { _, response, data, error in 208 | guard error == nil else { return .Failure(error!) } 209 | 210 | if let response = response where response.statusCode == 204 { return .Success("") } 211 | 212 | guard let validData = data else { 213 | let failureReason = "String could not be serialized. Input data was nil." 214 | let error = Error.error(code: .StringSerializationFailed, failureReason: failureReason) 215 | return .Failure(error) 216 | } 217 | 218 | var convertedEncoding = encoding 219 | 220 | if let encodingName = response?.textEncodingName where convertedEncoding == nil { 221 | convertedEncoding = CFStringConvertEncodingToNSStringEncoding( 222 | CFStringConvertIANACharSetNameToEncoding(encodingName) 223 | ) 224 | } 225 | 226 | let actualEncoding = convertedEncoding ?? NSISOLatin1StringEncoding 227 | 228 | if let string = String(data: validData, encoding: actualEncoding) { 229 | return .Success(string) 230 | } else { 231 | let failureReason = "String could not be serialized with encoding: \(actualEncoding)" 232 | let error = Error.error(code: .StringSerializationFailed, failureReason: failureReason) 233 | return .Failure(error) 234 | } 235 | } 236 | } 237 | 238 | /** 239 | Adds a handler to be called once the request has finished. 240 | 241 | - parameter encoding: The string encoding. If `nil`, the string encoding will be determined from the 242 | server response, falling back to the default HTTP default character set, 243 | ISO-8859-1. 244 | - parameter completionHandler: A closure to be executed once the request has finished. 245 | 246 | - returns: The request. 247 | */ 248 | public func responseString( 249 | queue queue: dispatch_queue_t? = nil, 250 | encoding: NSStringEncoding? = nil, 251 | completionHandler: Response -> Void) 252 | -> Self 253 | { 254 | return response( 255 | queue: queue, 256 | responseSerializer: Request.stringResponseSerializer(encoding: encoding), 257 | completionHandler: completionHandler 258 | ) 259 | } 260 | } 261 | 262 | // MARK: - JSON 263 | 264 | extension Request { 265 | 266 | /** 267 | Creates a response serializer that returns a JSON object constructed from the response data using 268 | `NSJSONSerialization` with the specified reading options. 269 | 270 | - parameter options: The JSON serialization reading options. `.AllowFragments` by default. 271 | 272 | - returns: A JSON object response serializer. 273 | */ 274 | public static func JSONResponseSerializer( 275 | options options: NSJSONReadingOptions = .AllowFragments) 276 | -> ResponseSerializer 277 | { 278 | return ResponseSerializer { _, response, data, error in 279 | guard error == nil else { return .Failure(error!) } 280 | 281 | if let response = response where response.statusCode == 204 { return .Success(NSNull()) } 282 | 283 | guard let validData = data where validData.length > 0 else { 284 | let failureReason = "JSON could not be serialized. Input data was nil or zero length." 285 | let error = Error.error(code: .JSONSerializationFailed, failureReason: failureReason) 286 | return .Failure(error) 287 | } 288 | 289 | do { 290 | let JSON = try NSJSONSerialization.JSONObjectWithData(validData, options: options) 291 | return .Success(JSON) 292 | } catch { 293 | return .Failure(error as NSError) 294 | } 295 | } 296 | } 297 | 298 | /** 299 | Adds a handler to be called once the request has finished. 300 | 301 | - parameter options: The JSON serialization reading options. `.AllowFragments` by default. 302 | - parameter completionHandler: A closure to be executed once the request has finished. 303 | 304 | - returns: The request. 305 | */ 306 | public func responseJSON( 307 | queue queue: dispatch_queue_t? = nil, 308 | options: NSJSONReadingOptions = .AllowFragments, 309 | completionHandler: Response -> Void) 310 | -> Self 311 | { 312 | return response( 313 | queue: queue, 314 | responseSerializer: Request.JSONResponseSerializer(options: options), 315 | completionHandler: completionHandler 316 | ) 317 | } 318 | } 319 | 320 | // MARK: - Property List 321 | 322 | extension Request { 323 | 324 | /** 325 | Creates a response serializer that returns an object constructed from the response data using 326 | `NSPropertyListSerialization` with the specified reading options. 327 | 328 | - parameter options: The property list reading options. `NSPropertyListReadOptions()` by default. 329 | 330 | - returns: A property list object response serializer. 331 | */ 332 | public static func propertyListResponseSerializer( 333 | options options: NSPropertyListReadOptions = NSPropertyListReadOptions()) 334 | -> ResponseSerializer 335 | { 336 | return ResponseSerializer { _, response, data, error in 337 | guard error == nil else { return .Failure(error!) } 338 | 339 | if let response = response where response.statusCode == 204 { return .Success(NSNull()) } 340 | 341 | guard let validData = data where validData.length > 0 else { 342 | let failureReason = "Property list could not be serialized. Input data was nil or zero length." 343 | let error = Error.error(code: .PropertyListSerializationFailed, failureReason: failureReason) 344 | return .Failure(error) 345 | } 346 | 347 | do { 348 | let plist = try NSPropertyListSerialization.propertyListWithData(validData, options: options, format: nil) 349 | return .Success(plist) 350 | } catch { 351 | return .Failure(error as NSError) 352 | } 353 | } 354 | } 355 | 356 | /** 357 | Adds a handler to be called once the request has finished. 358 | 359 | - parameter options: The property list reading options. `0` by default. 360 | - parameter completionHandler: A closure to be executed once the request has finished. The closure takes 3 361 | arguments: the URL request, the URL response, the server data and the result 362 | produced while creating the property list. 363 | 364 | - returns: The request. 365 | */ 366 | public func responsePropertyList( 367 | queue queue: dispatch_queue_t? = nil, 368 | options: NSPropertyListReadOptions = NSPropertyListReadOptions(), 369 | completionHandler: Response -> Void) 370 | -> Self 371 | { 372 | return response( 373 | queue: queue, 374 | responseSerializer: Request.propertyListResponseSerializer(options: options), 375 | completionHandler: completionHandler 376 | ) 377 | } 378 | } 379 | -------------------------------------------------------------------------------- /XHNetworkSwiftExample.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 4B2F7EAB1D69928A00BD070E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B2F7EAA1D69928A00BD070E /* AppDelegate.swift */; }; 11 | 4B2F7EAD1D69928A00BD070E /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B2F7EAC1D69928A00BD070E /* ViewController.swift */; }; 12 | 4B2F7EB21D69928A00BD070E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4B2F7EB11D69928A00BD070E /* Assets.xcassets */; }; 13 | 4B2F7EB51D69928A00BD070E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4B2F7EB31D69928A00BD070E /* LaunchScreen.storyboard */; }; 14 | 4B2F7EBE1D69934500BD070E /* XHNetwork.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B2F7EBD1D69934500BD070E /* XHNetwork.swift */; }; 15 | 4B56B9571D69A57C00BB43B8 /* ViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4B56B9561D69A57C00BB43B8 /* ViewController.xib */; }; 16 | DEA76C94DDAC80B813A27DFE /* Pods_XHNetworkSwiftExample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 81759C250E430BF30DB03B34 /* Pods_XHNetworkSwiftExample.framework */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXFileReference section */ 20 | 09CE44AEF785F1E7B97E367D /* Pods-XHNetworkSwiftExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-XHNetworkSwiftExample.release.xcconfig"; path = "Pods/Target Support Files/Pods-XHNetworkSwiftExample/Pods-XHNetworkSwiftExample.release.xcconfig"; sourceTree = ""; }; 21 | 0D7A8F1787090DE017F02A96 /* Pods-XHNetworkSwiftExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-XHNetworkSwiftExample.debug.xcconfig"; path = "Pods/Target Support Files/Pods-XHNetworkSwiftExample/Pods-XHNetworkSwiftExample.debug.xcconfig"; sourceTree = ""; }; 22 | 4B2F7EA71D69928A00BD070E /* XHNetworkSwiftExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = XHNetworkSwiftExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 23 | 4B2F7EAA1D69928A00BD070E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 24 | 4B2F7EAC1D69928A00BD070E /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 25 | 4B2F7EB11D69928A00BD070E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 26 | 4B2F7EB41D69928A00BD070E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 27 | 4B2F7EB61D69928A00BD070E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 28 | 4B2F7EBD1D69934500BD070E /* XHNetwork.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XHNetwork.swift; sourceTree = ""; }; 29 | 4B56B9561D69A57C00BB43B8 /* ViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ViewController.xib; sourceTree = ""; }; 30 | 81759C250E430BF30DB03B34 /* Pods_XHNetworkSwiftExample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_XHNetworkSwiftExample.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 31 | /* End PBXFileReference section */ 32 | 33 | /* Begin PBXFrameworksBuildPhase section */ 34 | 4B2F7EA41D69928A00BD070E /* Frameworks */ = { 35 | isa = PBXFrameworksBuildPhase; 36 | buildActionMask = 2147483647; 37 | files = ( 38 | DEA76C94DDAC80B813A27DFE /* Pods_XHNetworkSwiftExample.framework in Frameworks */, 39 | ); 40 | runOnlyForDeploymentPostprocessing = 0; 41 | }; 42 | /* End PBXFrameworksBuildPhase section */ 43 | 44 | /* Begin PBXGroup section */ 45 | 4B2F7E9E1D69928A00BD070E = { 46 | isa = PBXGroup; 47 | children = ( 48 | 4B2F7EA91D69928A00BD070E /* XHNetworkSwiftExample */, 49 | 4B2F7EBC1D6992C700BD070E /* XHNetworkSwift */, 50 | 4B2F7EA81D69928A00BD070E /* Products */, 51 | E3AE71AD27CB62A5A752CB4E /* Pods */, 52 | A5E7F5EE56D9B212C1E60355 /* Frameworks */, 53 | ); 54 | sourceTree = ""; 55 | }; 56 | 4B2F7EA81D69928A00BD070E /* Products */ = { 57 | isa = PBXGroup; 58 | children = ( 59 | 4B2F7EA71D69928A00BD070E /* XHNetworkSwiftExample.app */, 60 | ); 61 | name = Products; 62 | sourceTree = ""; 63 | }; 64 | 4B2F7EA91D69928A00BD070E /* XHNetworkSwiftExample */ = { 65 | isa = PBXGroup; 66 | children = ( 67 | 4B2F7EAA1D69928A00BD070E /* AppDelegate.swift */, 68 | 4B2F7EAC1D69928A00BD070E /* ViewController.swift */, 69 | 4B56B9561D69A57C00BB43B8 /* ViewController.xib */, 70 | 4B2F7EB11D69928A00BD070E /* Assets.xcassets */, 71 | 4B2F7EB31D69928A00BD070E /* LaunchScreen.storyboard */, 72 | 4B2F7EB61D69928A00BD070E /* Info.plist */, 73 | ); 74 | path = XHNetworkSwiftExample; 75 | sourceTree = ""; 76 | }; 77 | 4B2F7EBC1D6992C700BD070E /* XHNetworkSwift */ = { 78 | isa = PBXGroup; 79 | children = ( 80 | 4B2F7EBD1D69934500BD070E /* XHNetwork.swift */, 81 | ); 82 | path = XHNetworkSwift; 83 | sourceTree = ""; 84 | }; 85 | A5E7F5EE56D9B212C1E60355 /* Frameworks */ = { 86 | isa = PBXGroup; 87 | children = ( 88 | 81759C250E430BF30DB03B34 /* Pods_XHNetworkSwiftExample.framework */, 89 | ); 90 | name = Frameworks; 91 | sourceTree = ""; 92 | }; 93 | E3AE71AD27CB62A5A752CB4E /* Pods */ = { 94 | isa = PBXGroup; 95 | children = ( 96 | 0D7A8F1787090DE017F02A96 /* Pods-XHNetworkSwiftExample.debug.xcconfig */, 97 | 09CE44AEF785F1E7B97E367D /* Pods-XHNetworkSwiftExample.release.xcconfig */, 98 | ); 99 | name = Pods; 100 | sourceTree = ""; 101 | }; 102 | /* End PBXGroup section */ 103 | 104 | /* Begin PBXNativeTarget section */ 105 | 4B2F7EA61D69928A00BD070E /* XHNetworkSwiftExample */ = { 106 | isa = PBXNativeTarget; 107 | buildConfigurationList = 4B2F7EB91D69928A00BD070E /* Build configuration list for PBXNativeTarget "XHNetworkSwiftExample" */; 108 | buildPhases = ( 109 | A4F72D1023615385AACF8EA0 /* [CP] Check Pods Manifest.lock */, 110 | 4B2F7EA31D69928A00BD070E /* Sources */, 111 | 4B2F7EA41D69928A00BD070E /* Frameworks */, 112 | 4B2F7EA51D69928A00BD070E /* Resources */, 113 | 34D41BAE1EFA12B28BC9B0D8 /* [CP] Embed Pods Frameworks */, 114 | 4B47C915F66F6C58D08378D3 /* [CP] Copy Pods Resources */, 115 | ); 116 | buildRules = ( 117 | ); 118 | dependencies = ( 119 | ); 120 | name = XHNetworkSwiftExample; 121 | productName = XHNetworkSwiftExample; 122 | productReference = 4B2F7EA71D69928A00BD070E /* XHNetworkSwiftExample.app */; 123 | productType = "com.apple.product-type.application"; 124 | }; 125 | /* End PBXNativeTarget section */ 126 | 127 | /* Begin PBXProject section */ 128 | 4B2F7E9F1D69928A00BD070E /* Project object */ = { 129 | isa = PBXProject; 130 | attributes = { 131 | LastSwiftUpdateCheck = 0730; 132 | LastUpgradeCheck = 0730; 133 | ORGANIZATIONNAME = returnoc.com; 134 | TargetAttributes = { 135 | 4B2F7EA61D69928A00BD070E = { 136 | CreatedOnToolsVersion = 7.3.1; 137 | }; 138 | }; 139 | }; 140 | buildConfigurationList = 4B2F7EA21D69928A00BD070E /* Build configuration list for PBXProject "XHNetworkSwiftExample" */; 141 | compatibilityVersion = "Xcode 3.2"; 142 | developmentRegion = English; 143 | hasScannedForEncodings = 0; 144 | knownRegions = ( 145 | en, 146 | Base, 147 | ); 148 | mainGroup = 4B2F7E9E1D69928A00BD070E; 149 | productRefGroup = 4B2F7EA81D69928A00BD070E /* Products */; 150 | projectDirPath = ""; 151 | projectRoot = ""; 152 | targets = ( 153 | 4B2F7EA61D69928A00BD070E /* XHNetworkSwiftExample */, 154 | ); 155 | }; 156 | /* End PBXProject section */ 157 | 158 | /* Begin PBXResourcesBuildPhase section */ 159 | 4B2F7EA51D69928A00BD070E /* Resources */ = { 160 | isa = PBXResourcesBuildPhase; 161 | buildActionMask = 2147483647; 162 | files = ( 163 | 4B2F7EB51D69928A00BD070E /* LaunchScreen.storyboard in Resources */, 164 | 4B56B9571D69A57C00BB43B8 /* ViewController.xib in Resources */, 165 | 4B2F7EB21D69928A00BD070E /* Assets.xcassets in Resources */, 166 | ); 167 | runOnlyForDeploymentPostprocessing = 0; 168 | }; 169 | /* End PBXResourcesBuildPhase section */ 170 | 171 | /* Begin PBXShellScriptBuildPhase section */ 172 | 34D41BAE1EFA12B28BC9B0D8 /* [CP] Embed Pods Frameworks */ = { 173 | isa = PBXShellScriptBuildPhase; 174 | buildActionMask = 2147483647; 175 | files = ( 176 | ); 177 | inputPaths = ( 178 | ); 179 | name = "[CP] Embed Pods Frameworks"; 180 | outputPaths = ( 181 | ); 182 | runOnlyForDeploymentPostprocessing = 0; 183 | shellPath = /bin/sh; 184 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-XHNetworkSwiftExample/Pods-XHNetworkSwiftExample-frameworks.sh\"\n"; 185 | showEnvVarsInLog = 0; 186 | }; 187 | 4B47C915F66F6C58D08378D3 /* [CP] Copy Pods Resources */ = { 188 | isa = PBXShellScriptBuildPhase; 189 | buildActionMask = 2147483647; 190 | files = ( 191 | ); 192 | inputPaths = ( 193 | ); 194 | name = "[CP] Copy Pods Resources"; 195 | outputPaths = ( 196 | ); 197 | runOnlyForDeploymentPostprocessing = 0; 198 | shellPath = /bin/sh; 199 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-XHNetworkSwiftExample/Pods-XHNetworkSwiftExample-resources.sh\"\n"; 200 | showEnvVarsInLog = 0; 201 | }; 202 | A4F72D1023615385AACF8EA0 /* [CP] Check Pods Manifest.lock */ = { 203 | isa = PBXShellScriptBuildPhase; 204 | buildActionMask = 2147483647; 205 | files = ( 206 | ); 207 | inputPaths = ( 208 | ); 209 | name = "[CP] Check Pods Manifest.lock"; 210 | outputPaths = ( 211 | ); 212 | runOnlyForDeploymentPostprocessing = 0; 213 | shellPath = /bin/sh; 214 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; 215 | showEnvVarsInLog = 0; 216 | }; 217 | /* End PBXShellScriptBuildPhase section */ 218 | 219 | /* Begin PBXSourcesBuildPhase section */ 220 | 4B2F7EA31D69928A00BD070E /* Sources */ = { 221 | isa = PBXSourcesBuildPhase; 222 | buildActionMask = 2147483647; 223 | files = ( 224 | 4B2F7EBE1D69934500BD070E /* XHNetwork.swift in Sources */, 225 | 4B2F7EAD1D69928A00BD070E /* ViewController.swift in Sources */, 226 | 4B2F7EAB1D69928A00BD070E /* AppDelegate.swift in Sources */, 227 | ); 228 | runOnlyForDeploymentPostprocessing = 0; 229 | }; 230 | /* End PBXSourcesBuildPhase section */ 231 | 232 | /* Begin PBXVariantGroup section */ 233 | 4B2F7EB31D69928A00BD070E /* LaunchScreen.storyboard */ = { 234 | isa = PBXVariantGroup; 235 | children = ( 236 | 4B2F7EB41D69928A00BD070E /* Base */, 237 | ); 238 | name = LaunchScreen.storyboard; 239 | sourceTree = ""; 240 | }; 241 | /* End PBXVariantGroup section */ 242 | 243 | /* Begin XCBuildConfiguration section */ 244 | 4B2F7EB71D69928A00BD070E /* Debug */ = { 245 | isa = XCBuildConfiguration; 246 | buildSettings = { 247 | ALWAYS_SEARCH_USER_PATHS = NO; 248 | CLANG_ANALYZER_NONNULL = YES; 249 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 250 | CLANG_CXX_LIBRARY = "libc++"; 251 | CLANG_ENABLE_MODULES = YES; 252 | CLANG_ENABLE_OBJC_ARC = YES; 253 | CLANG_WARN_BOOL_CONVERSION = YES; 254 | CLANG_WARN_CONSTANT_CONVERSION = YES; 255 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 256 | CLANG_WARN_EMPTY_BODY = YES; 257 | CLANG_WARN_ENUM_CONVERSION = YES; 258 | CLANG_WARN_INT_CONVERSION = YES; 259 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 260 | CLANG_WARN_UNREACHABLE_CODE = YES; 261 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 262 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 263 | COPY_PHASE_STRIP = NO; 264 | DEBUG_INFORMATION_FORMAT = dwarf; 265 | ENABLE_STRICT_OBJC_MSGSEND = YES; 266 | ENABLE_TESTABILITY = YES; 267 | GCC_C_LANGUAGE_STANDARD = gnu99; 268 | GCC_DYNAMIC_NO_PIC = NO; 269 | GCC_NO_COMMON_BLOCKS = YES; 270 | GCC_OPTIMIZATION_LEVEL = 0; 271 | GCC_PREPROCESSOR_DEFINITIONS = ( 272 | "DEBUG=1", 273 | "$(inherited)", 274 | ); 275 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 276 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 277 | GCC_WARN_UNDECLARED_SELECTOR = YES; 278 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 279 | GCC_WARN_UNUSED_FUNCTION = YES; 280 | GCC_WARN_UNUSED_VARIABLE = YES; 281 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 282 | MTL_ENABLE_DEBUG_INFO = YES; 283 | ONLY_ACTIVE_ARCH = YES; 284 | SDKROOT = iphoneos; 285 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 286 | }; 287 | name = Debug; 288 | }; 289 | 4B2F7EB81D69928A00BD070E /* Release */ = { 290 | isa = XCBuildConfiguration; 291 | buildSettings = { 292 | ALWAYS_SEARCH_USER_PATHS = NO; 293 | CLANG_ANALYZER_NONNULL = YES; 294 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 295 | CLANG_CXX_LIBRARY = "libc++"; 296 | CLANG_ENABLE_MODULES = YES; 297 | CLANG_ENABLE_OBJC_ARC = YES; 298 | CLANG_WARN_BOOL_CONVERSION = YES; 299 | CLANG_WARN_CONSTANT_CONVERSION = YES; 300 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 301 | CLANG_WARN_EMPTY_BODY = YES; 302 | CLANG_WARN_ENUM_CONVERSION = YES; 303 | CLANG_WARN_INT_CONVERSION = YES; 304 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 305 | CLANG_WARN_UNREACHABLE_CODE = YES; 306 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 307 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 308 | COPY_PHASE_STRIP = NO; 309 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 310 | ENABLE_NS_ASSERTIONS = NO; 311 | ENABLE_STRICT_OBJC_MSGSEND = YES; 312 | GCC_C_LANGUAGE_STANDARD = gnu99; 313 | GCC_NO_COMMON_BLOCKS = YES; 314 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 315 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 316 | GCC_WARN_UNDECLARED_SELECTOR = YES; 317 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 318 | GCC_WARN_UNUSED_FUNCTION = YES; 319 | GCC_WARN_UNUSED_VARIABLE = YES; 320 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 321 | MTL_ENABLE_DEBUG_INFO = NO; 322 | SDKROOT = iphoneos; 323 | VALIDATE_PRODUCT = YES; 324 | }; 325 | name = Release; 326 | }; 327 | 4B2F7EBA1D69928A00BD070E /* Debug */ = { 328 | isa = XCBuildConfiguration; 329 | baseConfigurationReference = 0D7A8F1787090DE017F02A96 /* Pods-XHNetworkSwiftExample.debug.xcconfig */; 330 | buildSettings = { 331 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 332 | INFOPLIST_FILE = XHNetworkSwiftExample/Info.plist; 333 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 334 | PRODUCT_BUNDLE_IDENTIFIER = returnoc.com.XHNetworkSwiftExample; 335 | PRODUCT_NAME = "$(TARGET_NAME)"; 336 | USER_HEADER_SEARCH_PATHS = "$(PODS_ROOT)/**"; 337 | }; 338 | name = Debug; 339 | }; 340 | 4B2F7EBB1D69928A00BD070E /* Release */ = { 341 | isa = XCBuildConfiguration; 342 | baseConfigurationReference = 09CE44AEF785F1E7B97E367D /* Pods-XHNetworkSwiftExample.release.xcconfig */; 343 | buildSettings = { 344 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 345 | INFOPLIST_FILE = XHNetworkSwiftExample/Info.plist; 346 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 347 | PRODUCT_BUNDLE_IDENTIFIER = returnoc.com.XHNetworkSwiftExample; 348 | PRODUCT_NAME = "$(TARGET_NAME)"; 349 | USER_HEADER_SEARCH_PATHS = "$(PODS_ROOT)/**"; 350 | }; 351 | name = Release; 352 | }; 353 | /* End XCBuildConfiguration section */ 354 | 355 | /* Begin XCConfigurationList section */ 356 | 4B2F7EA21D69928A00BD070E /* Build configuration list for PBXProject "XHNetworkSwiftExample" */ = { 357 | isa = XCConfigurationList; 358 | buildConfigurations = ( 359 | 4B2F7EB71D69928A00BD070E /* Debug */, 360 | 4B2F7EB81D69928A00BD070E /* Release */, 361 | ); 362 | defaultConfigurationIsVisible = 0; 363 | defaultConfigurationName = Release; 364 | }; 365 | 4B2F7EB91D69928A00BD070E /* Build configuration list for PBXNativeTarget "XHNetworkSwiftExample" */ = { 366 | isa = XCConfigurationList; 367 | buildConfigurations = ( 368 | 4B2F7EBA1D69928A00BD070E /* Debug */, 369 | 4B2F7EBB1D69928A00BD070E /* Release */, 370 | ); 371 | defaultConfigurationIsVisible = 0; 372 | defaultConfigurationName = Release; 373 | }; 374 | /* End XCConfigurationList section */ 375 | }; 376 | rootObject = 4B2F7E9F1D69928A00BD070E /* Project object */; 377 | } 378 | -------------------------------------------------------------------------------- /Pods/Alamofire/Source/Upload.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Upload.swift 3 | // 4 | // Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | import Foundation 26 | 27 | extension Manager { 28 | private enum Uploadable { 29 | case Data(NSURLRequest, NSData) 30 | case File(NSURLRequest, NSURL) 31 | case Stream(NSURLRequest, NSInputStream) 32 | } 33 | 34 | private func upload(uploadable: Uploadable) -> Request { 35 | var uploadTask: NSURLSessionUploadTask! 36 | var HTTPBodyStream: NSInputStream? 37 | 38 | switch uploadable { 39 | case .Data(let request, let data): 40 | dispatch_sync(queue) { 41 | uploadTask = self.session.uploadTaskWithRequest(request, fromData: data) 42 | } 43 | case .File(let request, let fileURL): 44 | dispatch_sync(queue) { 45 | uploadTask = self.session.uploadTaskWithRequest(request, fromFile: fileURL) 46 | } 47 | case .Stream(let request, let stream): 48 | dispatch_sync(queue) { 49 | uploadTask = self.session.uploadTaskWithStreamedRequest(request) 50 | } 51 | 52 | HTTPBodyStream = stream 53 | } 54 | 55 | let request = Request(session: session, task: uploadTask) 56 | 57 | if HTTPBodyStream != nil { 58 | request.delegate.taskNeedNewBodyStream = { _, _ in 59 | return HTTPBodyStream 60 | } 61 | } 62 | 63 | delegate[request.delegate.task] = request.delegate 64 | 65 | if startRequestsImmediately { 66 | request.resume() 67 | } 68 | 69 | return request 70 | } 71 | 72 | // MARK: File 73 | 74 | /** 75 | Creates a request for uploading a file to the specified URL request. 76 | 77 | If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. 78 | 79 | - parameter URLRequest: The URL request 80 | - parameter file: The file to upload 81 | 82 | - returns: The created upload request. 83 | */ 84 | public func upload(URLRequest: URLRequestConvertible, file: NSURL) -> Request { 85 | return upload(.File(URLRequest.URLRequest, file)) 86 | } 87 | 88 | /** 89 | Creates a request for uploading a file to the specified URL request. 90 | 91 | If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. 92 | 93 | - parameter method: The HTTP method. 94 | - parameter URLString: The URL string. 95 | - parameter headers: The HTTP headers. `nil` by default. 96 | - parameter file: The file to upload 97 | 98 | - returns: The created upload request. 99 | */ 100 | public func upload( 101 | method: Method, 102 | _ URLString: URLStringConvertible, 103 | headers: [String: String]? = nil, 104 | file: NSURL) 105 | -> Request 106 | { 107 | let mutableURLRequest = URLRequest(method, URLString, headers: headers) 108 | return upload(mutableURLRequest, file: file) 109 | } 110 | 111 | // MARK: Data 112 | 113 | /** 114 | Creates a request for uploading data to the specified URL request. 115 | 116 | If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. 117 | 118 | - parameter URLRequest: The URL request. 119 | - parameter data: The data to upload. 120 | 121 | - returns: The created upload request. 122 | */ 123 | public func upload(URLRequest: URLRequestConvertible, data: NSData) -> Request { 124 | return upload(.Data(URLRequest.URLRequest, data)) 125 | } 126 | 127 | /** 128 | Creates a request for uploading data to the specified URL request. 129 | 130 | If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. 131 | 132 | - parameter method: The HTTP method. 133 | - parameter URLString: The URL string. 134 | - parameter headers: The HTTP headers. `nil` by default. 135 | - parameter data: The data to upload 136 | 137 | - returns: The created upload request. 138 | */ 139 | public func upload( 140 | method: Method, 141 | _ URLString: URLStringConvertible, 142 | headers: [String: String]? = nil, 143 | data: NSData) 144 | -> Request 145 | { 146 | let mutableURLRequest = URLRequest(method, URLString, headers: headers) 147 | 148 | return upload(mutableURLRequest, data: data) 149 | } 150 | 151 | // MARK: Stream 152 | 153 | /** 154 | Creates a request for uploading a stream to the specified URL request. 155 | 156 | If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. 157 | 158 | - parameter URLRequest: The URL request. 159 | - parameter stream: The stream to upload. 160 | 161 | - returns: The created upload request. 162 | */ 163 | public func upload(URLRequest: URLRequestConvertible, stream: NSInputStream) -> Request { 164 | return upload(.Stream(URLRequest.URLRequest, stream)) 165 | } 166 | 167 | /** 168 | Creates a request for uploading a stream to the specified URL request. 169 | 170 | If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. 171 | 172 | - parameter method: The HTTP method. 173 | - parameter URLString: The URL string. 174 | - parameter headers: The HTTP headers. `nil` by default. 175 | - parameter stream: The stream to upload. 176 | 177 | - returns: The created upload request. 178 | */ 179 | public func upload( 180 | method: Method, 181 | _ URLString: URLStringConvertible, 182 | headers: [String: String]? = nil, 183 | stream: NSInputStream) 184 | -> Request 185 | { 186 | let mutableURLRequest = URLRequest(method, URLString, headers: headers) 187 | 188 | return upload(mutableURLRequest, stream: stream) 189 | } 190 | 191 | // MARK: MultipartFormData 192 | 193 | /// Default memory threshold used when encoding `MultipartFormData`. 194 | public static let MultipartFormDataEncodingMemoryThreshold: UInt64 = 10 * 1024 * 1024 195 | 196 | /** 197 | Defines whether the `MultipartFormData` encoding was successful and contains result of the encoding as 198 | associated values. 199 | 200 | - Success: Represents a successful `MultipartFormData` encoding and contains the new `Request` along with 201 | streaming information. 202 | - Failure: Used to represent a failure in the `MultipartFormData` encoding and also contains the encoding 203 | error. 204 | */ 205 | public enum MultipartFormDataEncodingResult { 206 | case Success(request: Request, streamingFromDisk: Bool, streamFileURL: NSURL?) 207 | case Failure(ErrorType) 208 | } 209 | 210 | /** 211 | Encodes the `MultipartFormData` and creates a request to upload the result to the specified URL request. 212 | 213 | It is important to understand the memory implications of uploading `MultipartFormData`. If the cummulative 214 | payload is small, encoding the data in-memory and directly uploading to a server is the by far the most 215 | efficient approach. However, if the payload is too large, encoding the data in-memory could cause your app to 216 | be terminated. Larger payloads must first be written to disk using input and output streams to keep the memory 217 | footprint low, then the data can be uploaded as a stream from the resulting file. Streaming from disk MUST be 218 | used for larger payloads such as video content. 219 | 220 | The `encodingMemoryThreshold` parameter allows Alamofire to automatically determine whether to encode in-memory 221 | or stream from disk. If the content length of the `MultipartFormData` is below the `encodingMemoryThreshold`, 222 | encoding takes place in-memory. If the content length exceeds the threshold, the data is streamed to disk 223 | during the encoding process. Then the result is uploaded as data or as a stream depending on which encoding 224 | technique was used. 225 | 226 | If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. 227 | 228 | - parameter method: The HTTP method. 229 | - parameter URLString: The URL string. 230 | - parameter headers: The HTTP headers. `nil` by default. 231 | - parameter multipartFormData: The closure used to append body parts to the `MultipartFormData`. 232 | - parameter encodingMemoryThreshold: The encoding memory threshold in bytes. 233 | `MultipartFormDataEncodingMemoryThreshold` by default. 234 | - parameter encodingCompletion: The closure called when the `MultipartFormData` encoding is complete. 235 | */ 236 | public func upload( 237 | method: Method, 238 | _ URLString: URLStringConvertible, 239 | headers: [String: String]? = nil, 240 | multipartFormData: MultipartFormData -> Void, 241 | encodingMemoryThreshold: UInt64 = Manager.MultipartFormDataEncodingMemoryThreshold, 242 | encodingCompletion: (MultipartFormDataEncodingResult -> Void)?) 243 | { 244 | let mutableURLRequest = URLRequest(method, URLString, headers: headers) 245 | 246 | return upload( 247 | mutableURLRequest, 248 | multipartFormData: multipartFormData, 249 | encodingMemoryThreshold: encodingMemoryThreshold, 250 | encodingCompletion: encodingCompletion 251 | ) 252 | } 253 | 254 | /** 255 | Encodes the `MultipartFormData` and creates a request to upload the result to the specified URL request. 256 | 257 | It is important to understand the memory implications of uploading `MultipartFormData`. If the cummulative 258 | payload is small, encoding the data in-memory and directly uploading to a server is the by far the most 259 | efficient approach. However, if the payload is too large, encoding the data in-memory could cause your app to 260 | be terminated. Larger payloads must first be written to disk using input and output streams to keep the memory 261 | footprint low, then the data can be uploaded as a stream from the resulting file. Streaming from disk MUST be 262 | used for larger payloads such as video content. 263 | 264 | The `encodingMemoryThreshold` parameter allows Alamofire to automatically determine whether to encode in-memory 265 | or stream from disk. If the content length of the `MultipartFormData` is below the `encodingMemoryThreshold`, 266 | encoding takes place in-memory. If the content length exceeds the threshold, the data is streamed to disk 267 | during the encoding process. Then the result is uploaded as data or as a stream depending on which encoding 268 | technique was used. 269 | 270 | If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. 271 | 272 | - parameter URLRequest: The URL request. 273 | - parameter multipartFormData: The closure used to append body parts to the `MultipartFormData`. 274 | - parameter encodingMemoryThreshold: The encoding memory threshold in bytes. 275 | `MultipartFormDataEncodingMemoryThreshold` by default. 276 | - parameter encodingCompletion: The closure called when the `MultipartFormData` encoding is complete. 277 | */ 278 | public func upload( 279 | URLRequest: URLRequestConvertible, 280 | multipartFormData: MultipartFormData -> Void, 281 | encodingMemoryThreshold: UInt64 = Manager.MultipartFormDataEncodingMemoryThreshold, 282 | encodingCompletion: (MultipartFormDataEncodingResult -> Void)?) 283 | { 284 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { 285 | let formData = MultipartFormData() 286 | multipartFormData(formData) 287 | 288 | let URLRequestWithContentType = URLRequest.URLRequest 289 | URLRequestWithContentType.setValue(formData.contentType, forHTTPHeaderField: "Content-Type") 290 | 291 | let isBackgroundSession = self.session.configuration.identifier != nil 292 | 293 | if formData.contentLength < encodingMemoryThreshold && !isBackgroundSession { 294 | do { 295 | let data = try formData.encode() 296 | let encodingResult = MultipartFormDataEncodingResult.Success( 297 | request: self.upload(URLRequestWithContentType, data: data), 298 | streamingFromDisk: false, 299 | streamFileURL: nil 300 | ) 301 | 302 | dispatch_async(dispatch_get_main_queue()) { 303 | encodingCompletion?(encodingResult) 304 | } 305 | } catch { 306 | dispatch_async(dispatch_get_main_queue()) { 307 | encodingCompletion?(.Failure(error as NSError)) 308 | } 309 | } 310 | } else { 311 | let fileManager = NSFileManager.defaultManager() 312 | let tempDirectoryURL = NSURL(fileURLWithPath: NSTemporaryDirectory()) 313 | let directoryURL = tempDirectoryURL.URLByAppendingPathComponent("com.alamofire.manager/multipart.form.data") 314 | let fileName = NSUUID().UUIDString 315 | let fileURL = directoryURL.URLByAppendingPathComponent(fileName) 316 | 317 | do { 318 | try fileManager.createDirectoryAtURL(directoryURL, withIntermediateDirectories: true, attributes: nil) 319 | try formData.writeEncodedDataToDisk(fileURL) 320 | 321 | dispatch_async(dispatch_get_main_queue()) { 322 | let encodingResult = MultipartFormDataEncodingResult.Success( 323 | request: self.upload(URLRequestWithContentType, file: fileURL), 324 | streamingFromDisk: true, 325 | streamFileURL: fileURL 326 | ) 327 | encodingCompletion?(encodingResult) 328 | } 329 | } catch { 330 | dispatch_async(dispatch_get_main_queue()) { 331 | encodingCompletion?(.Failure(error as NSError)) 332 | } 333 | } 334 | } 335 | } 336 | } 337 | } 338 | 339 | // MARK: - 340 | 341 | extension Request { 342 | 343 | // MARK: - UploadTaskDelegate 344 | 345 | class UploadTaskDelegate: DataTaskDelegate { 346 | var uploadTask: NSURLSessionUploadTask? { return task as? NSURLSessionUploadTask } 347 | var uploadProgress: ((Int64, Int64, Int64) -> Void)! 348 | 349 | // MARK: - NSURLSessionTaskDelegate 350 | 351 | // MARK: Override Closures 352 | 353 | var taskDidSendBodyData: ((NSURLSession, NSURLSessionTask, Int64, Int64, Int64) -> Void)? 354 | 355 | // MARK: Delegate Methods 356 | 357 | func URLSession( 358 | session: NSURLSession, 359 | task: NSURLSessionTask, 360 | didSendBodyData bytesSent: Int64, 361 | totalBytesSent: Int64, 362 | totalBytesExpectedToSend: Int64) 363 | { 364 | if initialResponseTime == nil { initialResponseTime = CFAbsoluteTimeGetCurrent() } 365 | 366 | if let taskDidSendBodyData = taskDidSendBodyData { 367 | taskDidSendBodyData(session, task, bytesSent, totalBytesSent, totalBytesExpectedToSend) 368 | } else { 369 | progress.totalUnitCount = totalBytesExpectedToSend 370 | progress.completedUnitCount = totalBytesSent 371 | 372 | uploadProgress?(bytesSent, totalBytesSent, totalBytesExpectedToSend) 373 | } 374 | } 375 | } 376 | } 377 | --------------------------------------------------------------------------------