浏览代码

Version final app

Stephanie M. Ramos 5 年前
父节点
当前提交
e0d9533e13
共有 100 个文件被更改,包括 15776 次插入131 次删除
  1. 二进制
      Trolley App/Assets.xcassets/map.imageset/map.jpg
  2. 二进制
      Trolley App/Assets.xcassets/map.imageset/map@2x.jpg
  3. 二进制
      Trolley App/Assets.xcassets/map.imageset/map@3x.jpg
  4. 0
    66
      Trolley App/Base.lproj/Main.storyboard
  5. 0
    60
      Trolley App/ViewController.swift
  6. 二进制
      trolley/.DS_Store
  7. 13
    0
      trolley/Podfile
  8. 20
    0
      trolley/Podfile.lock
  9. 二进制
      trolley/Pods/.DS_Store
  10. 19
    0
      trolley/Pods/Alamofire/LICENSE
  11. 202
    0
      trolley/Pods/Alamofire/README.md
  12. 840
    0
      trolley/Pods/Alamofire/Source/AFError.swift
  13. 520
    0
      trolley/Pods/Alamofire/Source/Alamofire.swift
  14. 58
    0
      trolley/Pods/Alamofire/Source/AlamofireExtended.swift
  15. 91
    0
      trolley/Pods/Alamofire/Source/CachedResponseHandler.swift
  16. 37
    0
      trolley/Pods/Alamofire/Source/DispatchQueue+Alamofire.swift
  17. 844
    0
      trolley/Pods/Alamofire/Source/EventMonitor.swift
  18. 445
    0
      trolley/Pods/Alamofire/Source/HTTPHeaders.swift
  19. 54
    0
      trolley/Pods/Alamofire/Source/HTTPMethod.swift
  20. 544
    0
      trolley/Pods/Alamofire/Source/MultipartFormData.swift
  21. 87
    0
      trolley/Pods/Alamofire/Source/MultipartUpload.swift
  22. 266
    0
      trolley/Pods/Alamofire/Source/NetworkReachabilityManager.swift
  23. 115
    0
      trolley/Pods/Alamofire/Source/Notifications.swift
  24. 49
    0
      trolley/Pods/Alamofire/Source/OperationQueue+Alamofire.swift
  25. 184
    0
      trolley/Pods/Alamofire/Source/ParameterEncoder.swift
  26. 314
    0
      trolley/Pods/Alamofire/Source/ParameterEncoding.swift
  27. 167
    0
      trolley/Pods/Alamofire/Source/Protector.swift
  28. 95
    0
      trolley/Pods/Alamofire/Source/RedirectHandler.swift
  29. 1461
    0
      trolley/Pods/Alamofire/Source/Request.swift
  30. 243
    0
      trolley/Pods/Alamofire/Source/RequestInterceptor.swift
  31. 136
    0
      trolley/Pods/Alamofire/Source/RequestTaskMap.swift
  32. 399
    0
      trolley/Pods/Alamofire/Source/Response.swift
  33. 779
    0
      trolley/Pods/Alamofire/Source/ResponseSerialization.swift
  34. 109
    0
      trolley/Pods/Alamofire/Source/Result+Alamofire.swift
  35. 363
    0
      trolley/Pods/Alamofire/Source/RetryPolicy.swift
  36. 606
    0
      trolley/Pods/Alamofire/Source/ServerTrustEvaluation.swift
  37. 1039
    0
      trolley/Pods/Alamofire/Source/Session.swift
  38. 305
    0
      trolley/Pods/Alamofire/Source/SessionDelegate.swift
  39. 105
    0
      trolley/Pods/Alamofire/Source/URLConvertible+URLRequestConvertible.swift
  40. 973
    0
      trolley/Pods/Alamofire/Source/URLEncodedFormEncoder.swift
  41. 39
    0
      trolley/Pods/Alamofire/Source/URLRequest+Alamofire.swift
  42. 37
    0
      trolley/Pods/Alamofire/Source/URLSessionConfiguration+Alamofire.swift
  43. 247
    0
      trolley/Pods/Alamofire/Source/Validation.swift
  44. 20
    0
      trolley/Pods/Manifest.lock
  45. 917
    0
      trolley/Pods/Pods.xcodeproj/project.pbxproj
  46. 60
    0
      trolley/Pods/Pods.xcodeproj/xcuserdata/stephanie.marie.xcuserdatad/xcschemes/Alamofire.xcscheme
  47. 58
    0
      trolley/Pods/Pods.xcodeproj/xcuserdata/stephanie.marie.xcuserdatad/xcschemes/Pods-Trolley App.xcscheme
  48. 60
    0
      trolley/Pods/Pods.xcodeproj/xcuserdata/stephanie.marie.xcuserdatad/xcschemes/SwiftyJSON.xcscheme
  49. 32
    0
      trolley/Pods/Pods.xcodeproj/xcuserdata/stephanie.marie.xcuserdatad/xcschemes/xcschememanagement.plist
  50. 60
    0
      trolley/Pods/Pods.xcodeproj/xcuserdata/stephaniem.ramos.xcuserdatad/xcschemes/Alamofire.xcscheme
  51. 58
    0
      trolley/Pods/Pods.xcodeproj/xcuserdata/stephaniem.ramos.xcuserdatad/xcschemes/Pods-Trolley App.xcscheme
  52. 25
    0
      trolley/Pods/Pods.xcodeproj/xcuserdata/stephaniem.ramos.xcuserdatad/xcschemes/xcschememanagement.plist
  53. 21
    0
      trolley/Pods/SwiftyJSON/LICENSE
  54. 562
    0
      trolley/Pods/SwiftyJSON/README.md
  55. 1401
    0
      trolley/Pods/SwiftyJSON/Source/SwiftyJSON/SwiftyJSON.swift
  56. 26
    0
      trolley/Pods/Target Support Files/Alamofire/Alamofire-Info.plist
  57. 5
    0
      trolley/Pods/Target Support Files/Alamofire/Alamofire-dummy.m
  58. 12
    0
      trolley/Pods/Target Support Files/Alamofire/Alamofire-prefix.pch
  59. 16
    0
      trolley/Pods/Target Support Files/Alamofire/Alamofire-umbrella.h
  60. 6
    0
      trolley/Pods/Target Support Files/Alamofire/Alamofire.modulemap
  61. 11
    0
      trolley/Pods/Target Support Files/Alamofire/Alamofire.xcconfig
  62. 26
    0
      trolley/Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App-Info.plist
  63. 51
    0
      trolley/Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App-acknowledgements.markdown
  64. 89
    0
      trolley/Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App-acknowledgements.plist
  65. 5
    0
      trolley/Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App-dummy.m
  66. 3
    0
      trolley/Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App-frameworks-Debug-input-files.xcfilelist
  67. 2
    0
      trolley/Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App-frameworks-Debug-output-files.xcfilelist
  68. 3
    0
      trolley/Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App-frameworks-Release-input-files.xcfilelist
  69. 2
    0
      trolley/Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App-frameworks-Release-output-files.xcfilelist
  70. 173
    0
      trolley/Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App-frameworks.sh
  71. 16
    0
      trolley/Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App-umbrella.h
  72. 12
    0
      trolley/Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App.debug.xcconfig
  73. 6
    0
      trolley/Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App.modulemap
  74. 12
    0
      trolley/Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App.release.xcconfig
  75. 26
    0
      trolley/Pods/Target Support Files/SwiftyJSON/SwiftyJSON-Info.plist
  76. 5
    0
      trolley/Pods/Target Support Files/SwiftyJSON/SwiftyJSON-dummy.m
  77. 12
    0
      trolley/Pods/Target Support Files/SwiftyJSON/SwiftyJSON-prefix.pch
  78. 16
    0
      trolley/Pods/Target Support Files/SwiftyJSON/SwiftyJSON-umbrella.h
  79. 6
    0
      trolley/Pods/Target Support Files/SwiftyJSON/SwiftyJSON.modulemap
  80. 10
    0
      trolley/Pods/Target Support Files/SwiftyJSON/SwiftyJSON.xcconfig
  81. 77
    5
      trolley/Trolley App.xcodeproj/project.pbxproj
  82. 0
    0
      trolley/Trolley App.xcodeproj/project.xcworkspace/contents.xcworkspacedata
  83. 0
    0
      trolley/Trolley App.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
  84. 二进制
      trolley/Trolley App.xcodeproj/project.xcworkspace/xcuserdata/kendrickmorales.xcuserdatad/UserInterfaceState.xcuserstate
  85. 二进制
      trolley/Trolley App.xcodeproj/project.xcworkspace/xcuserdata/stephanie.marie.xcuserdatad/UserInterfaceState.xcuserstate
  86. 二进制
      trolley/Trolley App.xcodeproj/project.xcworkspace/xcuserdata/stephaniem.ramos.xcuserdatad/UserInterfaceState.xcuserstate
  87. 0
    0
      trolley/Trolley App.xcodeproj/xcuserdata/kendrickmorales.xcuserdatad/xcschemes/xcschememanagement.plist
  88. 14
    0
      trolley/Trolley App.xcodeproj/xcuserdata/stephanie.marie.xcuserdatad/xcschemes/xcschememanagement.plist
  89. 14
    0
      trolley/Trolley App.xcodeproj/xcuserdata/stephaniem.ramos.xcuserdatad/xcschemes/xcschememanagement.plist
  90. 10
    0
      trolley/Trolley App.xcworkspace/contents.xcworkspacedata
  91. 8
    0
      trolley/Trolley App.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
  92. 二进制
      trolley/Trolley App.xcworkspace/xcuserdata/stephanie.marie.xcuserdatad/UserInterfaceState.xcuserstate
  93. 二进制
      trolley/Trolley App.xcworkspace/xcuserdata/stephaniem.ramos.xcuserdatad/UserInterfaceState.xcuserstate
  94. 二进制
      trolley/Trolley App/.DS_Store
  95. 0
    0
      trolley/Trolley App/AppDelegate.swift
  96. 二进制
      trolley/Trolley App/Assets.xcassets/.DS_Store
  97. 0
    0
      trolley/Trolley App/Assets.xcassets/AppIcon.appiconset/Contents.json
  98. 0
    0
      trolley/Trolley App/Assets.xcassets/Contents.json
  99. 23
    0
      trolley/Trolley App/Assets.xcassets/biblio_Biblio.imageset/Contents.json
  100. 0
    0
      trolley/Trolley App/Assets.xcassets/biblio_Biblio.imageset/biblio_Biblio-1.png

二进制
Trolley App/Assets.xcassets/map.imageset/map.jpg 查看文件


二进制
Trolley App/Assets.xcassets/map.imageset/map@2x.jpg 查看文件


二进制
Trolley App/Assets.xcassets/map.imageset/map@3x.jpg 查看文件


+ 0
- 66
Trolley App/Base.lproj/Main.storyboard 查看文件

@@ -1,66 +0,0 @@
1
-<?xml version="1.0" encoding="UTF-8"?>
2
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15400" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
3
-    <device id="retina6_1" orientation="portrait" appearance="light"/>
4
-    <dependencies>
5
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15404"/>
6
-        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
7
-        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
8
-    </dependencies>
9
-    <scenes>
10
-        <!--View Controller-->
11
-        <scene sceneID="tne-QT-ifu">
12
-            <objects>
13
-                <viewController id="BYZ-38-t0r" customClass="ViewController" customModule="Trolley_App" customModuleProvider="target" sceneMemberID="viewController">
14
-                    <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
15
-                        <rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
16
-                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
17
-                        <subviews>
18
-                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Trolley IUPI" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="5sx-mb-Vhu">
19
-                                <rect key="frame" x="108" y="90" width="201" height="47"/>
20
-                                <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
21
-                                <fontDescription key="fontDescription" name="HelveticaNeue" family="Helvetica Neue" pointSize="40"/>
22
-                                <nil key="textColor"/>
23
-                                <nil key="highlightedColor"/>
24
-                            </label>
25
-                            <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="map" translatesAutoresizingMaskIntoConstraints="NO" id="KQC-gY-9mQ">
26
-                                <rect key="frame" x="7" y="248" width="400" height="400"/>
27
-                                <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
28
-                            </imageView>
29
-                            <button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="OCY-3M-KE5">
30
-                                <rect key="frame" x="71" y="706" width="111" height="47"/>
31
-                                <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
32
-                                <color key="backgroundColor" systemColor="systemPinkColor" red="1" green="0.1764705882" blue="0.33333333329999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
33
-                                <fontDescription key="fontDescription" name="HelveticaNeue" family="Helvetica Neue" pointSize="30"/>
34
-                                <state key="normal" title="Paradas">
35
-                                    <color key="titleColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
36
-                                </state>
37
-                                <connections>
38
-                                    <action selector="paradasButton:" destination="BYZ-38-t0r" eventType="touchUpInside" id="esp-QM-yT5"/>
39
-                                </connections>
40
-                            </button>
41
-                            <button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="2cl-Ch-09v">
42
-                                <rect key="frame" x="246" y="706" width="113" height="47"/>
43
-                                <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
44
-                                <color key="backgroundColor" systemColor="systemPinkColor" red="1" green="0.1764705882" blue="0.33333333329999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
45
-                                <fontDescription key="fontDescription" name="HelveticaNeue" family="Helvetica Neue" pointSize="30"/>
46
-                                <state key="normal" title="Tracking">
47
-                                    <color key="titleColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
48
-                                </state>
49
-                                <connections>
50
-                                    <action selector="trackingButton:" destination="BYZ-38-t0r" eventType="touchUpInside" id="bj2-2c-F73"/>
51
-                                </connections>
52
-                            </button>
53
-                        </subviews>
54
-                        <color key="backgroundColor" systemColor="secondarySystemGroupedBackgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
55
-                        <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
56
-                    </view>
57
-                </viewController>
58
-                <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
59
-            </objects>
60
-            <point key="canvasLocation" x="137.68115942028987" y="133.92857142857142"/>
61
-        </scene>
62
-    </scenes>
63
-    <resources>
64
-        <image name="map" width="520.5" height="431"/>
65
-    </resources>
66
-</document>

+ 0
- 60
Trolley App/ViewController.swift 查看文件

@@ -1,60 +0,0 @@
1
-//
2
-//  ViewController.swift
3
-//  Trolley App
4
-//
5
-//  Created by Kendrick Morales on 10/21/19.
6
-//  Copyright © 2019 Kendrick Morales. All rights reserved.
7
-//
8
-
9
-import UIKit
10
-import CoreLocation
11
-import MapKit
12
-class ViewController: UIViewController,  CLLocationManagerDelegate {
13
-
14
-    var estado = false
15
-    let locationManager = CLLocationManager()
16
-    
17
-   
18
-    
19
-    
20
-    override func viewDidLoad() {
21
-        super.viewDidLoad()
22
-        locationManager.requestAlwaysAuthorization()
23
-        if CLLocationManager.locationServicesEnabled() {
24
-            locationManager.delegate = self
25
-            locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
26
-        }
27
-
28
-        // Do any additional setup after loading the view.
29
-    }
30
-    
31
-    //funcion para poder extraer latitud y longitud
32
-    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
33
-        guard let locValue: CLLocationCoordinate2D = manager.location?.coordinate
34
-            else { return }
35
-        print("locations = \(locValue.latitude) \(locValue.longitude)")
36
-    }
37
- 
38
-    
39
-    //botton de las paradas
40
-    @IBAction func trackingButton(_ sender: UIButton) {
41
-        
42
-        // si el estado esta en falso
43
-        if estado != true{
44
-         sender.setTitle("Stop", for: .normal) // cambia el texto del boton
45
-         estado = true // cambiamos el estado a activado
46
-         locationManager.startUpdatingLocation() // activamos el metodo de capturacion de localizacion
47
-        }
48
-        else{ // si el estado esta en cierto
49
-             sender.setTitle("Tracking", for: .normal) // cambiamos el texto del boton
50
-            locationManager.stopUpdatingLocation() // paramos el metodo de capturacion de localizacion
51
-            
52
-            estado = false // se cambia estado de nuevo a falso
53
-        }
54
-    }
55
-    
56
-   
57
-    
58
-    
59
-}
60
-

二进制
trolley/.DS_Store 查看文件


+ 13
- 0
trolley/Podfile 查看文件

@@ -0,0 +1,13 @@
1
+# Uncomment the next line to define a global platform for your project
2
+#source 'https://github.com/CocoaPods/Specs.git' 
3
+platform :ios, '10.0'
4
+
5
+target 'Trolley App' do
6
+  # Comment the next line if you don't want to use dynamic frameworks
7
+  use_frameworks!
8
+
9
+  # Pods for Trolley App
10
+  pod 'Alamofire', '~> 5.0.0-rc.3'
11
+  pod 'SwiftyJSON', '~> 4.0'
12
+
13
+end

+ 20
- 0
trolley/Podfile.lock 查看文件

@@ -0,0 +1,20 @@
1
+PODS:
2
+  - Alamofire (5.0.0-rc.3)
3
+  - SwiftyJSON (4.3.0)
4
+
5
+DEPENDENCIES:
6
+  - Alamofire (~> 5.0.0-rc.3)
7
+  - SwiftyJSON (~> 4.0)
8
+
9
+SPEC REPOS:
10
+  trunk:
11
+    - Alamofire
12
+    - SwiftyJSON
13
+
14
+SPEC CHECKSUMS:
15
+  Alamofire: ca8c0de6906873be89d6deec5c8de279e00bf872
16
+  SwiftyJSON: 6faa0040f8b59dead0ee07436cbf76b73c08fd08
17
+
18
+PODFILE CHECKSUM: bbeb87e6f37761e96d8e2b35e3bf81e6aa0f8a7f
19
+
20
+COCOAPODS: 1.8.4

二进制
trolley/Pods/.DS_Store 查看文件


+ 19
- 0
trolley/Pods/Alamofire/LICENSE 查看文件

@@ -0,0 +1,19 @@
1
+Copyright (c) 2014-2018 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.

+ 202
- 0
trolley/Pods/Alamofire/README.md 查看文件

@@ -0,0 +1,202 @@
1
+![Alamofire: Elegant Networking in Swift](https://raw.githubusercontent.com/Alamofire/Alamofire/master/alamofire.png)
2
+
3
+[![Build Status](https://travis-ci.org/Alamofire/Alamofire.svg?branch=master)](https://travis-ci.org/Alamofire/Alamofire)
4
+[![CocoaPods Compatible](https://img.shields.io/cocoapods/v/Alamofire.svg)](https://img.shields.io/cocoapods/v/Alamofire.svg)
5
+[![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)
6
+[![Platform](https://img.shields.io/cocoapods/p/Alamofire.svg?style=flat)](https://alamofire.github.io/Alamofire)
7
+[![Twitter](https://img.shields.io/badge/twitter-@AlamofireSF-blue.svg?style=flat)](https://twitter.com/AlamofireSF)
8
+[![Gitter](https://badges.gitter.im/Alamofire/Alamofire.svg)](https://gitter.im/Alamofire/Alamofire?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
9
+[![Open Source Helpers](https://www.codetriage.com/alamofire/alamofire/badges/users.svg)](https://www.codetriage.com/alamofire/alamofire)
10
+
11
+Alamofire is an HTTP networking library written in Swift.
12
+
13
+**⚠️⚠️⚠️ WARNING ⚠️⚠️⚠️** This documentation is out of date during the Alamofire 5 beta process.
14
+
15
+- [Features](#features)
16
+- [Component Libraries](#component-libraries)
17
+- [Requirements](#requirements)
18
+- [Migration Guides](#migration-guides)
19
+- [Communication](#communication)
20
+- [Installation](#installation)
21
+- [Usage](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#using-alamofire)
22
+    - [**Introduction -**](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#introduction) [Making Requests](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#making-requests), [Response Handling](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#response-handling), [Response Validation](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#response-validation), [Response Caching](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#response-caching)
23
+	- **HTTP -** [HTTP Methods](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#http-methods), [Parameters and Parameter Encoder](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md##request-parameters-and-parameter-encoders), [HTTP Headers](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#http-headers), [Authentication](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#authentication)
24
+	- **Large Data -** [Downloading Data to a File](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#downloading-data-to-a-file), [Uploading Data to a Server](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#uploading-data-to-a-server)
25
+	- **Tools -** [Statistical Metrics](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#statistical-metrics), [cURL Command Output](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#curl-command-output)
26
+- [Advanced Usage](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md)
27
+	- **URL Session -** [Session Manager](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#session-manager), [Session Delegate](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#session-delegate), [Request](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#request)
28
+	- **Routing -** [Routing Requests](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#routing-requests), [Adapting and Retrying Requests](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#adapting-and-retrying-requests)
29
+	- **Model Objects -** [Custom Response Serialization](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#custom-response-serialization)
30
+	- **Connection -** [Security](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#security), [Network Reachability](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#network-reachability)
31
+- [Open Radars](#open-radars)
32
+- [FAQ](#faq)
33
+- [Credits](#credits)
34
+- [Donations](#donations)
35
+- [License](#license)
36
+
37
+## Features
38
+
39
+- [x] Chainable Request / Response Methods
40
+- [x] URL / JSON / plist Parameter Encoding
41
+- [x] Upload File / Data / Stream / MultipartFormData
42
+- [x] Download File using Request or Resume Data
43
+- [x] Authentication with URLCredential
44
+- [x] HTTP Response Validation
45
+- [x] Upload and Download Progress Closures with Progress
46
+- [x] cURL Command Output
47
+- [x] Dynamically Adapt and Retry Requests
48
+- [x] TLS Certificate and Public Key Pinning
49
+- [x] Network Reachability
50
+- [x] Comprehensive Unit and Integration Test Coverage
51
+- [x] [Complete Documentation](https://alamofire.github.io/Alamofire)
52
+
53
+## Component Libraries
54
+
55
+In order to keep Alamofire focused specifically on core networking implementations, additional component libraries have been created by the [Alamofire Software Foundation](https://github.com/Alamofire/Foundation) to bring additional functionality to the Alamofire ecosystem.
56
+
57
+- [AlamofireImage](https://github.com/Alamofire/AlamofireImage) - An image library including image response serializers, `UIImage` and `UIImageView` extensions, custom image filters, an auto-purging in-memory cache and a priority-based image downloading system.
58
+- [AlamofireNetworkActivityIndicator](https://github.com/Alamofire/AlamofireNetworkActivityIndicator) - Controls the visibility of the network activity indicator on iOS using Alamofire. It contains configurable delay timers to help mitigate flicker and can support `URLSession` instances not managed by Alamofire.
59
+
60
+## Requirements
61
+
62
+- iOS 10.0+ / macOS 10.12+ / tvOS 10.0+ / watchOS 3.0+
63
+- Xcode 10.2+
64
+- Swift 5+
65
+
66
+## Migration Guides
67
+
68
+- Alamofire 5.0 Migration Guide: To be written!
69
+- [Alamofire 4.0 Migration Guide](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Alamofire%204.0%20Migration%20Guide.md)
70
+- [Alamofire 3.0 Migration Guide](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Alamofire%203.0%20Migration%20Guide.md)
71
+- [Alamofire 2.0 Migration Guide](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Alamofire%202.0%20Migration%20Guide.md)
72
+
73
+## Communication
74
+- If you **need help with making network requests** using Alamofire, use [Stack Overflow](https://stackoverflow.com/questions/tagged/alamofire) and tag `alamofire`.
75
+- If you need to **find or understand an API**, check [our documentation](http://alamofire.github.io/Alamofire/) or [Apple's documentation for `URLSession`](https://developer.apple.com/documentation/foundation/url_loading_system), on top of which Alamofire is built.
76
+- If you need **help with an Alamofire feature**, use [our forum on swift.org](https://forums.swift.org/c/related-projects/alamofire).
77
+- If you'd like to **discuss Alamofire best practices**, use [our forum on swift.org](https://forums.swift.org/c/related-projects/alamofire).
78
+- If you'd like to **discuss a feature request**, use [our forum on swift.org](https://forums.swift.org/c/related-projects/alamofire). 
79
+- If you **found a bug**, open an issue here on GitHub and follow the guide. The more detail the better!
80
+- If you **want to contribute**, submit a pull request.
81
+
82
+## Installation
83
+
84
+### CocoaPods
85
+
86
+[CocoaPods](https://cocoapods.org) is a dependency manager for Cocoa projects. For usage and installation instructions, visit their website. To integrate Alamofire into your Xcode project using CocoaPods, specify it in your `Podfile`:
87
+
88
+```ruby
89
+pod 'Alamofire', '~> 5.0.0-rc.3'
90
+```
91
+
92
+### Carthage
93
+
94
+[Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks. To integrate Alamofire into your Xcode project using Carthage, specify it in your `Cartfile`:
95
+
96
+```ogdl
97
+github "Alamofire/Alamofire" "5.0.0-rc.3"
98
+```
99
+
100
+### Swift Package Manager
101
+
102
+The [Swift Package Manager](https://swift.org/package-manager/) is a tool for automating the distribution of Swift code and is integrated into the `swift` compiler. It is in early development, but Alamofire does support its use on supported platforms.
103
+
104
+Once you have your Swift package set up, adding Alamofire as a dependency is as easy as adding it to the `dependencies` value of your `Package.swift`.
105
+
106
+```swift
107
+dependencies: [
108
+    .package(url: "https://github.com/Alamofire/Alamofire.git", from: "5.0.0-rc.3")
109
+]
110
+```
111
+
112
+### Manually
113
+
114
+If you prefer not to use any of the aforementioned dependency managers, you can integrate Alamofire into your project manually.
115
+
116
+#### Embedded Framework
117
+
118
+- Open up Terminal, `cd` into your top-level project directory, and run the following command "if" your project is not initialized as a git repository:
119
+
120
+  ```bash
121
+  $ git init
122
+  ```
123
+
124
+- Add Alamofire as a git [submodule](https://git-scm.com/docs/git-submodule) by running the following command:
125
+
126
+  ```bash
127
+  $ git submodule add https://github.com/Alamofire/Alamofire.git
128
+  ```
129
+
130
+- Open the new `Alamofire` folder, and drag the `Alamofire.xcodeproj` into the Project Navigator of your application's Xcode project.
131
+
132
+    > It should appear nested underneath your application's blue project icon. Whether it is above or below all the other Xcode groups does not matter.
133
+
134
+- Select the `Alamofire.xcodeproj` in the Project Navigator and verify the deployment target matches that of your application target.
135
+- Next, select your application project in the Project Navigator (blue project icon) to navigate to the target configuration window and select the application target under the "Targets" heading in the sidebar.
136
+- In the tab bar at the top of that window, open the "General" panel.
137
+- Click on the `+` button under the "Embedded Binaries" section.
138
+- You will see two different `Alamofire.xcodeproj` folders each with two different versions of the `Alamofire.framework` nested inside a `Products` folder.
139
+
140
+    > It does not matter which `Products` folder you choose from, but it does matter whether you choose the top or bottom `Alamofire.framework`.
141
+
142
+- Select the top `Alamofire.framework` for iOS and the bottom one for macOS.
143
+
144
+    > You can verify which one you selected by inspecting the build log for your project. The build target for `Alamofire` will be listed as either `Alamofire iOS`, `Alamofire macOS`, `Alamofire tvOS` or `Alamofire watchOS`.
145
+
146
+- And that's it!
147
+
148
+  > The `Alamofire.framework` is automagically added as a target dependency, linked framework and embedded framework in a copy files build phase which is all you need to build on the simulator and a device.
149
+
150
+## Open Radars
151
+
152
+The following radars have some effect on the current implementation of Alamofire.
153
+
154
+- [`rdar://21349340`](http://www.openradar.me/radar?id=5517037090635776) - Compiler throwing warning due to toll-free bridging issue in test case
155
+- `rdar://26870455` - Background URL Session Configurations do not work in the simulator
156
+- `rdar://26849668` - Some URLProtocol APIs do not properly handle `URLRequest`
157
+
158
+## Resolved Radars
159
+
160
+The following radars have been resolved over time after being filed against the Alamofire project.
161
+
162
+- [`rdar://26761490`](http://www.openradar.me/radar?id=5010235949318144) - Swift string interpolation causing memory leak with common usage.
163
+  - (Resolved): 9/1/17 in Xcode 9 beta 6.
164
+- [`rdar://36082113`](http://openradar.appspot.com/radar?id=4942308441063424) - `URLSessionTaskMetrics` failing to link on watchOS 3.0+
165
+  - (Resolved): Just add `CFNetwork` to your linked frameworks.
166
+  
167
+## FAQ
168
+
169
+### What's the origin of the name Alamofire?
170
+
171
+Alamofire is named after the [Alamo Fire flower](https://aggie-horticulture.tamu.edu/wildseed/alamofire.html), a hybrid variant of the Bluebonnet, the official state flower of Texas.
172
+
173
+## Credits
174
+
175
+Alamofire is owned and maintained by the [Alamofire Software Foundation](http://alamofire.org). You can follow them on Twitter at [@AlamofireSF](https://twitter.com/AlamofireSF) for project updates and releases.
176
+
177
+### Security Disclosure
178
+
179
+If you believe you have identified a security vulnerability with Alamofire, you should report it as soon as possible via email to security@alamofire.org. Please do not post it to a public issue tracker.
180
+
181
+## Donations
182
+
183
+The [ASF](https://github.com/Alamofire/Foundation#members) is looking to raise money to officially stay registered as a federal non-profit organization.
184
+Registering will allow us members to gain some legal protections and also allow us to put donations to use, tax free.
185
+Donating to the ASF will enable us to:
186
+
187
+- Pay our yearly legal fees to keep the non-profit in good status
188
+- Pay for our mail servers to help us stay on top of all questions and security issues
189
+- Potentially fund test servers to make it easier for us to test the edge cases
190
+- Potentially fund developers to work on one of our projects full-time
191
+
192
+The community adoption of the ASF libraries has been amazing.
193
+We are greatly humbled by your enthusiasm around the projects, and want to continue to do everything we can to move the needle forward.
194
+With your continued support, the ASF will be able to improve its reach and also provide better legal safety for the core members.
195
+If you use any of our libraries for work, see if your employers would be interested in donating.
196
+Any amount you can donate today to help us reach our goal would be greatly appreciated.
197
+
198
+[![paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=W34WPEE74APJQ)
199
+
200
+## License
201
+
202
+Alamofire is released under the MIT license. [See LICENSE](https://github.com/Alamofire/Alamofire/blob/master/LICENSE) for details.

+ 840
- 0
trolley/Pods/Alamofire/Source/AFError.swift 查看文件

@@ -0,0 +1,840 @@
1
+//
2
+//  AFError.swift
3
+//
4
+//  Copyright (c) 2014-2018 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
+/// `AFError` is the error type returned by Alamofire. It encompasses a few different types of errors, each with
28
+/// their own associated reasons.
29
+public enum AFError: Error {
30
+    /// The underlying reason the `.multipartEncodingFailed` error occurred.
31
+    public enum MultipartEncodingFailureReason {
32
+        /// The `fileURL` provided for reading an encodable body part isn't a file `URL`.
33
+        case bodyPartURLInvalid(url: URL)
34
+        /// The filename of the `fileURL` provided has either an empty `lastPathComponent` or `pathExtension.
35
+        case bodyPartFilenameInvalid(in: URL)
36
+        /// The file at the `fileURL` provided was not reachable.
37
+        case bodyPartFileNotReachable(at: URL)
38
+        /// Attempting to check the reachability of the `fileURL` provided threw an error.
39
+        case bodyPartFileNotReachableWithError(atURL: URL, error: Error)
40
+        /// The file at the `fileURL` provided is actually a directory.
41
+        case bodyPartFileIsDirectory(at: URL)
42
+        /// The size of the file at the `fileURL` provided was not returned by the system.
43
+        case bodyPartFileSizeNotAvailable(at: URL)
44
+        /// The attempt to find the size of the file at the `fileURL` provided threw an error.
45
+        case bodyPartFileSizeQueryFailedWithError(forURL: URL, error: Error)
46
+        /// An `InputStream` could not be created for the provided `fileURL`.
47
+        case bodyPartInputStreamCreationFailed(for: URL)
48
+        /// An `OutputStream` could not be created when attempting to write the encoded data to disk.
49
+        case outputStreamCreationFailed(for: URL)
50
+        /// The encoded body data could not be written to disk because a file already exists at the provided `fileURL`.
51
+        case outputStreamFileAlreadyExists(at: URL)
52
+        /// The `fileURL` provided for writing the encoded body data to disk is not a file `URL`.
53
+        case outputStreamURLInvalid(url: URL)
54
+        /// The attempt to write the encoded body data to disk failed with an underlying error.
55
+        case outputStreamWriteFailed(error: Error)
56
+        /// The attempt to read an encoded body part `InputStream` failed with underlying system error.
57
+        case inputStreamReadFailed(error: Error)
58
+    }
59
+
60
+    /// The underlying reason the `.parameterEncodingFailed` error occurred.
61
+    public enum ParameterEncodingFailureReason {
62
+        /// The `URLRequest` did not have a `URL` to encode.
63
+        case missingURL
64
+        /// JSON serialization failed with an underlying system error during the encoding process.
65
+        case jsonEncodingFailed(error: Error)
66
+        /// Custom parameter encoding failed due to the associated `Error`.
67
+        case customEncodingFailed(error: Error)
68
+    }
69
+
70
+    /// The underlying reason the `.parameterEncoderFailed` error occurred.
71
+    public enum ParameterEncoderFailureReason {
72
+        /// Possible missing components.
73
+        public enum RequiredComponent {
74
+            /// The `URL` was missing or unable to be extracted from the passed `URLRequest` or during encoding.
75
+            case url
76
+            /// The `HTTPMethod` could not be extracted from the passed `URLRequest`.
77
+            case httpMethod(rawValue: String)
78
+        }
79
+
80
+        /// A `RequiredComponent` was missing during encoding.
81
+        case missingRequiredComponent(RequiredComponent)
82
+        /// The underlying encoder failed with the associated error.
83
+        case encoderFailed(error: Error)
84
+    }
85
+
86
+    /// The underlying reason the `.responseValidationFailed` error occurred.
87
+    public enum ResponseValidationFailureReason {
88
+        /// The data file containing the server response did not exist.
89
+        case dataFileNil
90
+        /// The data file containing the server response at the associated `URL` could not be read.
91
+        case dataFileReadFailed(at: URL)
92
+        /// The response did not contain a `Content-Type` and the `acceptableContentTypes` provided did not contain a
93
+        /// wildcard type.
94
+        case missingContentType(acceptableContentTypes: [String])
95
+        /// The response `Content-Type` did not match any type in the provided `acceptableContentTypes`.
96
+        case unacceptableContentType(acceptableContentTypes: [String], responseContentType: String)
97
+        /// The response status code was not acceptable.
98
+        case unacceptableStatusCode(code: Int)
99
+        /// Custom response validation failed due to the associated `Error`.
100
+        case customValidationFailed(error: Error)
101
+    }
102
+
103
+    /// The underlying reason the response serialization error occurred.
104
+    public enum ResponseSerializationFailureReason {
105
+        /// The server response contained no data or the data was zero length.
106
+        case inputDataNilOrZeroLength
107
+        /// The file containing the server response did not exist.
108
+        case inputFileNil
109
+        /// The file containing the server response could not be read from the associated `URL`.
110
+        case inputFileReadFailed(at: URL)
111
+        /// String serialization failed using the provided `String.Encoding`.
112
+        case stringSerializationFailed(encoding: String.Encoding)
113
+        /// JSON serialization failed with an underlying system error.
114
+        case jsonSerializationFailed(error: Error)
115
+        /// A `DataDecoder` failed to decode the response due to the associated `Error`.
116
+        case decodingFailed(error: Error)
117
+        /// A custom response serializer failed due to the associated `Error`.
118
+        case customSerializationFailed(error: Error)
119
+        /// Generic serialization failed for an empty response that wasn't type `Empty` but instead the associated type.
120
+        case invalidEmptyResponse(type: String)
121
+    }
122
+
123
+    /// Underlying reason a server trust evaluation error occurred.
124
+    public enum ServerTrustFailureReason {
125
+        /// The output of a server trust evaluation.
126
+        public struct Output {
127
+            /// The host for which the evaluation was performed.
128
+            public let host: String
129
+            /// The `SecTrust` value which was evaluated.
130
+            public let trust: SecTrust
131
+            /// The `OSStatus` of evaluation operation.
132
+            public let status: OSStatus
133
+            /// The result of the evaluation operation.
134
+            public let result: SecTrustResultType
135
+
136
+            /// Creates an `Output` value from the provided values.
137
+            init(_ host: String, _ trust: SecTrust, _ status: OSStatus, _ result: SecTrustResultType) {
138
+                self.host = host
139
+                self.trust = trust
140
+                self.status = status
141
+                self.result = result
142
+            }
143
+        }
144
+
145
+        /// No `ServerTrustEvaluator` was found for the associated host.
146
+        case noRequiredEvaluator(host: String)
147
+        /// No certificates were found with which to perform the trust evaluation.
148
+        case noCertificatesFound
149
+        /// No public keys were found with which to perform the trust evaluation.
150
+        case noPublicKeysFound
151
+        /// During evaluation, application of the associated `SecPolicy` failed.
152
+        case policyApplicationFailed(trust: SecTrust, policy: SecPolicy, status: OSStatus)
153
+        /// During evaluation, setting the associated anchor certificates failed.
154
+        case settingAnchorCertificatesFailed(status: OSStatus, certificates: [SecCertificate])
155
+        /// During evaluation, creation of the revocation policy failed.
156
+        case revocationPolicyCreationFailed
157
+        /// `SecTrust` evaluation failed with the associated `Error`, if one was produced.
158
+        case trustEvaluationFailed(error: Error?)
159
+        /// Default evaluation failed with the associated `Output`.
160
+        case defaultEvaluationFailed(output: Output)
161
+        /// Host validation failed with the associated `Output`.
162
+        case hostValidationFailed(output: Output)
163
+        /// Revocation check failed with the associated `Output` and options.
164
+        case revocationCheckFailed(output: Output, options: RevocationTrustEvaluator.Options)
165
+        /// Certificate pinning failed.
166
+        case certificatePinningFailed(host: String, trust: SecTrust, pinnedCertificates: [SecCertificate], serverCertificates: [SecCertificate])
167
+        /// Public key pinning failed.
168
+        case publicKeyPinningFailed(host: String, trust: SecTrust, pinnedKeys: [SecKey], serverKeys: [SecKey])
169
+        /// Custom server trust evaluation failed due to the associated `Error`.
170
+        case customEvaluationFailed(error: Error)
171
+    }
172
+
173
+    /// The underlying reason the `.urlRequestValidationFailed`
174
+    public enum URLRequestValidationFailureReason {
175
+        /// URLRequest with GET method had body data.
176
+        case bodyDataInGETRequest(Data)
177
+    }
178
+
179
+    ///  `UploadableConvertible` threw an error in `createUploadable()`.
180
+    case createUploadableFailed(error: Error)
181
+    ///  `URLRequestConvertible` threw an error in `asURLRequest()`.
182
+    case createURLRequestFailed(error: Error)
183
+    /// `SessionDelegate` threw an error while attempting to move downloaded file to destination URL.
184
+    case downloadedFileMoveFailed(error: Error, source: URL, destination: URL)
185
+    /// `Request` was explicitly cancelled.
186
+    case explicitlyCancelled
187
+    /// `URLConvertible` type failed to create a valid `URL`.
188
+    case invalidURL(url: URLConvertible)
189
+    /// Multipart form encoding failed.
190
+    case multipartEncodingFailed(reason: MultipartEncodingFailureReason)
191
+    /// `ParameterEncoding` threw an error during the encoding process.
192
+    case parameterEncodingFailed(reason: ParameterEncodingFailureReason)
193
+    /// `ParameterEncoder` threw an error while running the encoder.
194
+    case parameterEncoderFailed(reason: ParameterEncoderFailureReason)
195
+    /// `RequestAdapter` threw an error during adaptation.
196
+    case requestAdaptationFailed(error: Error)
197
+    /// `RequestRetrier` threw an error during the request retry process.
198
+    case requestRetryFailed(retryError: Error, originalError: Error)
199
+    /// Response validation failed.
200
+    case responseValidationFailed(reason: ResponseValidationFailureReason)
201
+    /// Response serialization failed.
202
+    case responseSerializationFailed(reason: ResponseSerializationFailureReason)
203
+    /// `ServerTrustEvaluating` instance threw an error during trust evaluation.
204
+    case serverTrustEvaluationFailed(reason: ServerTrustFailureReason)
205
+    /// `Session` which issued the `Request` was deinitialized, most likely because its reference went out of scope.
206
+    case sessionDeinitialized
207
+    /// `Session` was explicitly invalidated, possibly with the `Error` produced by the underlying `URLSession`.
208
+    case sessionInvalidated(error: Error?)
209
+    /// `URLSessionTask` completed with error.
210
+    case sessionTaskFailed(error: Error)
211
+    /// `URLRequest` failed validation.
212
+    case urlRequestValidationFailed(reason: URLRequestValidationFailureReason)
213
+}
214
+
215
+extension Error {
216
+    /// Returns the instance cast as an `AFError`.
217
+    public var asAFError: AFError? {
218
+        return self as? AFError
219
+    }
220
+
221
+    /// Returns the instance cast as an `AFError`. If casting fails, a `fatalError` with the specified `message` is thrown.
222
+    public func asAFError(orFailWith message: @autoclosure () -> String, file: StaticString = #file, line: UInt = #line) -> AFError {
223
+        guard let afError = self as? AFError else {
224
+            fatalError(message(), file: file, line: line)
225
+        }
226
+        return afError
227
+    }
228
+
229
+    /// Casts the instance as `AFError` or returns `defaultAFError`
230
+    func asAFError(or defaultAFError: @autoclosure () -> AFError) -> AFError {
231
+        return self as? AFError ?? defaultAFError()
232
+    }
233
+}
234
+
235
+// MARK: - Error Booleans
236
+
237
+extension AFError {
238
+    /// Returns whether the instance is `.sessionDeinitialized`.
239
+    public var isSessionDeinitializedError: Bool {
240
+        if case .sessionDeinitialized = self { return true }
241
+        return false
242
+    }
243
+
244
+    /// Returns whether the instance is `.sessionInvalidated`.
245
+    public var isSessionInvalidatedError: Bool {
246
+        if case .sessionInvalidated = self { return true }
247
+        return false
248
+    }
249
+
250
+    /// Returns whether the instance is `.explicitlyCancelled`.
251
+    public var isExplicitlyCancelledError: Bool {
252
+        if case .explicitlyCancelled = self { return true }
253
+        return false
254
+    }
255
+
256
+    /// Returns whether the instance is `.invalidURL`.
257
+    public var isInvalidURLError: Bool {
258
+        if case .invalidURL = self { return true }
259
+        return false
260
+    }
261
+
262
+    /// Returns whether the instance is `.parameterEncodingFailed`. When `true`, the `underlyingError` property will
263
+    /// contain the associated value.
264
+    public var isParameterEncodingError: Bool {
265
+        if case .parameterEncodingFailed = self { return true }
266
+        return false
267
+    }
268
+
269
+    /// Returns whether the instance is `.parameterEncoderFailed`. When `true`, the `underlyingError` property will
270
+    /// contain the associated value.
271
+    public var isParameterEncoderError: Bool {
272
+        if case .parameterEncoderFailed = self { return true }
273
+        return false
274
+    }
275
+
276
+    /// Returns whether the instance is `.multipartEncodingFailed`. When `true`, the `url` and `underlyingError`
277
+    /// properties will contain the associated values.
278
+    public var isMultipartEncodingError: Bool {
279
+        if case .multipartEncodingFailed = self { return true }
280
+        return false
281
+    }
282
+
283
+    /// Returns whether the instance is `.requestAdaptationFailed`. When `true`, the `underlyingError` property will
284
+    /// contain the associated value.
285
+    public var isRequestAdaptationError: Bool {
286
+        if case .requestAdaptationFailed = self { return true }
287
+        return false
288
+    }
289
+
290
+    /// Returns whether the instance is `.responseValidationFailed`. When `true`, the `acceptableContentTypes`,
291
+    /// `responseContentType`,  `responseCode`, and `underlyingError` properties will contain the associated values.
292
+    public var isResponseValidationError: Bool {
293
+        if case .responseValidationFailed = self { return true }
294
+        return false
295
+    }
296
+
297
+    /// Returns whether the instance is `.responseSerializationFailed`. When `true`, the `failedStringEncoding` and
298
+    /// `underlyingError` properties will contain the associated values.
299
+    public var isResponseSerializationError: Bool {
300
+        if case .responseSerializationFailed = self { return true }
301
+        return false
302
+    }
303
+
304
+    /// Returns whether the instance is `.serverTrustEvaluationFailed`. When `true`, the `underlyingError` property will
305
+    /// contain the associated value.
306
+    public var isServerTrustEvaluationError: Bool {
307
+        if case .serverTrustEvaluationFailed = self { return true }
308
+        return false
309
+    }
310
+
311
+    /// Returns whether the instance is `requestRetryFailed`. When `true`, the `underlyingError` property will
312
+    /// contain the associated value.
313
+    public var isRequestRetryError: Bool {
314
+        if case .requestRetryFailed = self { return true }
315
+        return false
316
+    }
317
+
318
+    /// Returns whether the instance is `createUploadableFailed`. When `true`, the `underlyingError` property will
319
+    /// contain the associated value.
320
+    public var isCreateUploadableError: Bool {
321
+        if case .createUploadableFailed = self { return true }
322
+        return false
323
+    }
324
+
325
+    /// Returns whether the instance is `createURLRequestFailed`. When `true`, the `underlyingError` property will
326
+    /// contain the associated value.
327
+    public var isCreateURLRequestError: Bool {
328
+        if case .createURLRequestFailed = self { return true }
329
+        return false
330
+    }
331
+
332
+    /// Returns whether the instance is `downloadedFileMoveFailed`. When `true`, the `destination` and `underlyingError` properties will
333
+    /// contain the associated values.
334
+    public var isDownloadedFileMoveError: Bool {
335
+        if case .downloadedFileMoveFailed = self { return true }
336
+        return false
337
+    }
338
+
339
+    /// Returns whether the instance is `createURLRequestFailed`. When `true`, the `underlyingError` property will
340
+    /// contain the associated value.
341
+    public var isSessionTaskError: Bool {
342
+        if case .sessionTaskFailed = self { return true }
343
+        return false
344
+    }
345
+}
346
+
347
+// MARK: - Convenience Properties
348
+
349
+extension AFError {
350
+    /// The `URLConvertible` associated with the error.
351
+    public var urlConvertible: URLConvertible? {
352
+        guard case let .invalidURL(url) = self else { return nil }
353
+        return url
354
+    }
355
+
356
+    /// The `URL` associated with the error.
357
+    public var url: URL? {
358
+        guard case let .multipartEncodingFailed(reason) = self else { return nil }
359
+        return reason.url
360
+    }
361
+
362
+    /// The underlying `Error` responsible for generating the failure associated with `.sessionInvalidated`,
363
+    /// `.parameterEncodingFailed`, `.parameterEncoderFailed`, `.multipartEncodingFailed`, `.requestAdaptationFailed`,
364
+    /// `.responseSerializationFailed`, `.requestRetryFailed` errors.
365
+    public var underlyingError: Error? {
366
+        switch self {
367
+        case let .multipartEncodingFailed(reason):
368
+            return reason.underlyingError
369
+        case let .parameterEncodingFailed(reason):
370
+            return reason.underlyingError
371
+        case let .parameterEncoderFailed(reason):
372
+            return reason.underlyingError
373
+        case let .requestAdaptationFailed(error):
374
+            return error
375
+        case let .requestRetryFailed(retryError, _):
376
+            return retryError
377
+        case let .responseValidationFailed(reason):
378
+            return reason.underlyingError
379
+        case let .responseSerializationFailed(reason):
380
+            return reason.underlyingError
381
+        case let .serverTrustEvaluationFailed(reason):
382
+            return reason.underlyingError
383
+        case let .sessionInvalidated(error):
384
+            return error
385
+        case let .createUploadableFailed(error):
386
+            return error
387
+        case let .createURLRequestFailed(error):
388
+            return error
389
+        case let .downloadedFileMoveFailed(error, _, _):
390
+            return error
391
+        case let .sessionTaskFailed(error):
392
+            return error
393
+        case .explicitlyCancelled,
394
+             .invalidURL,
395
+             .sessionDeinitialized,
396
+             .urlRequestValidationFailed:
397
+            return nil
398
+        }
399
+    }
400
+
401
+    /// The acceptable `Content-Type`s of a `.responseValidationFailed` error.
402
+    public var acceptableContentTypes: [String]? {
403
+        guard case let .responseValidationFailed(reason) = self else { return nil }
404
+        return reason.acceptableContentTypes
405
+    }
406
+
407
+    /// The response `Content-Type` of a `.responseValidationFailed` error.
408
+    public var responseContentType: String? {
409
+        guard case let .responseValidationFailed(reason) = self else { return nil }
410
+        return reason.responseContentType
411
+    }
412
+
413
+    /// The response code of a `.responseValidationFailed` error.
414
+    public var responseCode: Int? {
415
+        guard case let .responseValidationFailed(reason) = self else { return nil }
416
+        return reason.responseCode
417
+    }
418
+
419
+    /// The `String.Encoding` associated with a failed `.stringResponse()` call.
420
+    public var failedStringEncoding: String.Encoding? {
421
+        guard case let .responseSerializationFailed(reason) = self else { return nil }
422
+        return reason.failedStringEncoding
423
+    }
424
+
425
+    /// The `source` URL of a `.downloadedFileMoveFailed` error.
426
+    public var sourceURL: URL? {
427
+        guard case let .downloadedFileMoveFailed(_, source, _) = self else { return nil }
428
+        return source
429
+    }
430
+
431
+    /// The `destination` URL of a `.downloadedFileMoveFailed` error.
432
+    public var destinationURL: URL? {
433
+        guard case let .downloadedFileMoveFailed(_, _, destination) = self else { return nil }
434
+        return destination
435
+    }
436
+}
437
+
438
+extension AFError.ParameterEncodingFailureReason {
439
+    var underlyingError: Error? {
440
+        switch self {
441
+        case let .jsonEncodingFailed(error),
442
+             let .customEncodingFailed(error):
443
+            return error
444
+        case .missingURL:
445
+            return nil
446
+        }
447
+    }
448
+}
449
+
450
+extension AFError.ParameterEncoderFailureReason {
451
+    var underlyingError: Error? {
452
+        switch self {
453
+        case let .encoderFailed(error):
454
+            return error
455
+        case .missingRequiredComponent:
456
+            return nil
457
+        }
458
+    }
459
+}
460
+
461
+extension AFError.MultipartEncodingFailureReason {
462
+    var url: URL? {
463
+        switch self {
464
+        case let .bodyPartURLInvalid(url),
465
+             let .bodyPartFilenameInvalid(url),
466
+             let .bodyPartFileNotReachable(url),
467
+             let .bodyPartFileIsDirectory(url),
468
+             let .bodyPartFileSizeNotAvailable(url),
469
+             let .bodyPartInputStreamCreationFailed(url),
470
+             let .outputStreamCreationFailed(url),
471
+             let .outputStreamFileAlreadyExists(url),
472
+             let .outputStreamURLInvalid(url),
473
+             let .bodyPartFileNotReachableWithError(url, _),
474
+             let .bodyPartFileSizeQueryFailedWithError(url, _):
475
+            return url
476
+        case .outputStreamWriteFailed,
477
+             .inputStreamReadFailed:
478
+            return nil
479
+        }
480
+    }
481
+
482
+    var underlyingError: Error? {
483
+        switch self {
484
+        case let .bodyPartFileNotReachableWithError(_, error),
485
+             let .bodyPartFileSizeQueryFailedWithError(_, error),
486
+             let .outputStreamWriteFailed(error),
487
+             let .inputStreamReadFailed(error):
488
+            return error
489
+        case .bodyPartURLInvalid,
490
+             .bodyPartFilenameInvalid,
491
+             .bodyPartFileNotReachable,
492
+             .bodyPartFileIsDirectory,
493
+             .bodyPartFileSizeNotAvailable,
494
+             .bodyPartInputStreamCreationFailed,
495
+             .outputStreamCreationFailed,
496
+             .outputStreamFileAlreadyExists,
497
+             .outputStreamURLInvalid:
498
+            return nil
499
+        }
500
+    }
501
+}
502
+
503
+extension AFError.ResponseValidationFailureReason {
504
+    var acceptableContentTypes: [String]? {
505
+        switch self {
506
+        case let .missingContentType(types),
507
+             let .unacceptableContentType(types, _):
508
+            return types
509
+        case .dataFileNil,
510
+             .dataFileReadFailed,
511
+             .unacceptableStatusCode,
512
+             .customValidationFailed:
513
+            return nil
514
+        }
515
+    }
516
+
517
+    var responseContentType: String? {
518
+        switch self {
519
+        case let .unacceptableContentType(_, responseType):
520
+            return responseType
521
+        case .dataFileNil,
522
+             .dataFileReadFailed,
523
+             .missingContentType,
524
+             .unacceptableStatusCode,
525
+             .customValidationFailed:
526
+            return nil
527
+        }
528
+    }
529
+
530
+    var responseCode: Int? {
531
+        switch self {
532
+        case let .unacceptableStatusCode(code):
533
+            return code
534
+        case .dataFileNil,
535
+             .dataFileReadFailed,
536
+             .missingContentType,
537
+             .unacceptableContentType,
538
+             .customValidationFailed:
539
+            return nil
540
+        }
541
+    }
542
+
543
+    var underlyingError: Error? {
544
+        switch self {
545
+        case let .customValidationFailed(error):
546
+            return error
547
+        case .dataFileNil,
548
+             .dataFileReadFailed,
549
+             .missingContentType,
550
+             .unacceptableContentType,
551
+             .unacceptableStatusCode:
552
+            return nil
553
+        }
554
+    }
555
+}
556
+
557
+extension AFError.ResponseSerializationFailureReason {
558
+    var failedStringEncoding: String.Encoding? {
559
+        switch self {
560
+        case let .stringSerializationFailed(encoding):
561
+            return encoding
562
+        case .inputDataNilOrZeroLength,
563
+             .inputFileNil,
564
+             .inputFileReadFailed(_),
565
+             .jsonSerializationFailed(_),
566
+             .decodingFailed(_),
567
+             .customSerializationFailed(_),
568
+             .invalidEmptyResponse:
569
+            return nil
570
+        }
571
+    }
572
+
573
+    var underlyingError: Error? {
574
+        switch self {
575
+        case let .jsonSerializationFailed(error),
576
+             let .decodingFailed(error),
577
+             let .customSerializationFailed(error):
578
+            return error
579
+        case .inputDataNilOrZeroLength,
580
+             .inputFileNil,
581
+             .inputFileReadFailed,
582
+             .stringSerializationFailed,
583
+             .invalidEmptyResponse:
584
+            return nil
585
+        }
586
+    }
587
+}
588
+
589
+extension AFError.ServerTrustFailureReason {
590
+    var output: AFError.ServerTrustFailureReason.Output? {
591
+        switch self {
592
+        case let .defaultEvaluationFailed(output),
593
+             let .hostValidationFailed(output),
594
+             let .revocationCheckFailed(output, _):
595
+            return output
596
+        case .noRequiredEvaluator,
597
+             .noCertificatesFound,
598
+             .noPublicKeysFound,
599
+             .policyApplicationFailed,
600
+             .settingAnchorCertificatesFailed,
601
+             .revocationPolicyCreationFailed,
602
+             .trustEvaluationFailed,
603
+             .certificatePinningFailed,
604
+             .publicKeyPinningFailed,
605
+             .customEvaluationFailed:
606
+            return nil
607
+        }
608
+    }
609
+
610
+    var underlyingError: Error? {
611
+        switch self {
612
+        case let .customEvaluationFailed(error):
613
+            return error
614
+        case let .trustEvaluationFailed(error):
615
+            return error
616
+        case .noRequiredEvaluator,
617
+             .noCertificatesFound,
618
+             .noPublicKeysFound,
619
+             .policyApplicationFailed,
620
+             .settingAnchorCertificatesFailed,
621
+             .revocationPolicyCreationFailed,
622
+             .defaultEvaluationFailed,
623
+             .hostValidationFailed,
624
+             .revocationCheckFailed,
625
+             .certificatePinningFailed,
626
+             .publicKeyPinningFailed:
627
+            return nil
628
+        }
629
+    }
630
+}
631
+
632
+// MARK: - Error Descriptions
633
+
634
+extension AFError: LocalizedError {
635
+    public var errorDescription: String? {
636
+        switch self {
637
+        case .explicitlyCancelled:
638
+            return "Request explicitly cancelled."
639
+        case let .invalidURL(url):
640
+            return "URL is not valid: \(url)"
641
+        case let .parameterEncodingFailed(reason):
642
+            return reason.localizedDescription
643
+        case let .parameterEncoderFailed(reason):
644
+            return reason.localizedDescription
645
+        case let .multipartEncodingFailed(reason):
646
+            return reason.localizedDescription
647
+        case let .requestAdaptationFailed(error):
648
+            return "Request adaption failed with error: \(error.localizedDescription)"
649
+        case let .responseValidationFailed(reason):
650
+            return reason.localizedDescription
651
+        case let .responseSerializationFailed(reason):
652
+            return reason.localizedDescription
653
+        case let .requestRetryFailed(retryError, originalError):
654
+            return """
655
+            Request retry failed with retry error: \(retryError.localizedDescription), \
656
+            original error: \(originalError.localizedDescription)
657
+            """
658
+        case .sessionDeinitialized:
659
+            return """
660
+            Session was invalidated without error, so it was likely deinitialized unexpectedly. \
661
+            Be sure to retain a reference to your Session for the duration of your requests.
662
+            """
663
+        case let .sessionInvalidated(error):
664
+            return "Session was invalidated with error: \(error?.localizedDescription ?? "No description.")"
665
+        case let .serverTrustEvaluationFailed(reason):
666
+            return "Server trust evaluation failed due to reason: \(reason.localizedDescription)"
667
+        case let .urlRequestValidationFailed(reason):
668
+            return "URLRequest validation failed due to reason: \(reason.localizedDescription)"
669
+        case let .createUploadableFailed(error):
670
+            return "Uploadable creation failed with error: \(error.localizedDescription)"
671
+        case let .createURLRequestFailed(error):
672
+            return "URLRequest creation failed with error: \(error.localizedDescription)"
673
+        case let .downloadedFileMoveFailed(error, source, destination):
674
+            return "Moving downloaded file from: \(source) to: \(destination) failed with error: \(error.localizedDescription)"
675
+        case let .sessionTaskFailed(error):
676
+            return "URLSessionTask failed with error: \(error.localizedDescription)"
677
+        }
678
+    }
679
+}
680
+
681
+extension AFError.ParameterEncodingFailureReason {
682
+    var localizedDescription: String {
683
+        switch self {
684
+        case .missingURL:
685
+            return "URL request to encode was missing a URL"
686
+        case let .jsonEncodingFailed(error):
687
+            return "JSON could not be encoded because of error:\n\(error.localizedDescription)"
688
+        case let .customEncodingFailed(error):
689
+            return "Custom parameter encoder failed with error: \(error.localizedDescription)"
690
+        }
691
+    }
692
+}
693
+
694
+extension AFError.ParameterEncoderFailureReason {
695
+    var localizedDescription: String {
696
+        switch self {
697
+        case let .missingRequiredComponent(component):
698
+            return "Encoding failed due to a missing request component: \(component)"
699
+        case let .encoderFailed(error):
700
+            return "The underlying encoder failed with the error: \(error)"
701
+        }
702
+    }
703
+}
704
+
705
+extension AFError.MultipartEncodingFailureReason {
706
+    var localizedDescription: String {
707
+        switch self {
708
+        case let .bodyPartURLInvalid(url):
709
+            return "The URL provided is not a file URL: \(url)"
710
+        case let .bodyPartFilenameInvalid(url):
711
+            return "The URL provided does not have a valid filename: \(url)"
712
+        case let .bodyPartFileNotReachable(url):
713
+            return "The URL provided is not reachable: \(url)"
714
+        case let .bodyPartFileNotReachableWithError(url, error):
715
+            return """
716
+            The system returned an error while checking the provided URL for reachability.
717
+            URL: \(url)
718
+            Error: \(error)
719
+            """
720
+        case let .bodyPartFileIsDirectory(url):
721
+            return "The URL provided is a directory: \(url)"
722
+        case let .bodyPartFileSizeNotAvailable(url):
723
+            return "Could not fetch the file size from the provided URL: \(url)"
724
+        case let .bodyPartFileSizeQueryFailedWithError(url, error):
725
+            return """
726
+            The system returned an error while attempting to fetch the file size from the provided URL.
727
+            URL: \(url)
728
+            Error: \(error)
729
+            """
730
+        case let .bodyPartInputStreamCreationFailed(url):
731
+            return "Failed to create an InputStream for the provided URL: \(url)"
732
+        case let .outputStreamCreationFailed(url):
733
+            return "Failed to create an OutputStream for URL: \(url)"
734
+        case let .outputStreamFileAlreadyExists(url):
735
+            return "A file already exists at the provided URL: \(url)"
736
+        case let .outputStreamURLInvalid(url):
737
+            return "The provided OutputStream URL is invalid: \(url)"
738
+        case let .outputStreamWriteFailed(error):
739
+            return "OutputStream write failed with error: \(error)"
740
+        case let .inputStreamReadFailed(error):
741
+            return "InputStream read failed with error: \(error)"
742
+        }
743
+    }
744
+}
745
+
746
+extension AFError.ResponseSerializationFailureReason {
747
+    var localizedDescription: String {
748
+        switch self {
749
+        case .inputDataNilOrZeroLength:
750
+            return "Response could not be serialized, input data was nil or zero length."
751
+        case .inputFileNil:
752
+            return "Response could not be serialized, input file was nil."
753
+        case let .inputFileReadFailed(url):
754
+            return "Response could not be serialized, input file could not be read: \(url)."
755
+        case let .stringSerializationFailed(encoding):
756
+            return "String could not be serialized with encoding: \(encoding)."
757
+        case let .jsonSerializationFailed(error):
758
+            return "JSON could not be serialized because of error:\n\(error.localizedDescription)"
759
+        case let .invalidEmptyResponse(type):
760
+            return """
761
+            Empty response could not be serialized to type: \(type). \
762
+            Use Empty as the expected type for such responses.
763
+            """
764
+        case let .decodingFailed(error):
765
+            return "Response could not be decoded because of error:\n\(error.localizedDescription)"
766
+        case let .customSerializationFailed(error):
767
+            return "Custom response serializer failed with error:\n\(error.localizedDescription)"
768
+        }
769
+    }
770
+}
771
+
772
+extension AFError.ResponseValidationFailureReason {
773
+    var localizedDescription: String {
774
+        switch self {
775
+        case .dataFileNil:
776
+            return "Response could not be validated, data file was nil."
777
+        case let .dataFileReadFailed(url):
778
+            return "Response could not be validated, data file could not be read: \(url)."
779
+        case let .missingContentType(types):
780
+            return """
781
+            Response Content-Type was missing and acceptable content types \
782
+            (\(types.joined(separator: ","))) do not match "*/*".
783
+            """
784
+        case let .unacceptableContentType(acceptableTypes, responseType):
785
+            return """
786
+            Response Content-Type "\(responseType)" does not match any acceptable types: \
787
+            \(acceptableTypes.joined(separator: ",")).
788
+            """
789
+        case let .unacceptableStatusCode(code):
790
+            return "Response status code was unacceptable: \(code)."
791
+        case let .customValidationFailed(error):
792
+            return "Custom response validation failed with error: \(error.localizedDescription)"
793
+        }
794
+    }
795
+}
796
+
797
+extension AFError.ServerTrustFailureReason {
798
+    var localizedDescription: String {
799
+        switch self {
800
+        case let .noRequiredEvaluator(host):
801
+            return "A ServerTrustEvaluating value is required for host \(host) but none was found."
802
+        case .noCertificatesFound:
803
+            return "No certificates were found or provided for evaluation."
804
+        case .noPublicKeysFound:
805
+            return "No public keys were found or provided for evaluation."
806
+        case .policyApplicationFailed:
807
+            return "Attempting to set a SecPolicy failed."
808
+        case .settingAnchorCertificatesFailed:
809
+            return "Attempting to set the provided certificates as anchor certificates failed."
810
+        case .revocationPolicyCreationFailed:
811
+            return "Attempting to create a revocation policy failed."
812
+        case let .trustEvaluationFailed(error):
813
+            return "SecTrust evaluation failed with error: \(error?.localizedDescription ?? "None")"
814
+        case let .defaultEvaluationFailed(output):
815
+            return "Default evaluation failed for host \(output.host)."
816
+        case let .hostValidationFailed(output):
817
+            return "Host validation failed for host \(output.host)."
818
+        case let .revocationCheckFailed(output, _):
819
+            return "Revocation check failed for host \(output.host)."
820
+        case let .certificatePinningFailed(host, _, _, _):
821
+            return "Certificate pinning failed for host \(host)."
822
+        case let .publicKeyPinningFailed(host, _, _, _):
823
+            return "Public key pinning failed for host \(host)."
824
+        case let .customEvaluationFailed(error):
825
+            return "Custom trust evaluation failed with error: \(error.localizedDescription)"
826
+        }
827
+    }
828
+}
829
+
830
+extension AFError.URLRequestValidationFailureReason {
831
+    var localizedDescription: String {
832
+        switch self {
833
+        case let .bodyDataInGETRequest(data):
834
+            return """
835
+            Invalid URLRequest: Requests with GET method cannot have body data:
836
+            \(String(decoding: data, as: UTF8.self))
837
+            """
838
+        }
839
+    }
840
+}

+ 520
- 0
trolley/Pods/Alamofire/Source/Alamofire.swift 查看文件

@@ -0,0 +1,520 @@
1
+//
2
+//  Alamofire.swift
3
+//
4
+//  Copyright (c) 2014-2018 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
+/// Global namespace containing API for the `default` `Session` instance.
28
+public enum AF {
29
+    /// Current Alamofire version. Necessary since SPM doesn't use dynamic libraries. Plus this will be more accurate.
30
+    static let version = "5.0.0-rc.3"
31
+
32
+    // MARK: - Data Request
33
+
34
+    /// Creates a `DataRequest` using `Session.default` to retrieve the contents of the specified `url` using the
35
+    /// `method`, `parameters`, `encoding`, and `headers` provided.
36
+    ///
37
+    /// - Parameters:
38
+    ///   - url:           The `URLConvertible` value.
39
+    ///   - method:        The `HTTPMethod`, `.get` by default.
40
+    ///   - parameters:    The `Parameters`, `nil` by default.
41
+    ///   - encoding:      The `ParameterEncoding`, `URLEncoding.default` by default.
42
+    ///   - headers:       The `HTTPHeaders`, `nil` by default.
43
+    ///   - interceptor:   The `RequestInterceptor`, `nil` by default.
44
+    ///
45
+    /// - Returns: The created `DataRequest`.
46
+    public static func request(_ url: URLConvertible,
47
+                               method: HTTPMethod = .get,
48
+                               parameters: Parameters? = nil,
49
+                               encoding: ParameterEncoding = URLEncoding.default,
50
+                               headers: HTTPHeaders? = nil,
51
+                               interceptor: RequestInterceptor? = nil) -> DataRequest {
52
+        return Session.default.request(url,
53
+                                       method: method,
54
+                                       parameters: parameters,
55
+                                       encoding: encoding,
56
+                                       headers: headers,
57
+                                       interceptor: interceptor)
58
+    }
59
+
60
+    /// Creates a `DataRequest` using `Session.default` to retrieve the contents of the specified `url` using the
61
+    /// `method`, `parameters`, `encoding`, and `headers` provided.
62
+    ///
63
+    /// - Parameters:
64
+    ///   - url:           The `URLConvertible` value.
65
+    ///   - method:        The `HTTPMethod`, `.get` by default.
66
+    ///   - parameters:    The `Encodable` parameters, `nil` by default.
67
+    ///   - encoding:      The `ParameterEncoder`, `URLEncodedFormParameterEncoder.default` by default.
68
+    ///   - headers:       The `HTTPHeaders`, `nil` by default.
69
+    ///   - interceptor:   The `RequestInterceptor`, `nil` by default.
70
+    ///
71
+    /// - Returns: The created `DataRequest`.
72
+    public static func request<Parameters: Encodable>(_ url: URLConvertible,
73
+                                                      method: HTTPMethod = .get,
74
+                                                      parameters: Parameters? = nil,
75
+                                                      encoder: ParameterEncoder = URLEncodedFormParameterEncoder.default,
76
+                                                      headers: HTTPHeaders? = nil,
77
+                                                      interceptor: RequestInterceptor? = nil) -> DataRequest {
78
+        return Session.default.request(url,
79
+                                       method: method,
80
+                                       parameters: parameters,
81
+                                       encoder: encoder,
82
+                                       headers: headers,
83
+                                       interceptor: interceptor)
84
+    }
85
+
86
+    /// Creates a `DataRequest` using `Session.default` to execute the specified `urlRequest`.
87
+    ///
88
+    /// - Parameters:
89
+    ///   - urlRequest:    The `URLRequestConvertible` value.
90
+    ///   - interceptor:   The `RequestInterceptor`, `nil` by default.
91
+    ///
92
+    /// - Returns: The created `DataRequest`.
93
+    public static func request(_ urlRequest: URLRequestConvertible, interceptor: RequestInterceptor? = nil) -> DataRequest {
94
+        return Session.default.request(urlRequest, interceptor: interceptor)
95
+    }
96
+
97
+    // MARK: - Download Request
98
+
99
+    /// Creates a `DownloadRequest` using `Session.default` to download the contents of the specified `url` to
100
+    /// the provided `destination` using the `method`, `parameters`, `encoding`, and `headers` provided.
101
+    ///
102
+    /// If `destination` is not specified, the download will be moved to a temporary location determined by Alamofire.
103
+    ///
104
+    /// - Parameters:
105
+    ///   - url:           The `URLConvertible` value.
106
+    ///   - method:        The `HTTPMethod`, `.get` by default.
107
+    ///   - parameters:    The `Parameters`, `nil` by default.
108
+    ///   - encoding:      The `ParameterEncoding`, `URLEncoding.default` by default.
109
+    ///   - headers:       The `HTTPHeaders`, `nil` by default.
110
+    ///   - interceptor:   The `RequestInterceptor`, `nil` by default.
111
+    ///   - destination:   The `DownloadRequest.Destination` closure used the determine the destination of the
112
+    ///                    downloaded file. `nil` by default.
113
+    ///
114
+    /// - Returns: The created `DownloadRequest`.
115
+    public static func download(_ url: URLConvertible,
116
+                                method: HTTPMethod = .get,
117
+                                parameters: Parameters? = nil,
118
+                                encoding: ParameterEncoding = URLEncoding.default,
119
+                                headers: HTTPHeaders? = nil,
120
+                                interceptor: RequestInterceptor? = nil,
121
+                                to destination: DownloadRequest.Destination? = nil) -> DownloadRequest {
122
+        return Session.default.download(url,
123
+                                        method: method,
124
+                                        parameters: parameters,
125
+                                        encoding: encoding,
126
+                                        headers: headers,
127
+                                        interceptor: interceptor,
128
+                                        to: destination)
129
+    }
130
+
131
+    /// Creates a `DownloadRequest` using `Session.default` to download the contents of the specified `url` to the
132
+    /// provided `destination` using the `method`, encodable `parameters`, `encoder`, and `headers` provided.
133
+    ///
134
+    /// - Note: If `destination` is not specified, the download will be moved to a temporary location determined by
135
+    ///         Alamofire.
136
+    ///
137
+    /// - Parameters:
138
+    ///   - url:           The `URLConvertible` value.
139
+    ///   - method:        The `HTTPMethod`, `.get` by default.
140
+    ///   - parameters:    The `Encodable` parameters, `nil` by default.
141
+    ///   - encoder:       The `ParameterEncoder`, `URLEncodedFormParameterEncoder.default` by default.
142
+    ///   - headers:       The `HTTPHeaders`, `nil` by default.
143
+    ///   - interceptor:   The `RequestInterceptor`, `nil` by default.
144
+    ///   - destination:   The `DownloadRequest.Destination` closure used the determine the destination of the
145
+    ///                    downloaded file. `nil` by default.
146
+    ///
147
+    /// - Returns: The created `DownloadRequest`.
148
+    public static func download<Parameters: Encodable>(_ url: URLConvertible,
149
+                                                       method: HTTPMethod = .get,
150
+                                                       parameters: Parameters? = nil,
151
+                                                       encoder: ParameterEncoder = URLEncodedFormParameterEncoder.default,
152
+                                                       headers: HTTPHeaders? = nil,
153
+                                                       interceptor: RequestInterceptor? = nil,
154
+                                                       to destination: DownloadRequest.Destination? = nil) -> DownloadRequest {
155
+        return Session.default.download(url,
156
+                                        method: method,
157
+                                        parameters: parameters,
158
+                                        encoder: encoder,
159
+                                        headers: headers,
160
+                                        interceptor: interceptor,
161
+                                        to: destination)
162
+    }
163
+
164
+    // MARK: URLRequest
165
+
166
+    /// Creates a `DownloadRequest` using `Session.default` to execute the specified `urlRequest` and download
167
+    /// the result to the provided `destination`.
168
+    ///
169
+    /// - Parameters:
170
+    ///   - urlRequest:    The `URLRequestConvertible` value.
171
+    ///   - interceptor:   The `RequestInterceptor`, `nil` by default.
172
+    ///   - destination:   The `DownloadRequest.Destination` closure used the determine the destination of the
173
+    ///                    downloaded file. `nil` by default.
174
+    ///
175
+    /// - Returns: The created `DownloadRequest`.
176
+    public static func download(_ urlRequest: URLRequestConvertible,
177
+                                interceptor: RequestInterceptor? = nil,
178
+                                to destination: DownloadRequest.Destination? = nil) -> DownloadRequest {
179
+        return Session.default.download(urlRequest, interceptor: interceptor, to: destination)
180
+    }
181
+
182
+    // MARK: Resume Data
183
+
184
+    /// Creates a `DownloadRequest` using the `Session.default` from the `resumeData` produced from a previous
185
+    /// `DownloadRequest` cancellation to retrieve the contents of the original request and save them to the `destination`.
186
+    ///
187
+    /// - Note: If `destination` is not specified, the download will be moved to a temporary location determined by
188
+    ///         Alamofire.
189
+    ///
190
+    /// - Note: On some versions of all Apple platforms (iOS 10 - 10.2, macOS 10.12 - 10.12.2, tvOS 10 - 10.1, watchOS 3 - 3.1.1),
191
+    /// `resumeData` is broken on background URL session configurations. There's an underlying bug in the `resumeData`
192
+    /// generation logic where the data is written incorrectly and will always fail to resume the download. For more
193
+    /// information about the bug and possible workarounds, please refer to the [this Stack Overflow post](http://stackoverflow.com/a/39347461/1342462).
194
+    ///
195
+    /// - Parameters:
196
+    ///   - resumeData:    The resume `Data`. This is an opaque blob produced by `URLSessionDownloadTask` when a task is
197
+    ///                    cancelled. See [Apple's documentation](https://developer.apple.com/documentation/foundation/urlsessiondownloadtask/1411634-cancel)
198
+    ///                    for more information.
199
+    ///   - interceptor:   The `RequestInterceptor`, `nil` by default.
200
+    ///   - destination:   The `DownloadRequest.Destination` closure used to determine the destination of the downloaded
201
+    ///                    file. `nil` by default.
202
+    ///
203
+    /// - Returns:         The created `DownloadRequest`.
204
+    public static func download(resumingWith resumeData: Data,
205
+                                interceptor: RequestInterceptor? = nil,
206
+                                to destination: DownloadRequest.Destination? = nil) -> DownloadRequest {
207
+        return Session.default.download(resumingWith: resumeData, interceptor: interceptor, to: destination)
208
+    }
209
+
210
+    // MARK: - Upload Request
211
+
212
+    // MARK: Data
213
+
214
+    /// Creates an `UploadRequest` for the given `Data`, `URLRequest` components, and `RequestInterceptor`.
215
+    ///
216
+    /// - Parameters:
217
+    ///   - data:        The `Data` to upload.
218
+    ///   - convertible: `URLConvertible` value to be used as the `URLRequest`'s `URL`.
219
+    ///   - method:      `HTTPMethod` for the `URLRequest`. `.post` by default.
220
+    ///   - headers:     `HTTPHeaders` value to be added to the `URLRequest`. `nil` by default.
221
+    ///   - interceptor: `RequestInterceptor` value to be used by the returned `DataRequest`. `nil` by default.
222
+    ///   - fileManager: `FileManager` instance to be used by the returned `UploadRequest`. `.default` instance by
223
+    ///                  default.
224
+    ///
225
+    /// - Returns:       The created `UploadRequest`.
226
+    public static func upload(_ data: Data,
227
+                              to convertible: URLConvertible,
228
+                              method: HTTPMethod = .post,
229
+                              headers: HTTPHeaders? = nil,
230
+                              interceptor: RequestInterceptor? = nil,
231
+                              fileManager: FileManager = .default) -> UploadRequest {
232
+        return Session.default.upload(data,
233
+                                      to: convertible,
234
+                                      method: method,
235
+                                      headers: headers,
236
+                                      interceptor: interceptor,
237
+                                      fileManager: fileManager)
238
+    }
239
+
240
+    /// Creates an `UploadRequest` for the given `Data` using the `URLRequestConvertible` value and `RequestInterceptor`.
241
+    ///
242
+    /// - Parameters:
243
+    ///   - data:        The `Data` to upload.
244
+    ///   - convertible: `URLRequestConvertible` value to be used to create the `URLRequest`.
245
+    ///   - interceptor: `RequestInterceptor` value to be used by the returned `DataRequest`. `nil` by default.
246
+    ///   - fileManager: `FileManager` instance to be used by the returned `UploadRequest`. `.default` instance by
247
+    ///                  default.
248
+    ///
249
+    /// - Returns:       The created `UploadRequest`.
250
+    public static func upload(_ data: Data,
251
+                              with convertible: URLRequestConvertible,
252
+                              interceptor: RequestInterceptor? = nil,
253
+                              fileManager: FileManager = .default) -> UploadRequest {
254
+        return Session.default.upload(data, with: convertible, interceptor: interceptor, fileManager: fileManager)
255
+    }
256
+
257
+    // MARK: File
258
+
259
+    /// Creates an `UploadRequest` for the file at the given file `URL`, using a `URLRequest` from the provided
260
+    /// components and `RequestInterceptor`.
261
+    ///
262
+    /// - Parameters:
263
+    ///   - fileURL:     The `URL` of the file to upload.
264
+    ///   - convertible: `URLConvertible` value to be used as the `URLRequest`'s `URL`.
265
+    ///   - method:      `HTTPMethod` for the `URLRequest`. `.post` by default.
266
+    ///   - headers:     `HTTPHeaders` value to be added to the `URLRequest`. `nil` by default.
267
+    ///   - interceptor: `RequestInterceptor` value to be used by the returned `UploadRequest`. `nil` by default.
268
+    ///   - fileManager: `FileManager` instance to be used by the returned `UploadRequest`. `.default` instance by
269
+    ///                  default.
270
+    ///
271
+    /// - Returns:       The created `UploadRequest`.
272
+    public static func upload(_ fileURL: URL,
273
+                              to convertible: URLConvertible,
274
+                              method: HTTPMethod = .post,
275
+                              headers: HTTPHeaders? = nil,
276
+                              interceptor: RequestInterceptor? = nil,
277
+                              fileManager: FileManager = .default) -> UploadRequest {
278
+        return Session.default.upload(fileURL,
279
+                                      to: convertible,
280
+                                      method: method,
281
+                                      headers: headers,
282
+                                      interceptor: interceptor,
283
+                                      fileManager: fileManager)
284
+    }
285
+
286
+    /// Creates an `UploadRequest` for the file at the given file `URL` using the `URLRequestConvertible` value and
287
+    /// `RequestInterceptor`.
288
+    ///
289
+    /// - Parameters:
290
+    ///   - fileURL:     The `URL` of the file to upload.
291
+    ///   - convertible: `URLRequestConvertible` value to be used to create the `URLRequest`.
292
+    ///   - interceptor: `RequestInterceptor` value to be used by the returned `DataRequest`. `nil` by default.
293
+    ///   - fileManager: `FileManager` instance to be used by the returned `UploadRequest`. `.default` instance by
294
+    ///                  default.
295
+    ///
296
+    /// - Returns:       The created `UploadRequest`.
297
+    public static func upload(_ fileURL: URL,
298
+                              with convertible: URLRequestConvertible,
299
+                              interceptor: RequestInterceptor? = nil,
300
+                              fileManager: FileManager = .default) -> UploadRequest {
301
+        return Session.default.upload(fileURL, with: convertible, interceptor: interceptor, fileManager: fileManager)
302
+    }
303
+
304
+    // MARK: InputStream
305
+
306
+    /// Creates an `UploadRequest` from the `InputStream` provided using a `URLRequest` from the provided components and
307
+    /// `RequestInterceptor`.
308
+    ///
309
+    /// - Parameters:
310
+    ///   - stream:      The `InputStream` that provides the data to upload.
311
+    ///   - convertible: `URLConvertible` value to be used as the `URLRequest`'s `URL`.
312
+    ///   - method:      `HTTPMethod` for the `URLRequest`. `.post` by default.
313
+    ///   - headers:     `HTTPHeaders` value to be added to the `URLRequest`. `nil` by default.
314
+    ///   - interceptor: `RequestInterceptor` value to be used by the returned `DataRequest`. `nil` by default.
315
+    ///   - fileManager: `FileManager` instance to be used by the returned `UploadRequest`. `.default` instance by
316
+    ///                  default.
317
+    ///
318
+    /// - Returns:       The created `UploadRequest`.
319
+    public static func upload(_ stream: InputStream,
320
+                              to convertible: URLConvertible,
321
+                              method: HTTPMethod = .post,
322
+                              headers: HTTPHeaders? = nil,
323
+                              interceptor: RequestInterceptor? = nil,
324
+                              fileManager: FileManager = .default) -> UploadRequest {
325
+        return Session.default.upload(stream,
326
+                                      to: convertible,
327
+                                      method: method,
328
+                                      headers: headers,
329
+                                      interceptor: interceptor,
330
+                                      fileManager: fileManager)
331
+    }
332
+
333
+    /// Creates an `UploadRequest` from the provided `InputStream` using the `URLRequestConvertible` value and
334
+    /// `RequestInterceptor`.
335
+    ///
336
+    /// - Parameters:
337
+    ///   - stream:      The `InputStream` that provides the data to upload.
338
+    ///   - convertible: `URLRequestConvertible` value to be used to create the `URLRequest`.
339
+    ///   - interceptor: `RequestInterceptor` value to be used by the returned `DataRequest`. `nil` by default.
340
+    ///   - fileManager: `FileManager` instance to be used by the returned `UploadRequest`. `.default` instance by
341
+    ///                  default.
342
+    ///
343
+    /// - Returns:       The created `UploadRequest`.
344
+    public static func upload(_ stream: InputStream,
345
+                              with convertible: URLRequestConvertible,
346
+                              interceptor: RequestInterceptor? = nil,
347
+                              fileManager: FileManager = .default) -> UploadRequest {
348
+        return Session.default.upload(stream, with: convertible, interceptor: interceptor, fileManager: fileManager)
349
+    }
350
+
351
+    // MARK: MultipartFormData
352
+
353
+    /// Creates an `UploadRequest` for the multipart form data built using a closure and sent using the provided
354
+    /// `URLRequest` components and `RequestInterceptor`.
355
+    ///
356
+    /// It is important to understand the memory implications of uploading `MultipartFormData`. If the cumulative
357
+    /// payload is small, encoding the data in-memory and directly uploading to a server is the by far the most
358
+    /// efficient approach. However, if the payload is too large, encoding the data in-memory could cause your app to
359
+    /// be terminated. Larger payloads must first be written to disk using input and output streams to keep the memory
360
+    /// footprint low, then the data can be uploaded as a stream from the resulting file. Streaming from disk MUST be
361
+    /// used for larger payloads such as video content.
362
+    ///
363
+    /// The `encodingMemoryThreshold` parameter allows Alamofire to automatically determine whether to encode in-memory
364
+    /// or stream from disk. If the content length of the `MultipartFormData` is below the `encodingMemoryThreshold`,
365
+    /// encoding takes place in-memory. If the content length exceeds the threshold, the data is streamed to disk
366
+    /// during the encoding process. Then the result is uploaded as data or as a stream depending on which encoding
367
+    /// technique was used.
368
+    ///
369
+    /// - Parameters:
370
+    ///   - multipartFormData:       `MultipartFormData` building closure.
371
+    ///   - convertible:             `URLConvertible` value to be used as the `URLRequest`'s `URL`.
372
+    ///   - encodingMemoryThreshold: Byte threshold used to determine whether the form data is encoded into memory or
373
+    ///                              onto disk before being uploaded. `MultipartFormData.encodingMemoryThreshold` by
374
+    ///                              default.
375
+    ///   - method:                  `HTTPMethod` for the `URLRequest`. `.post` by default.
376
+    ///   - headers:                 `HTTPHeaders` value to be added to the `URLRequest`. `nil` by default.
377
+    ///   - interceptor:             `RequestInterceptor` value to be used by the returned `DataRequest`. `nil` by default.
378
+    ///   - fileManager:             `FileManager` to be used if the form data exceeds the memory threshold and is
379
+    ///                              written to disk before being uploaded. `.default` instance by default.
380
+    ///
381
+    /// - Returns:                   The created `UploadRequest`.
382
+    public static func upload(multipartFormData: @escaping (MultipartFormData) -> Void,
383
+                              to url: URLConvertible,
384
+                              usingThreshold encodingMemoryThreshold: UInt64 = MultipartFormData.encodingMemoryThreshold,
385
+                              method: HTTPMethod = .post,
386
+                              headers: HTTPHeaders? = nil,
387
+                              interceptor: RequestInterceptor? = nil,
388
+                              fileManager: FileManager = .default) -> UploadRequest {
389
+        return Session.default.upload(multipartFormData: multipartFormData,
390
+                                      to: url,
391
+                                      usingThreshold: encodingMemoryThreshold,
392
+                                      method: method,
393
+                                      headers: headers,
394
+                                      interceptor: interceptor,
395
+                                      fileManager: fileManager)
396
+    }
397
+
398
+    /// Creates an `UploadRequest` using a `MultipartFormData` building closure, the provided `URLRequestConvertible`
399
+    /// value, and a `RequestInterceptor`.
400
+    ///
401
+    /// It is important to understand the memory implications of uploading `MultipartFormData`. If the cumulative
402
+    /// payload is small, encoding the data in-memory and directly uploading to a server is the by far the most
403
+    /// efficient approach. However, if the payload is too large, encoding the data in-memory could cause your app to
404
+    /// be terminated. Larger payloads must first be written to disk using input and output streams to keep the memory
405
+    /// footprint low, then the data can be uploaded as a stream from the resulting file. Streaming from disk MUST be
406
+    /// used for larger payloads such as video content.
407
+    ///
408
+    /// The `encodingMemoryThreshold` parameter allows Alamofire to automatically determine whether to encode in-memory
409
+    /// or stream from disk. If the content length of the `MultipartFormData` is below the `encodingMemoryThreshold`,
410
+    /// encoding takes place in-memory. If the content length exceeds the threshold, the data is streamed to disk
411
+    /// during the encoding process. Then the result is uploaded as data or as a stream depending on which encoding
412
+    /// technique was used.
413
+    ///
414
+    /// - Parameters:
415
+    ///   - multipartFormData:       `MultipartFormData` building closure.
416
+    ///   - request:                 `URLRequestConvertible` value to be used to create the `URLRequest`.
417
+    ///   - encodingMemoryThreshold: Byte threshold used to determine whether the form data is encoded into memory or
418
+    ///                              onto disk before being uploaded. `MultipartFormData.encodingMemoryThreshold` by
419
+    ///                              default.
420
+    ///   - interceptor:             `RequestInterceptor` value to be used by the returned `DataRequest`. `nil` by default.
421
+    ///   - fileManager:             `FileManager` to be used if the form data exceeds the memory threshold and is
422
+    ///                              written to disk before being uploaded. `.default` instance by default.
423
+    ///
424
+    /// - Returns:                   The created `UploadRequest`.
425
+    public static func upload(multipartFormData: @escaping (MultipartFormData) -> Void,
426
+                              with request: URLRequestConvertible,
427
+                              usingThreshold encodingMemoryThreshold: UInt64 = MultipartFormData.encodingMemoryThreshold,
428
+                              interceptor: RequestInterceptor? = nil,
429
+                              fileManager: FileManager = .default) -> UploadRequest {
430
+        return Session.default.upload(multipartFormData: multipartFormData,
431
+                                      with: request,
432
+                                      usingThreshold: encodingMemoryThreshold,
433
+                                      interceptor: interceptor,
434
+                                      fileManager: fileManager)
435
+    }
436
+
437
+    /// Creates an `UploadRequest` for the prebuilt `MultipartFormData` value using the provided `URLRequest` components
438
+    /// and `RequestInterceptor`.
439
+    ///
440
+    /// It is important to understand the memory implications of uploading `MultipartFormData`. If the cumulative
441
+    /// payload is small, encoding the data in-memory and directly uploading to a server is the by far the most
442
+    /// efficient approach. However, if the payload is too large, encoding the data in-memory could cause your app to
443
+    /// be terminated. Larger payloads must first be written to disk using input and output streams to keep the memory
444
+    /// footprint low, then the data can be uploaded as a stream from the resulting file. Streaming from disk MUST be
445
+    /// used for larger payloads such as video content.
446
+    ///
447
+    /// The `encodingMemoryThreshold` parameter allows Alamofire to automatically determine whether to encode in-memory
448
+    /// or stream from disk. If the content length of the `MultipartFormData` is below the `encodingMemoryThreshold`,
449
+    /// encoding takes place in-memory. If the content length exceeds the threshold, the data is streamed to disk
450
+    /// during the encoding process. Then the result is uploaded as data or as a stream depending on which encoding
451
+    /// technique was used.
452
+    ///
453
+    /// - Parameters:
454
+    ///   - multipartFormData:       `MultipartFormData` instance to upload.
455
+    ///   - url:                     `URLConvertible` value to be used as the `URLRequest`'s `URL`.
456
+    ///   - encodingMemoryThreshold: Byte threshold used to determine whether the form data is encoded into memory or
457
+    ///                              onto disk before being uploaded. `MultipartFormData.encodingMemoryThreshold` by
458
+    ///                              default.
459
+    ///   - method:                  `HTTPMethod` for the `URLRequest`. `.post` by default.
460
+    ///   - headers:                 `HTTPHeaders` value to be added to the `URLRequest`. `nil` by default.
461
+    ///   - interceptor:             `RequestInterceptor` value to be used by the returned `DataRequest`. `nil` by default.
462
+    ///   - fileManager:             `FileManager` to be used if the form data exceeds the memory threshold and is
463
+    ///                              written to disk before being uploaded. `.default` instance by default.
464
+    ///
465
+    /// - Returns:                   The created `UploadRequest`.
466
+    public static func upload(multipartFormData: MultipartFormData,
467
+                              to url: URLConvertible,
468
+                              usingThreshold encodingMemoryThreshold: UInt64 = MultipartFormData.encodingMemoryThreshold,
469
+                              method: HTTPMethod = .post,
470
+                              headers: HTTPHeaders? = nil,
471
+                              interceptor: RequestInterceptor? = nil,
472
+                              fileManager: FileManager = .default) -> UploadRequest {
473
+        return Session.default.upload(multipartFormData: multipartFormData,
474
+                                      to: url,
475
+                                      usingThreshold: encodingMemoryThreshold,
476
+                                      method: method,
477
+                                      headers: headers,
478
+                                      interceptor: interceptor,
479
+                                      fileManager: fileManager)
480
+    }
481
+
482
+    /// Creates an `UploadRequest` for the prebuilt `MultipartFormData` value using the providing `URLRequestConvertible`
483
+    /// value and `RequestInterceptor`.
484
+    ///
485
+    /// It is important to understand the memory implications of uploading `MultipartFormData`. If the cumulative
486
+    /// payload is small, encoding the data in-memory and directly uploading to a server is the by far the most
487
+    /// efficient approach. However, if the payload is too large, encoding the data in-memory could cause your app to
488
+    /// be terminated. Larger payloads must first be written to disk using input and output streams to keep the memory
489
+    /// footprint low, then the data can be uploaded as a stream from the resulting file. Streaming from disk MUST be
490
+    /// used for larger payloads such as video content.
491
+    ///
492
+    /// The `encodingMemoryThreshold` parameter allows Alamofire to automatically determine whether to encode in-memory
493
+    /// or stream from disk. If the content length of the `MultipartFormData` is below the `encodingMemoryThreshold`,
494
+    /// encoding takes place in-memory. If the content length exceeds the threshold, the data is streamed to disk
495
+    /// during the encoding process. Then the result is uploaded as data or as a stream depending on which encoding
496
+    /// technique was used.
497
+    ///
498
+    /// - Parameters:
499
+    ///   - multipartFormData:       `MultipartFormData` instance to upload.
500
+    ///   - request:                 `URLRequestConvertible` value to be used to create the `URLRequest`.
501
+    ///   - encodingMemoryThreshold: Byte threshold used to determine whether the form data is encoded into memory or
502
+    ///                              onto disk before being uploaded. `MultipartFormData.encodingMemoryThreshold` by
503
+    ///                              default.
504
+    ///   - interceptor:             `RequestInterceptor` value to be used by the returned `DataRequest`. `nil` by default.
505
+    ///   - fileManager:             `FileManager` instance to be used by the returned `UploadRequest`. `.default` instance by
506
+    ///                              default.
507
+    ///
508
+    /// - Returns:                   The created `UploadRequest`.
509
+    public static func upload(multipartFormData: MultipartFormData,
510
+                              with request: URLRequestConvertible,
511
+                              usingThreshold encodingMemoryThreshold: UInt64 = MultipartFormData.encodingMemoryThreshold,
512
+                              interceptor: RequestInterceptor? = nil,
513
+                              fileManager: FileManager = .default) -> UploadRequest {
514
+        return Session.default.upload(multipartFormData: multipartFormData,
515
+                                      with: request,
516
+                                      usingThreshold: encodingMemoryThreshold,
517
+                                      interceptor: interceptor,
518
+                                      fileManager: fileManager)
519
+    }
520
+}

+ 58
- 0
trolley/Pods/Alamofire/Source/AlamofireExtended.swift 查看文件

@@ -0,0 +1,58 @@
1
+//
2
+//  AlamofireExtended.swift
3
+//
4
+//  Copyright (c) 2019 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
+/// Type that acts as a generic extension point for all `AlamofireExtended` types.
26
+public struct AlamofireExtension<ExtendedType> {
27
+    /// Stores the type or metatype of any extended type.
28
+    let type: ExtendedType
29
+
30
+    init(_ type: ExtendedType) {
31
+        self.type = type
32
+    }
33
+}
34
+
35
+/// Protocol describing the `af` extension points for Alamofire extended types.
36
+public protocol AlamofireExtended {
37
+    /// Type being extended.
38
+    associatedtype ExtendedType
39
+
40
+    /// Static Alamofire extension point.
41
+    static var af: AlamofireExtension<ExtendedType>.Type { get set }
42
+    /// Instance Alamofire extension point.
43
+    var af: AlamofireExtension<ExtendedType> { get set }
44
+}
45
+
46
+public extension AlamofireExtended {
47
+    /// Static Alamofire extension point.
48
+    static var af: AlamofireExtension<Self>.Type {
49
+        get { return AlamofireExtension<Self>.self }
50
+        set {}
51
+    }
52
+
53
+    /// Instance Alamofire extension point.
54
+    var af: AlamofireExtension<Self> {
55
+        get { return AlamofireExtension(self) }
56
+        set {}
57
+    }
58
+}

+ 91
- 0
trolley/Pods/Alamofire/Source/CachedResponseHandler.swift 查看文件

@@ -0,0 +1,91 @@
1
+//
2
+//  CachedResponseHandler.swift
3
+//
4
+//  Copyright (c) 2019 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
+/// A type that handles whether the data task should store the HTTP response in the cache.
28
+public protocol CachedResponseHandler {
29
+    /// Determines whether the HTTP response should be stored in the cache.
30
+    ///
31
+    /// The `completion` closure should be passed one of three possible options:
32
+    ///
33
+    ///   1. The cached response provided by the server (this is the most common use case).
34
+    ///   2. A modified version of the cached response (you may want to modify it in some way before caching).
35
+    ///   3. A `nil` value to prevent the cached response from being stored in the cache.
36
+    ///
37
+    /// - Parameters:
38
+    ///   - task:       The data task whose request resulted in the cached response.
39
+    ///   - response:   The cached response to potentially store in the cache.
40
+    ///   - completion: The closure to execute containing cached response, a modified response, or `nil`.
41
+    func dataTask(_ task: URLSessionDataTask,
42
+                  willCacheResponse response: CachedURLResponse,
43
+                  completion: @escaping (CachedURLResponse?) -> Void)
44
+}
45
+
46
+// MARK: -
47
+
48
+/// `ResponseCacher` is a convenience `CachedResponseHandler` making it easy to cache, not cache, or modify a cached
49
+/// response.
50
+public struct ResponseCacher {
51
+    /// Defines the behavior of the `ResponseCacher` type.
52
+    public enum Behavior {
53
+        /// Stores the cached response in the cache.
54
+        case cache
55
+        /// Prevents the cached response from being stored in the cache.
56
+        case doNotCache
57
+        /// Modifies the cached response before storing it in the cache.
58
+        case modify((URLSessionDataTask, CachedURLResponse) -> CachedURLResponse?)
59
+    }
60
+
61
+    /// Returns a `ResponseCacher` with a follow `Behavior`.
62
+    public static let cache = ResponseCacher(behavior: .cache)
63
+    /// Returns a `ResponseCacher` with a do not follow `Behavior`.
64
+    public static let doNotCache = ResponseCacher(behavior: .doNotCache)
65
+
66
+    /// The `Behavior` of the `ResponseCacher`.
67
+    public let behavior: Behavior
68
+
69
+    /// Creates a `ResponseCacher` instance from the `Behavior`.
70
+    ///
71
+    /// - Parameter behavior: The `Behavior`.
72
+    public init(behavior: Behavior) {
73
+        self.behavior = behavior
74
+    }
75
+}
76
+
77
+extension ResponseCacher: CachedResponseHandler {
78
+    public func dataTask(_ task: URLSessionDataTask,
79
+                         willCacheResponse response: CachedURLResponse,
80
+                         completion: @escaping (CachedURLResponse?) -> Void) {
81
+        switch behavior {
82
+        case .cache:
83
+            completion(response)
84
+        case .doNotCache:
85
+            completion(nil)
86
+        case let .modify(closure):
87
+            let response = closure(task, response)
88
+            completion(response)
89
+        }
90
+    }
91
+}

+ 37
- 0
trolley/Pods/Alamofire/Source/DispatchQueue+Alamofire.swift 查看文件

@@ -0,0 +1,37 @@
1
+//
2
+//  DispatchQueue+Alamofire.swift
3
+//
4
+//  Copyright (c) 2014-2018 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 Dispatch
26
+import Foundation
27
+
28
+extension DispatchQueue {
29
+    /// Execute the provided closure after a `TimeInterval`.
30
+    ///
31
+    /// - Parameters:
32
+    ///   - delay:   `TimeInterval` to delay execution.
33
+    ///   - closure: Closure to execute.
34
+    func after(_ delay: TimeInterval, execute closure: @escaping () -> Void) {
35
+        asyncAfter(deadline: .now() + delay, execute: closure)
36
+    }
37
+}

+ 844
- 0
trolley/Pods/Alamofire/Source/EventMonitor.swift 查看文件

@@ -0,0 +1,844 @@
1
+//
2
+//  EventMonitor.swift
3
+//
4
+//  Copyright (c) 2014-2018 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
+/// Protocol outlining the lifetime events inside Alamofire. It includes both events received from the various
28
+/// `URLSession` delegate protocols as well as various events from the lifetime of `Request` and its subclasses.
29
+public protocol EventMonitor {
30
+    /// The `DispatchQueue` onto which Alamofire's root `CompositeEventMonitor` will dispatch events. `.main` by default.
31
+    var queue: DispatchQueue { get }
32
+
33
+    // MARK: - URLSession Events
34
+
35
+    // MARK: URLSessionDelegate Events
36
+
37
+    /// Event called during `URLSessionDelegate`'s `urlSession(_:didBecomeInvalidWithError:)` method.
38
+    func urlSession(_ session: URLSession, didBecomeInvalidWithError error: Error?)
39
+
40
+    // MARK: URLSessionTaskDelegate Events
41
+
42
+    /// Event called during `URLSessionTaskDelegate`'s `urlSession(_:task:didReceive:completionHandler:)` method.
43
+    func urlSession(_ session: URLSession, task: URLSessionTask, didReceive challenge: URLAuthenticationChallenge)
44
+
45
+    /// Event called during `URLSessionTaskDelegate`'s `urlSession(_:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:)` method.
46
+    func urlSession(_ session: URLSession,
47
+                    task: URLSessionTask,
48
+                    didSendBodyData bytesSent: Int64,
49
+                    totalBytesSent: Int64,
50
+                    totalBytesExpectedToSend: Int64)
51
+
52
+    /// Event called during `URLSessionTaskDelegate`'s `urlSession(_:task:needNewBodyStream:)` method.
53
+    func urlSession(_ session: URLSession, taskNeedsNewBodyStream task: URLSessionTask)
54
+
55
+    /// Event called during `URLSessionTaskDelegate`'s `urlSession(_:task:willPerformHTTPRedirection:newRequest:completionHandler:)` method.
56
+    func urlSession(_ session: URLSession,
57
+                    task: URLSessionTask,
58
+                    willPerformHTTPRedirection response: HTTPURLResponse,
59
+                    newRequest request: URLRequest)
60
+
61
+    /// Event called during `URLSessionTaskDelegate`'s `urlSession(_:task:didFinishCollecting:)` method.
62
+    func urlSession(_ session: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics)
63
+
64
+    /// Event called during `URLSessionTaskDelegate`'s `urlSession(_:task:didCompleteWithError:)` method.
65
+    func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?)
66
+
67
+    /// Event called during `URLSessionTaskDelegate`'s `urlSession(_:taskIsWaitingForConnectivity:)` method.
68
+    @available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
69
+    func urlSession(_ session: URLSession, taskIsWaitingForConnectivity task: URLSessionTask)
70
+
71
+    // MARK: URLSessionDataDelegate Events
72
+
73
+    /// Event called during `URLSessionDataDelegate`'s `urlSession(_:dataTask:didReceive:)` method.
74
+    func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data)
75
+
76
+    /// Event called during `URLSessionDataDelegate`'s `urlSession(_:dataTask:willCacheResponse:completionHandler:)` method.
77
+    func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, willCacheResponse proposedResponse: CachedURLResponse)
78
+
79
+    // MARK: URLSessionDownloadDelegate Events
80
+
81
+    /// Event called during `URLSessionDownloadDelegate`'s `urlSession(_:downloadTask:didResumeAtOffset:expectedTotalBytes:)` method.
82
+    func urlSession(_ session: URLSession,
83
+                    downloadTask: URLSessionDownloadTask,
84
+                    didResumeAtOffset fileOffset: Int64,
85
+                    expectedTotalBytes: Int64)
86
+
87
+    /// Event called during `URLSessionDownloadDelegate`'s `urlSession(_:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:)` method.
88
+    func urlSession(_ session: URLSession,
89
+                    downloadTask: URLSessionDownloadTask,
90
+                    didWriteData bytesWritten: Int64,
91
+                    totalBytesWritten: Int64,
92
+                    totalBytesExpectedToWrite: Int64)
93
+
94
+    /// Event called during `URLSessionDownloadDelegate`'s `urlSession(_:downloadTask:didFinishDownloadingTo:)` method.
95
+    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL)
96
+
97
+    // MARK: - Request Events
98
+
99
+    /// Event called when a `URLRequest` is first created for a `Request`. If a `RequestAdapter` is active, the
100
+    /// `URLRequest` will be adapted before being issued.
101
+    func request(_ request: Request, didCreateInitialURLRequest urlRequest: URLRequest)
102
+
103
+    /// Event called when the attempt to create a `URLRequest` from a `Request`'s original `URLRequestConvertible` value fails.
104
+    func request(_ request: Request, didFailToCreateURLRequestWithError error: AFError)
105
+
106
+    /// Event called when a `RequestAdapter` adapts the `Request`'s initial `URLRequest`.
107
+    func request(_ request: Request, didAdaptInitialRequest initialRequest: URLRequest, to adaptedRequest: URLRequest)
108
+
109
+    /// Event called when a `RequestAdapter` fails to adapt the `Request`'s initial `URLRequest`.
110
+    func request(_ request: Request, didFailToAdaptURLRequest initialRequest: URLRequest, withError error: AFError)
111
+
112
+    /// Event called when a final `URLRequest` is created for a `Request`.
113
+    func request(_ request: Request, didCreateURLRequest urlRequest: URLRequest)
114
+
115
+    /// Event called when a `URLSessionTask` subclass instance is created for a `Request`.
116
+    func request(_ request: Request, didCreateTask task: URLSessionTask)
117
+
118
+    /// Event called when a `Request` receives a `URLSessionTaskMetrics` value.
119
+    func request(_ request: Request, didGatherMetrics metrics: URLSessionTaskMetrics)
120
+
121
+    /// Event called when a `Request` fails due to an error created by Alamofire. e.g. When certificate pinning fails.
122
+    func request(_ request: Request, didFailTask task: URLSessionTask, earlyWithError error: AFError)
123
+
124
+    /// Event called when a `Request`'s task completes, possibly with an error. A `Request` may receive this event
125
+    /// multiple times if it is retried.
126
+    func request(_ request: Request, didCompleteTask task: URLSessionTask, with error: AFError?)
127
+
128
+    /// Event called when a `Request` is about to be retried.
129
+    func requestIsRetrying(_ request: Request)
130
+
131
+    /// Event called when a `Request` finishes and response serializers are being called.
132
+    func requestDidFinish(_ request: Request)
133
+
134
+    /// Event called when a `Request` receives a `resume` call.
135
+    func requestDidResume(_ request: Request)
136
+
137
+    /// Event called when a `Request`'s associated `URLSessionTask` is resumed.
138
+    func request(_ request: Request, didResumeTask task: URLSessionTask)
139
+
140
+    /// Event called when a `Request` receives a `suspend` call.
141
+    func requestDidSuspend(_ request: Request)
142
+
143
+    /// Event called when a `Request`'s associated `URLSessionTask` is suspended.
144
+    func request(_ request: Request, didSuspendTask task: URLSessionTask)
145
+
146
+    /// Event called when a `Request` receives a `cancel` call.
147
+    func requestDidCancel(_ request: Request)
148
+
149
+    /// Event called when a `Request`'s associated `URLSessionTask` is cancelled.
150
+    func request(_ request: Request, didCancelTask task: URLSessionTask)
151
+
152
+    // MARK: DataRequest Events
153
+
154
+    /// Event called when a `DataRequest` calls a `Validation`.
155
+    func request(_ request: DataRequest,
156
+                 didValidateRequest urlRequest: URLRequest?,
157
+                 response: HTTPURLResponse,
158
+                 data: Data?,
159
+                 withResult result: Request.ValidationResult)
160
+
161
+    /// Event called when a `DataRequest` creates a `DataResponse<Data?>` value without calling a `ResponseSerializer`.
162
+    func request(_ request: DataRequest, didParseResponse response: DataResponse<Data?, AFError>)
163
+
164
+    /// Event called when a `DataRequest` calls a `ResponseSerializer` and creates a generic `DataResponse<Value, AFError>`.
165
+    func request<Value>(_ request: DataRequest, didParseResponse response: DataResponse<Value, AFError>)
166
+
167
+    // MARK: UploadRequest Events
168
+
169
+    /// Event called when an `UploadRequest` creates its `Uploadable` value, indicating the type of upload it represents.
170
+    func request(_ request: UploadRequest, didCreateUploadable uploadable: UploadRequest.Uploadable)
171
+
172
+    /// Event called when an `UploadRequest` failed to create its `Uploadable` value due to an error.
173
+    func request(_ request: UploadRequest, didFailToCreateUploadableWithError error: AFError)
174
+
175
+    /// Event called when an `UploadRequest` provides the `InputStream` from its `Uploadable` value. This only occurs if
176
+    /// the `InputStream` does not wrap a `Data` value or file `URL`.
177
+    func request(_ request: UploadRequest, didProvideInputStream stream: InputStream)
178
+
179
+    // MARK: DownloadRequest Events
180
+
181
+    /// Event called when a `DownloadRequest`'s `URLSessionDownloadTask` finishes and the temporary file has been moved.
182
+    func request(_ request: DownloadRequest, didFinishDownloadingUsing task: URLSessionTask, with result: Result<URL, AFError>)
183
+
184
+    /// Event called when a `DownloadRequest`'s `Destination` closure is called and creates the destination URL the
185
+    /// downloaded file will be moved to.
186
+    func request(_ request: DownloadRequest, didCreateDestinationURL url: URL)
187
+
188
+    /// Event called when a `DownloadRequest` calls a `Validation`.
189
+    func request(_ request: DownloadRequest,
190
+                 didValidateRequest urlRequest: URLRequest?,
191
+                 response: HTTPURLResponse,
192
+                 fileURL: URL?,
193
+                 withResult result: Request.ValidationResult)
194
+
195
+    /// Event called when a `DownloadRequest` creates a `DownloadResponse<URL?, AFError>` without calling a `ResponseSerializer`.
196
+    func request(_ request: DownloadRequest, didParseResponse response: DownloadResponse<URL?, AFError>)
197
+
198
+    /// Event called when a `DownloadRequest` calls a `DownloadResponseSerializer` and creates a generic `DownloadResponse<Value, AFError>`
199
+    func request<Value>(_ request: DownloadRequest, didParseResponse response: DownloadResponse<Value, AFError>)
200
+}
201
+
202
+extension EventMonitor {
203
+    /// The default queue on which `CompositeEventMonitor`s will call the `EventMonitor` methods. `.main` by default.
204
+    public var queue: DispatchQueue { return .main }
205
+
206
+    // MARK: Default Implementations
207
+
208
+    public func urlSession(_ session: URLSession, didBecomeInvalidWithError error: Error?) {}
209
+    public func urlSession(_ session: URLSession,
210
+                           task: URLSessionTask,
211
+                           didReceive challenge: URLAuthenticationChallenge) {}
212
+    public func urlSession(_ session: URLSession,
213
+                           task: URLSessionTask,
214
+                           didSendBodyData bytesSent: Int64,
215
+                           totalBytesSent: Int64,
216
+                           totalBytesExpectedToSend: Int64) {}
217
+    public func urlSession(_ session: URLSession, taskNeedsNewBodyStream task: URLSessionTask) {}
218
+    public func urlSession(_ session: URLSession,
219
+                           task: URLSessionTask,
220
+                           willPerformHTTPRedirection response: HTTPURLResponse,
221
+                           newRequest request: URLRequest) {}
222
+    public func urlSession(_ session: URLSession,
223
+                           task: URLSessionTask,
224
+                           didFinishCollecting metrics: URLSessionTaskMetrics) {}
225
+    public func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {}
226
+    public func urlSession(_ session: URLSession, taskIsWaitingForConnectivity task: URLSessionTask) {}
227
+    public func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {}
228
+    public func urlSession(_ session: URLSession,
229
+                           dataTask: URLSessionDataTask,
230
+                           willCacheResponse proposedResponse: CachedURLResponse) {}
231
+    public func urlSession(_ session: URLSession,
232
+                           downloadTask: URLSessionDownloadTask,
233
+                           didResumeAtOffset fileOffset: Int64,
234
+                           expectedTotalBytes: Int64) {}
235
+    public func urlSession(_ session: URLSession,
236
+                           downloadTask: URLSessionDownloadTask,
237
+                           didWriteData bytesWritten: Int64,
238
+                           totalBytesWritten: Int64,
239
+                           totalBytesExpectedToWrite: Int64) {}
240
+    public func urlSession(_ session: URLSession,
241
+                           downloadTask: URLSessionDownloadTask,
242
+                           didFinishDownloadingTo location: URL) {}
243
+    public func request(_ request: Request, didCreateInitialURLRequest urlRequest: URLRequest) {}
244
+    public func request(_ request: Request, didFailToCreateURLRequestWithError error: AFError) {}
245
+    public func request(_ request: Request,
246
+                        didAdaptInitialRequest initialRequest: URLRequest,
247
+                        to adaptedRequest: URLRequest) {}
248
+    public func request(_ request: Request,
249
+                        didFailToAdaptURLRequest initialRequest: URLRequest,
250
+                        withError error: AFError) {}
251
+    public func request(_ request: Request, didCreateURLRequest urlRequest: URLRequest) {}
252
+    public func request(_ request: Request, didCreateTask task: URLSessionTask) {}
253
+    public func request(_ request: Request, didGatherMetrics metrics: URLSessionTaskMetrics) {}
254
+    public func request(_ request: Request, didFailTask task: URLSessionTask, earlyWithError error: AFError) {}
255
+    public func request(_ request: Request, didCompleteTask task: URLSessionTask, with error: AFError?) {}
256
+    public func requestIsRetrying(_ request: Request) {}
257
+    public func requestDidFinish(_ request: Request) {}
258
+    public func requestDidResume(_ request: Request) {}
259
+    public func request(_ request: Request, didResumeTask task: URLSessionTask) {}
260
+    public func requestDidSuspend(_ request: Request) {}
261
+    public func request(_ request: Request, didSuspendTask task: URLSessionTask) {}
262
+    public func requestDidCancel(_ request: Request) {}
263
+    public func request(_ request: Request, didCancelTask task: URLSessionTask) {}
264
+    public func request(_ request: DataRequest,
265
+                        didValidateRequest urlRequest: URLRequest?,
266
+                        response: HTTPURLResponse,
267
+                        data: Data?,
268
+                        withResult result: Request.ValidationResult) {}
269
+    public func request(_ request: DataRequest, didParseResponse response: DataResponse<Data?, AFError>) {}
270
+    public func request<Value>(_ request: DataRequest, didParseResponse response: DataResponse<Value, AFError>) {}
271
+    public func request(_ request: UploadRequest, didCreateUploadable uploadable: UploadRequest.Uploadable) {}
272
+    public func request(_ request: UploadRequest, didFailToCreateUploadableWithError error: AFError) {}
273
+    public func request(_ request: UploadRequest, didProvideInputStream stream: InputStream) {}
274
+    public func request(_ request: DownloadRequest, didFinishDownloadingUsing task: URLSessionTask, with result: Result<URL, AFError>) {}
275
+    public func request(_ request: DownloadRequest, didCreateDestinationURL url: URL) {}
276
+    public func request(_ request: DownloadRequest,
277
+                        didValidateRequest urlRequest: URLRequest?,
278
+                        response: HTTPURLResponse,
279
+                        fileURL: URL?,
280
+                        withResult result: Request.ValidationResult) {}
281
+    public func request(_ request: DownloadRequest, didParseResponse response: DownloadResponse<URL?, AFError>) {}
282
+    public func request<Value>(_ request: DownloadRequest, didParseResponse response: DownloadResponse<Value, AFError>) {}
283
+}
284
+
285
+/// An `EventMonitor` which can contain multiple `EventMonitor`s and calls their methods on their queues.
286
+public final class CompositeEventMonitor: EventMonitor {
287
+    public let queue = DispatchQueue(label: "org.alamofire.compositeEventMonitor", qos: .background)
288
+
289
+    let monitors: [EventMonitor]
290
+
291
+    init(monitors: [EventMonitor]) {
292
+        self.monitors = monitors
293
+    }
294
+
295
+    func performEvent(_ event: @escaping (EventMonitor) -> Void) {
296
+        queue.async {
297
+            for monitor in self.monitors {
298
+                monitor.queue.async { event(monitor) }
299
+            }
300
+        }
301
+    }
302
+
303
+    public func urlSession(_ session: URLSession, didBecomeInvalidWithError error: Error?) {
304
+        performEvent { $0.urlSession(session, didBecomeInvalidWithError: error) }
305
+    }
306
+
307
+    public func urlSession(_ session: URLSession,
308
+                           task: URLSessionTask,
309
+                           didReceive challenge: URLAuthenticationChallenge) {
310
+        performEvent { $0.urlSession(session, task: task, didReceive: challenge) }
311
+    }
312
+
313
+    public func urlSession(_ session: URLSession,
314
+                           task: URLSessionTask,
315
+                           didSendBodyData bytesSent: Int64,
316
+                           totalBytesSent: Int64,
317
+                           totalBytesExpectedToSend: Int64) {
318
+        performEvent {
319
+            $0.urlSession(session,
320
+                          task: task,
321
+                          didSendBodyData: bytesSent,
322
+                          totalBytesSent: totalBytesSent,
323
+                          totalBytesExpectedToSend: totalBytesExpectedToSend)
324
+        }
325
+    }
326
+
327
+    public func urlSession(_ session: URLSession, taskNeedsNewBodyStream task: URLSessionTask) {
328
+        performEvent {
329
+            $0.urlSession(session, taskNeedsNewBodyStream: task)
330
+        }
331
+    }
332
+
333
+    public func urlSession(_ session: URLSession,
334
+                           task: URLSessionTask,
335
+                           willPerformHTTPRedirection response: HTTPURLResponse,
336
+                           newRequest request: URLRequest) {
337
+        performEvent {
338
+            $0.urlSession(session,
339
+                          task: task,
340
+                          willPerformHTTPRedirection: response,
341
+                          newRequest: request)
342
+        }
343
+    }
344
+
345
+    public func urlSession(_ session: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics) {
346
+        performEvent { $0.urlSession(session, task: task, didFinishCollecting: metrics) }
347
+    }
348
+
349
+    public func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
350
+        performEvent { $0.urlSession(session, task: task, didCompleteWithError: error) }
351
+    }
352
+
353
+    @available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
354
+    public func urlSession(_ session: URLSession, taskIsWaitingForConnectivity task: URLSessionTask) {
355
+        performEvent { $0.urlSession(session, taskIsWaitingForConnectivity: task) }
356
+    }
357
+
358
+    public func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
359
+        performEvent { $0.urlSession(session, dataTask: dataTask, didReceive: data) }
360
+    }
361
+
362
+    public func urlSession(_ session: URLSession,
363
+                           dataTask: URLSessionDataTask,
364
+                           willCacheResponse proposedResponse: CachedURLResponse) {
365
+        performEvent { $0.urlSession(session, dataTask: dataTask, willCacheResponse: proposedResponse) }
366
+    }
367
+
368
+    public func urlSession(_ session: URLSession,
369
+                           downloadTask: URLSessionDownloadTask,
370
+                           didResumeAtOffset fileOffset: Int64,
371
+                           expectedTotalBytes: Int64) {
372
+        performEvent {
373
+            $0.urlSession(session,
374
+                          downloadTask: downloadTask,
375
+                          didResumeAtOffset: fileOffset,
376
+                          expectedTotalBytes: expectedTotalBytes)
377
+        }
378
+    }
379
+
380
+    public func urlSession(_ session: URLSession,
381
+                           downloadTask: URLSessionDownloadTask,
382
+                           didWriteData bytesWritten: Int64,
383
+                           totalBytesWritten: Int64,
384
+                           totalBytesExpectedToWrite: Int64) {
385
+        performEvent {
386
+            $0.urlSession(session,
387
+                          downloadTask: downloadTask,
388
+                          didWriteData: bytesWritten,
389
+                          totalBytesWritten: totalBytesWritten,
390
+                          totalBytesExpectedToWrite: totalBytesExpectedToWrite)
391
+        }
392
+    }
393
+
394
+    public func urlSession(_ session: URLSession,
395
+                           downloadTask: URLSessionDownloadTask,
396
+                           didFinishDownloadingTo location: URL) {
397
+        performEvent { $0.urlSession(session, downloadTask: downloadTask, didFinishDownloadingTo: location) }
398
+    }
399
+
400
+    public func request(_ request: Request, didCreateInitialURLRequest urlRequest: URLRequest) {
401
+        performEvent { $0.request(request, didCreateInitialURLRequest: urlRequest) }
402
+    }
403
+
404
+    public func request(_ request: Request, didFailToCreateURLRequestWithError error: AFError) {
405
+        performEvent { $0.request(request, didFailToCreateURLRequestWithError: error) }
406
+    }
407
+
408
+    public func request(_ request: Request, didAdaptInitialRequest initialRequest: URLRequest, to adaptedRequest: URLRequest) {
409
+        performEvent { $0.request(request, didAdaptInitialRequest: initialRequest, to: adaptedRequest) }
410
+    }
411
+
412
+    public func request(_ request: Request, didFailToAdaptURLRequest initialRequest: URLRequest, withError error: AFError) {
413
+        performEvent { $0.request(request, didFailToAdaptURLRequest: initialRequest, withError: error) }
414
+    }
415
+
416
+    public func request(_ request: Request, didCreateURLRequest urlRequest: URLRequest) {
417
+        performEvent { $0.request(request, didCreateURLRequest: urlRequest) }
418
+    }
419
+
420
+    public func request(_ request: Request, didCreateTask task: URLSessionTask) {
421
+        performEvent { $0.request(request, didCreateTask: task) }
422
+    }
423
+
424
+    public func request(_ request: Request, didGatherMetrics metrics: URLSessionTaskMetrics) {
425
+        performEvent { $0.request(request, didGatherMetrics: metrics) }
426
+    }
427
+
428
+    public func request(_ request: Request, didFailTask task: URLSessionTask, earlyWithError error: AFError) {
429
+        performEvent { $0.request(request, didFailTask: task, earlyWithError: error) }
430
+    }
431
+
432
+    public func request(_ request: Request, didCompleteTask task: URLSessionTask, with error: AFError?) {
433
+        performEvent { $0.request(request, didCompleteTask: task, with: error) }
434
+    }
435
+
436
+    public func requestIsRetrying(_ request: Request) {
437
+        performEvent { $0.requestIsRetrying(request) }
438
+    }
439
+
440
+    public func requestDidFinish(_ request: Request) {
441
+        performEvent { $0.requestDidFinish(request) }
442
+    }
443
+
444
+    public func requestDidResume(_ request: Request) {
445
+        performEvent { $0.requestDidResume(request) }
446
+    }
447
+
448
+    public func request(_ request: Request, didResumeTask task: URLSessionTask) {
449
+        performEvent { $0.request(request, didResumeTask: task) }
450
+    }
451
+
452
+    public func requestDidSuspend(_ request: Request) {
453
+        performEvent { $0.requestDidSuspend(request) }
454
+    }
455
+
456
+    public func request(_ request: Request, didSuspendTask task: URLSessionTask) {
457
+        performEvent { $0.request(request, didSuspendTask: task) }
458
+    }
459
+
460
+    public func requestDidCancel(_ request: Request) {
461
+        performEvent { $0.requestDidCancel(request) }
462
+    }
463
+
464
+    public func request(_ request: Request, didCancelTask task: URLSessionTask) {
465
+        performEvent { $0.request(request, didCancelTask: task) }
466
+    }
467
+
468
+    public func request(_ request: DataRequest,
469
+                        didValidateRequest urlRequest: URLRequest?,
470
+                        response: HTTPURLResponse,
471
+                        data: Data?,
472
+                        withResult result: Request.ValidationResult) {
473
+        performEvent { $0.request(request,
474
+                                  didValidateRequest: urlRequest,
475
+                                  response: response,
476
+                                  data: data,
477
+                                  withResult: result)
478
+        }
479
+    }
480
+
481
+    public func request(_ request: DataRequest, didParseResponse response: DataResponse<Data?, AFError>) {
482
+        performEvent { $0.request(request, didParseResponse: response) }
483
+    }
484
+
485
+    public func request<Value>(_ request: DataRequest, didParseResponse response: DataResponse<Value, AFError>) {
486
+        performEvent { $0.request(request, didParseResponse: response) }
487
+    }
488
+
489
+    public func request(_ request: UploadRequest, didCreateUploadable uploadable: UploadRequest.Uploadable) {
490
+        performEvent { $0.request(request, didCreateUploadable: uploadable) }
491
+    }
492
+
493
+    public func request(_ request: UploadRequest, didFailToCreateUploadableWithError error: AFError) {
494
+        performEvent { $0.request(request, didFailToCreateUploadableWithError: error) }
495
+    }
496
+
497
+    public func request(_ request: UploadRequest, didProvideInputStream stream: InputStream) {
498
+        performEvent { $0.request(request, didProvideInputStream: stream) }
499
+    }
500
+
501
+    public func request(_ request: DownloadRequest, didFinishDownloadingUsing task: URLSessionTask, with result: Result<URL, AFError>) {
502
+        performEvent { $0.request(request, didFinishDownloadingUsing: task, with: result) }
503
+    }
504
+
505
+    public func request(_ request: DownloadRequest, didCreateDestinationURL url: URL) {
506
+        performEvent { $0.request(request, didCreateDestinationURL: url) }
507
+    }
508
+
509
+    public func request(_ request: DownloadRequest,
510
+                        didValidateRequest urlRequest: URLRequest?,
511
+                        response: HTTPURLResponse,
512
+                        fileURL: URL?,
513
+                        withResult result: Request.ValidationResult) {
514
+        performEvent { $0.request(request,
515
+                                  didValidateRequest: urlRequest,
516
+                                  response: response,
517
+                                  fileURL: fileURL,
518
+                                  withResult: result) }
519
+    }
520
+
521
+    public func request(_ request: DownloadRequest, didParseResponse response: DownloadResponse<URL?, AFError>) {
522
+        performEvent { $0.request(request, didParseResponse: response) }
523
+    }
524
+
525
+    public func request<Value>(_ request: DownloadRequest, didParseResponse response: DownloadResponse<Value, AFError>) {
526
+        performEvent { $0.request(request, didParseResponse: response) }
527
+    }
528
+}
529
+
530
+/// `EventMonitor` that allows optional closures to be set to receive events.
531
+open class ClosureEventMonitor: EventMonitor {
532
+    /// Closure called on the `urlSession(_:didBecomeInvalidWithError:)` event.
533
+    open var sessionDidBecomeInvalidWithError: ((URLSession, Error?) -> Void)?
534
+
535
+    /// Closure called on the `urlSession(_:task:didReceive:completionHandler:)`.
536
+    open var taskDidReceiveChallenge: ((URLSession, URLSessionTask, URLAuthenticationChallenge) -> Void)?
537
+
538
+    /// Closure that receives `urlSession(_:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:)` event.
539
+    open var taskDidSendBodyData: ((URLSession, URLSessionTask, Int64, Int64, Int64) -> Void)?
540
+
541
+    /// Closure called on the `urlSession(_:task:needNewBodyStream:)` event.
542
+    open var taskNeedNewBodyStream: ((URLSession, URLSessionTask) -> Void)?
543
+
544
+    /// Closure called on the `urlSession(_:task:willPerformHTTPRedirection:newRequest:completionHandler:)` event.
545
+    open var taskWillPerformHTTPRedirection: ((URLSession, URLSessionTask, HTTPURLResponse, URLRequest) -> Void)?
546
+
547
+    /// Closure called on the `urlSession(_:task:didFinishCollecting:)` event.
548
+    open var taskDidFinishCollectingMetrics: ((URLSession, URLSessionTask, URLSessionTaskMetrics) -> Void)?
549
+
550
+    /// Closure called on the `urlSession(_:task:didCompleteWithError:)` event.
551
+    open var taskDidComplete: ((URLSession, URLSessionTask, Error?) -> Void)?
552
+
553
+    /// Closure called on the `urlSession(_:taskIsWaitingForConnectivity:)` event.
554
+    open var taskIsWaitingForConnectivity: ((URLSession, URLSessionTask) -> Void)?
555
+
556
+    /// Closure that receives the `urlSession(_:dataTask:didReceive:)` event.
557
+    open var dataTaskDidReceiveData: ((URLSession, URLSessionDataTask, Data) -> Void)?
558
+
559
+    /// Closure called on the `urlSession(_:dataTask:willCacheResponse:completionHandler:)` event.
560
+    open var dataTaskWillCacheResponse: ((URLSession, URLSessionDataTask, CachedURLResponse) -> Void)?
561
+
562
+    /// Closure called on the `urlSession(_:downloadTask:didFinishDownloadingTo:)` event.
563
+    open var downloadTaskDidFinishDownloadingToURL: ((URLSession, URLSessionDownloadTask, URL) -> Void)?
564
+
565
+    /// Closure called on the `urlSession(_:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:)`
566
+    /// event.
567
+    open var downloadTaskDidWriteData: ((URLSession, URLSessionDownloadTask, Int64, Int64, Int64) -> Void)?
568
+
569
+    /// Closure called on the `urlSession(_:downloadTask:didResumeAtOffset:expectedTotalBytes:)` event.
570
+    open var downloadTaskDidResumeAtOffset: ((URLSession, URLSessionDownloadTask, Int64, Int64) -> Void)?
571
+
572
+    // MARK: - Request Events
573
+
574
+    /// Closure called on the `request(_:didCreateInitialURLRequest:)` event.
575
+    open var requestDidCreateInitialURLRequest: ((Request, URLRequest) -> Void)?
576
+
577
+    /// Closure called on the `request(_:didFailToCreateURLRequestWithError:)` event.
578
+    open var requestDidFailToCreateURLRequestWithError: ((Request, AFError) -> Void)?
579
+
580
+    /// Closure called on the `request(_:didAdaptInitialRequest:to:)` event.
581
+    open var requestDidAdaptInitialRequestToAdaptedRequest: ((Request, URLRequest, URLRequest) -> Void)?
582
+
583
+    /// Closure called on the `request(_:didFailToAdaptURLRequest:withError:)` event.
584
+    open var requestDidFailToAdaptURLRequestWithError: ((Request, URLRequest, AFError) -> Void)?
585
+
586
+    /// Closure called on the `request(_:didCreateURLRequest:)` event.
587
+    open var requestDidCreateURLRequest: ((Request, URLRequest) -> Void)?
588
+
589
+    /// Closure called on the `request(_:didCreateTask:)` event.
590
+    open var requestDidCreateTask: ((Request, URLSessionTask) -> Void)?
591
+
592
+    /// Closure called on the `request(_:didGatherMetrics:)` event.
593
+    open var requestDidGatherMetrics: ((Request, URLSessionTaskMetrics) -> Void)?
594
+
595
+    /// Closure called on the `request(_:didFailTask:earlyWithError:)` event.
596
+    open var requestDidFailTaskEarlyWithError: ((Request, URLSessionTask, AFError) -> Void)?
597
+
598
+    /// Closure called on the `request(_:didCompleteTask:with:)` event.
599
+    open var requestDidCompleteTaskWithError: ((Request, URLSessionTask, AFError?) -> Void)?
600
+
601
+    /// Closure called on the `requestIsRetrying(_:)` event.
602
+    open var requestIsRetrying: ((Request) -> Void)?
603
+
604
+    /// Closure called on the `requestDidFinish(_:)` event.
605
+    open var requestDidFinish: ((Request) -> Void)?
606
+
607
+    /// Closure called on the `requestDidResume(_:)` event.
608
+    open var requestDidResume: ((Request) -> Void)?
609
+
610
+    /// Closure called on the `request(_:didResumeTask:)` event.
611
+    open var requestDidResumeTask: ((Request, URLSessionTask) -> Void)?
612
+
613
+    /// Closure called on the `requestDidSuspend(_:)` event.
614
+    open var requestDidSuspend: ((Request) -> Void)?
615
+
616
+    /// Closure called on the `request(_:didSuspendTask:)` event.
617
+    open var requestDidSuspendTask: ((Request, URLSessionTask) -> Void)?
618
+
619
+    /// Closure called on the `requestDidCancel(_:)` event.
620
+    open var requestDidCancel: ((Request) -> Void)?
621
+
622
+    /// Closure called on the `request(_:didCancelTask:)` event.
623
+    open var requestDidCancelTask: ((Request, URLSessionTask) -> Void)?
624
+
625
+    /// Closure called on the `request(_:didValidateRequest:response:data:withResult:)` event.
626
+    open var requestDidValidateRequestResponseDataWithResult: ((DataRequest, URLRequest?, HTTPURLResponse, Data?, Request.ValidationResult) -> Void)?
627
+
628
+    /// Closure called on the `request(_:didParseResponse:)` event.
629
+    open var requestDidParseResponse: ((DataRequest, DataResponse<Data?, AFError>) -> Void)?
630
+
631
+    /// Closure called on the `request(_:didCreateUploadable:)` event.
632
+    open var requestDidCreateUploadable: ((UploadRequest, UploadRequest.Uploadable) -> Void)?
633
+
634
+    /// Closure called on the `request(_:didFailToCreateUploadableWithError:)` event.
635
+    open var requestDidFailToCreateUploadableWithError: ((UploadRequest, AFError) -> Void)?
636
+
637
+    /// Closure called on the `request(_:didProvideInputStream:)` event.
638
+    open var requestDidProvideInputStream: ((UploadRequest, InputStream) -> Void)?
639
+
640
+    /// Closure called on the `request(_:didFinishDownloadingUsing:with:)` event.
641
+    open var requestDidFinishDownloadingUsingTaskWithResult: ((DownloadRequest, URLSessionTask, Result<URL, AFError>) -> Void)?
642
+
643
+    /// Closure called on the `request(_:didCreateDestinationURL:)` event.
644
+    open var requestDidCreateDestinationURL: ((DownloadRequest, URL) -> Void)?
645
+
646
+    /// Closure called on the `request(_:didValidateRequest:response:temporaryURL:destinationURL:withResult:)` event.
647
+    open var requestDidValidateRequestResponseFileURLWithResult: ((DownloadRequest, URLRequest?, HTTPURLResponse, URL?, Request.ValidationResult) -> Void)?
648
+
649
+    /// Closure called on the `request(_:didParseResponse:)` event.
650
+    open var requestDidParseDownloadResponse: ((DownloadRequest, DownloadResponse<URL?, AFError>) -> Void)?
651
+
652
+    public let queue: DispatchQueue
653
+
654
+    /// Creates an instance using the provided queue.
655
+    ///
656
+    /// - Parameter queue: `DispatchQueue` on which events will fired. `.main` by default.
657
+    public init(queue: DispatchQueue = .main) {
658
+        self.queue = queue
659
+    }
660
+
661
+    open func urlSession(_ session: URLSession, didBecomeInvalidWithError error: Error?) {
662
+        sessionDidBecomeInvalidWithError?(session, error)
663
+    }
664
+
665
+    open func urlSession(_ session: URLSession, task: URLSessionTask, didReceive challenge: URLAuthenticationChallenge) {
666
+        taskDidReceiveChallenge?(session, task, challenge)
667
+    }
668
+
669
+    open func urlSession(_ session: URLSession,
670
+                         task: URLSessionTask,
671
+                         didSendBodyData bytesSent: Int64,
672
+                         totalBytesSent: Int64,
673
+                         totalBytesExpectedToSend: Int64) {
674
+        taskDidSendBodyData?(session, task, bytesSent, totalBytesSent, totalBytesExpectedToSend)
675
+    }
676
+
677
+    open func urlSession(_ session: URLSession, taskNeedsNewBodyStream task: URLSessionTask) {
678
+        taskNeedNewBodyStream?(session, task)
679
+    }
680
+
681
+    open func urlSession(_ session: URLSession,
682
+                         task: URLSessionTask,
683
+                         willPerformHTTPRedirection response: HTTPURLResponse,
684
+                         newRequest request: URLRequest) {
685
+        taskWillPerformHTTPRedirection?(session, task, response, request)
686
+    }
687
+
688
+    open func urlSession(_ session: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics) {
689
+        taskDidFinishCollectingMetrics?(session, task, metrics)
690
+    }
691
+
692
+    open func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
693
+        taskDidComplete?(session, task, error)
694
+    }
695
+
696
+    open func urlSession(_ session: URLSession, taskIsWaitingForConnectivity task: URLSessionTask) {
697
+        taskIsWaitingForConnectivity?(session, task)
698
+    }
699
+
700
+    open func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
701
+        dataTaskDidReceiveData?(session, dataTask, data)
702
+    }
703
+
704
+    open func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, willCacheResponse proposedResponse: CachedURLResponse) {
705
+        dataTaskWillCacheResponse?(session, dataTask, proposedResponse)
706
+    }
707
+
708
+    open func urlSession(_ session: URLSession,
709
+                         downloadTask: URLSessionDownloadTask,
710
+                         didResumeAtOffset fileOffset: Int64,
711
+                         expectedTotalBytes: Int64) {
712
+        downloadTaskDidResumeAtOffset?(session, downloadTask, fileOffset, expectedTotalBytes)
713
+    }
714
+
715
+    open func urlSession(_ session: URLSession,
716
+                         downloadTask: URLSessionDownloadTask,
717
+                         didWriteData bytesWritten: Int64,
718
+                         totalBytesWritten: Int64,
719
+                         totalBytesExpectedToWrite: Int64) {
720
+        downloadTaskDidWriteData?(session, downloadTask, bytesWritten, totalBytesWritten, totalBytesExpectedToWrite)
721
+    }
722
+
723
+    open func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
724
+        downloadTaskDidFinishDownloadingToURL?(session, downloadTask, location)
725
+    }
726
+
727
+    // MARK: Request Events
728
+
729
+    open func request(_ request: Request, didCreateInitialURLRequest urlRequest: URLRequest) {
730
+        requestDidCreateInitialURLRequest?(request, urlRequest)
731
+    }
732
+
733
+    open func request(_ request: Request, didFailToCreateURLRequestWithError error: AFError) {
734
+        requestDidFailToCreateURLRequestWithError?(request, error)
735
+    }
736
+
737
+    open func request(_ request: Request, didAdaptInitialRequest initialRequest: URLRequest, to adaptedRequest: URLRequest) {
738
+        requestDidAdaptInitialRequestToAdaptedRequest?(request, initialRequest, adaptedRequest)
739
+    }
740
+
741
+    open func request(_ request: Request, didFailToAdaptURLRequest initialRequest: URLRequest, withError error: AFError) {
742
+        requestDidFailToAdaptURLRequestWithError?(request, initialRequest, error)
743
+    }
744
+
745
+    open func request(_ request: Request, didCreateURLRequest urlRequest: URLRequest) {
746
+        requestDidCreateURLRequest?(request, urlRequest)
747
+    }
748
+
749
+    open func request(_ request: Request, didCreateTask task: URLSessionTask) {
750
+        requestDidCreateTask?(request, task)
751
+    }
752
+
753
+    open func request(_ request: Request, didGatherMetrics metrics: URLSessionTaskMetrics) {
754
+        requestDidGatherMetrics?(request, metrics)
755
+    }
756
+
757
+    open func request(_ request: Request, didFailTask task: URLSessionTask, earlyWithError error: AFError) {
758
+        requestDidFailTaskEarlyWithError?(request, task, error)
759
+    }
760
+
761
+    open func request(_ request: Request, didCompleteTask task: URLSessionTask, with error: AFError?) {
762
+        requestDidCompleteTaskWithError?(request, task, error)
763
+    }
764
+
765
+    open func requestIsRetrying(_ request: Request) {
766
+        requestIsRetrying?(request)
767
+    }
768
+
769
+    open func requestDidFinish(_ request: Request) {
770
+        requestDidFinish?(request)
771
+    }
772
+
773
+    open func requestDidResume(_ request: Request) {
774
+        requestDidResume?(request)
775
+    }
776
+
777
+    public func request(_ request: Request, didResumeTask task: URLSessionTask) {
778
+        requestDidResumeTask?(request, task)
779
+    }
780
+
781
+    open func requestDidSuspend(_ request: Request) {
782
+        requestDidSuspend?(request)
783
+    }
784
+
785
+    public func request(_ request: Request, didSuspendTask task: URLSessionTask) {
786
+        requestDidSuspendTask?(request, task)
787
+    }
788
+
789
+    open func requestDidCancel(_ request: Request) {
790
+        requestDidCancel?(request)
791
+    }
792
+
793
+    public func request(_ request: Request, didCancelTask task: URLSessionTask) {
794
+        requestDidCancelTask?(request, task)
795
+    }
796
+
797
+    open func request(_ request: DataRequest,
798
+                      didValidateRequest urlRequest: URLRequest?,
799
+                      response: HTTPURLResponse,
800
+                      data: Data?,
801
+                      withResult result: Request.ValidationResult) {
802
+        requestDidValidateRequestResponseDataWithResult?(request, urlRequest, response, data, result)
803
+    }
804
+
805
+    open func request(_ request: DataRequest, didParseResponse response: DataResponse<Data?, AFError>) {
806
+        requestDidParseResponse?(request, response)
807
+    }
808
+
809
+    open func request(_ request: UploadRequest, didCreateUploadable uploadable: UploadRequest.Uploadable) {
810
+        requestDidCreateUploadable?(request, uploadable)
811
+    }
812
+
813
+    open func request(_ request: UploadRequest, didFailToCreateUploadableWithError error: AFError) {
814
+        requestDidFailToCreateUploadableWithError?(request, error)
815
+    }
816
+
817
+    open func request(_ request: UploadRequest, didProvideInputStream stream: InputStream) {
818
+        requestDidProvideInputStream?(request, stream)
819
+    }
820
+
821
+    open func request(_ request: DownloadRequest, didFinishDownloadingUsing task: URLSessionTask, with result: Result<URL, AFError>) {
822
+        requestDidFinishDownloadingUsingTaskWithResult?(request, task, result)
823
+    }
824
+
825
+    open func request(_ request: DownloadRequest, didCreateDestinationURL url: URL) {
826
+        requestDidCreateDestinationURL?(request, url)
827
+    }
828
+
829
+    open func request(_ request: DownloadRequest,
830
+                      didValidateRequest urlRequest: URLRequest?,
831
+                      response: HTTPURLResponse,
832
+                      fileURL: URL?,
833
+                      withResult result: Request.ValidationResult) {
834
+        requestDidValidateRequestResponseFileURLWithResult?(request,
835
+                                                            urlRequest,
836
+                                                            response,
837
+                                                            fileURL,
838
+                                                            result)
839
+    }
840
+
841
+    open func request(_ request: DownloadRequest, didParseResponse response: DownloadResponse<URL?, AFError>) {
842
+        requestDidParseDownloadResponse?(request, response)
843
+    }
844
+}

+ 445
- 0
trolley/Pods/Alamofire/Source/HTTPHeaders.swift 查看文件

@@ -0,0 +1,445 @@
1
+//
2
+//  HTTPHeaders.swift
3
+//
4
+//  Copyright (c) 2014-2018 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
+/// An order-preserving and case-insensitive representation of HTTP headers.
28
+public struct HTTPHeaders {
29
+    private var headers: [HTTPHeader] = []
30
+
31
+    /// Creates an empty instance.
32
+    public init() {}
33
+
34
+    /// Creates an instance from an array of `HTTPHeader`s. Duplicate case-insensitive names are collapsed into the last
35
+    /// name and value encountered.
36
+    public init(_ headers: [HTTPHeader]) {
37
+        self.init()
38
+
39
+        headers.forEach { update($0) }
40
+    }
41
+
42
+    /// Creates an instance from a `[String: String]`. Duplicate case-insensitive names are collapsed into the last name
43
+    /// and value encountered.
44
+    public init(_ dictionary: [String: String]) {
45
+        self.init()
46
+
47
+        dictionary.forEach { update(HTTPHeader(name: $0.key, value: $0.value)) }
48
+    }
49
+
50
+    /// Case-insensitively updates or appends an `HTTPHeader` into the instance using the provided `name` and `value`.
51
+    ///
52
+    /// - Parameters:
53
+    ///   - name:  The `HTTPHeader` name.
54
+    ///   - value: The `HTTPHeader value.
55
+    public mutating func add(name: String, value: String) {
56
+        update(HTTPHeader(name: name, value: value))
57
+    }
58
+
59
+    /// Case-insensitively updates or appends the provided `HTTPHeader` into the instance.
60
+    ///
61
+    /// - Parameter header: The `HTTPHeader` to update or append.
62
+    public mutating func add(_ header: HTTPHeader) {
63
+        update(header)
64
+    }
65
+
66
+    /// Case-insensitively updates or appends an `HTTPHeader` into the instance using the provided `name` and `value`.
67
+    ///
68
+    /// - Parameters:
69
+    ///   - name:  The `HTTPHeader` name.
70
+    ///   - value: The `HTTPHeader value.
71
+    public mutating func update(name: String, value: String) {
72
+        update(HTTPHeader(name: name, value: value))
73
+    }
74
+
75
+    /// Case-insensitively updates or appends the provided `HTTPHeader` into the instance.
76
+    ///
77
+    /// - Parameter header: The `HTTPHeader` to update or append.
78
+    public mutating func update(_ header: HTTPHeader) {
79
+        guard let index = headers.index(of: header.name) else {
80
+            headers.append(header)
81
+            return
82
+        }
83
+
84
+        headers.replaceSubrange(index...index, with: [header])
85
+    }
86
+
87
+    /// Case-insensitively removes an `HTTPHeader`, if it exists, from the instance.
88
+    ///
89
+    /// - Parameter name: The name of the `HTTPHeader` to remove.
90
+    public mutating func remove(name: String) {
91
+        guard let index = headers.index(of: name) else { return }
92
+
93
+        headers.remove(at: index)
94
+    }
95
+
96
+    /// Sort the current instance by header name.
97
+    public mutating func sort() {
98
+        headers.sort { $0.name < $1.name }
99
+    }
100
+
101
+    /// Returns an instance sorted by header name.
102
+    ///
103
+    /// - Returns: A copy of the current instance sorted by name.
104
+    public func sorted() -> HTTPHeaders {
105
+        return HTTPHeaders(headers.sorted { $0.name < $1.name })
106
+    }
107
+
108
+    /// Case-insensitively find a header's value by name.
109
+    ///
110
+    /// - Parameter name: The name of the header to search for, case-insensitively.
111
+    ///
112
+    /// - Returns:        The value of header, if it exists.
113
+    public func value(for name: String) -> String? {
114
+        guard let index = headers.index(of: name) else { return nil }
115
+
116
+        return headers[index].value
117
+    }
118
+
119
+    /// Case-insensitively access the header with the given name.
120
+    ///
121
+    /// - Parameter name: The name of the header.
122
+    public subscript(_ name: String) -> String? {
123
+        get { return value(for: name) }
124
+        set {
125
+            if let value = newValue {
126
+                update(name: name, value: value)
127
+            } else {
128
+                remove(name: name)
129
+            }
130
+        }
131
+    }
132
+
133
+    /// The dictionary representation of all headers.
134
+    ///
135
+    /// This representation does not preserve the current order of the instance.
136
+    public var dictionary: [String: String] {
137
+        let namesAndValues = headers.map { ($0.name, $0.value) }
138
+
139
+        return Dictionary(namesAndValues, uniquingKeysWith: { _, last in last })
140
+    }
141
+}
142
+
143
+extension HTTPHeaders: ExpressibleByDictionaryLiteral {
144
+    public init(dictionaryLiteral elements: (String, String)...) {
145
+        self.init()
146
+
147
+        elements.forEach { update(name: $0.0, value: $0.1) }
148
+    }
149
+}
150
+
151
+extension HTTPHeaders: ExpressibleByArrayLiteral {
152
+    public init(arrayLiteral elements: HTTPHeader...) {
153
+        self.init(elements)
154
+    }
155
+}
156
+
157
+extension HTTPHeaders: Sequence {
158
+    public func makeIterator() -> IndexingIterator<[HTTPHeader]> {
159
+        return headers.makeIterator()
160
+    }
161
+}
162
+
163
+extension HTTPHeaders: Collection {
164
+    public var startIndex: Int {
165
+        return headers.startIndex
166
+    }
167
+
168
+    public var endIndex: Int {
169
+        return headers.endIndex
170
+    }
171
+
172
+    public subscript(position: Int) -> HTTPHeader {
173
+        return headers[position]
174
+    }
175
+
176
+    public func index(after i: Int) -> Int {
177
+        return headers.index(after: i)
178
+    }
179
+}
180
+
181
+extension HTTPHeaders: CustomStringConvertible {
182
+    public var description: String {
183
+        return headers.map { $0.description }
184
+            .joined(separator: "\n")
185
+    }
186
+}
187
+
188
+// MARK: - HTTPHeader
189
+
190
+/// A representation of a single HTTP header's name / value pair.
191
+public struct HTTPHeader: Hashable {
192
+    /// Name of the header.
193
+    public let name: String
194
+
195
+    /// Value of the header.
196
+    public let value: String
197
+
198
+    /// Creates an instance from the given `name` and `value`.
199
+    ///
200
+    /// - Parameters:
201
+    ///   - name:  The name of the header.
202
+    ///   - value: The value of the header.
203
+    public init(name: String, value: String) {
204
+        self.name = name
205
+        self.value = value
206
+    }
207
+}
208
+
209
+extension HTTPHeader: CustomStringConvertible {
210
+    public var description: String {
211
+        return "\(name): \(value)"
212
+    }
213
+}
214
+
215
+extension HTTPHeader {
216
+    /// Returns an `Accept` header.
217
+    ///
218
+    /// - Parameter value: The `Accept` value.
219
+    /// - Returns:         The header.
220
+    public static func accept(_ value: String) -> HTTPHeader {
221
+        return HTTPHeader(name: "Accept", value: value)
222
+    }
223
+
224
+    /// Returns an `Accept-Charset` header.
225
+    ///
226
+    /// - Parameter value: The `Accept-Charset` value.
227
+    /// - Returns:         The header.
228
+    public static func acceptCharset(_ value: String) -> HTTPHeader {
229
+        return HTTPHeader(name: "Accept-Charset", value: value)
230
+    }
231
+
232
+    /// Returns an `Accept-Language` header.
233
+    ///
234
+    /// Alamofire offers a default Accept-Language header that accumulates and encodes the system's preferred languages.
235
+    /// Use `HTTPHeader.defaultAcceptLanguage`.
236
+    ///
237
+    /// - Parameter value: The `Accept-Language` value.
238
+    ///
239
+    /// - Returns:         The header.
240
+    public static func acceptLanguage(_ value: String) -> HTTPHeader {
241
+        return HTTPHeader(name: "Accept-Language", value: value)
242
+    }
243
+
244
+    /// Returns an `Accept-Encoding` header.
245
+    ///
246
+    /// Alamofire offers a default accept encoding value that provides the most common values. Use
247
+    /// `HTTPHeader.defaultAcceptEncoding`.
248
+    ///
249
+    /// - Parameter value: The `Accept-Encoding` value.
250
+    ///
251
+    /// - Returns:         The header
252
+    public static func acceptEncoding(_ value: String) -> HTTPHeader {
253
+        return HTTPHeader(name: "Accept-Encoding", value: value)
254
+    }
255
+
256
+    /// Returns a `Basic` `Authorization` header using the `username` and `password` provided.
257
+    ///
258
+    /// - Parameters:
259
+    ///   - username: The username of the header.
260
+    ///   - password: The password of the header.
261
+    ///
262
+    /// - Returns:    The header.
263
+    public static func authorization(username: String, password: String) -> HTTPHeader {
264
+        let credential = Data("\(username):\(password)".utf8).base64EncodedString()
265
+
266
+        return authorization("Basic \(credential)")
267
+    }
268
+
269
+    /// Returns a `Bearer` `Authorization` header using the `bearerToken` provided
270
+    ///
271
+    /// - Parameter bearerToken: The bearer token.
272
+    ///
273
+    /// - Returns:               The header.
274
+    public static func authorization(bearerToken: String) -> HTTPHeader {
275
+        return authorization("Bearer \(bearerToken)")
276
+    }
277
+
278
+    /// Returns an `Authorization` header.
279
+    ///
280
+    /// Alamofire provides built-in methods to produce `Authorization` headers. For a Basic `Authorization` header use
281
+    /// `HTTPHeader.authorization(username:password:)`. For a Bearer `Authorization` header, use
282
+    /// `HTTPHeader.authorization(bearerToken:)`.
283
+    ///
284
+    /// - Parameter value: The `Authorization` value.
285
+    ///
286
+    /// - Returns:         The header.
287
+    public static func authorization(_ value: String) -> HTTPHeader {
288
+        return HTTPHeader(name: "Authorization", value: value)
289
+    }
290
+
291
+    /// Returns a `Content-Disposition` header.
292
+    ///
293
+    /// - Parameter value: The `Content-Disposition` value.
294
+    ///
295
+    /// - Returns:         The header.
296
+    public static func contentDisposition(_ value: String) -> HTTPHeader {
297
+        return HTTPHeader(name: "Content-Disposition", value: value)
298
+    }
299
+
300
+    /// Returns a `Content-Type` header.
301
+    ///
302
+    /// All Alamofire `ParameterEncoding`s and `ParameterEncoder`s set the `Content-Type` of the request, so it may not be necessary to manually
303
+    /// set this value.
304
+    ///
305
+    /// - Parameter value: The `Content-Type` value.
306
+    ///
307
+    /// - Returns:         The header.
308
+    public static func contentType(_ value: String) -> HTTPHeader {
309
+        return HTTPHeader(name: "Content-Type", value: value)
310
+    }
311
+
312
+    /// Returns a `User-Agent` header.
313
+    ///
314
+    /// - Parameter value: The `User-Agent` value.
315
+    ///
316
+    /// - Returns:         The header.
317
+    public static func userAgent(_ value: String) -> HTTPHeader {
318
+        return HTTPHeader(name: "User-Agent", value: value)
319
+    }
320
+}
321
+
322
+extension Array where Element == HTTPHeader {
323
+    /// Case-insensitively finds the index of an `HTTPHeader` with the provided name, if it exists.
324
+    func index(of name: String) -> Int? {
325
+        let lowercasedName = name.lowercased()
326
+        return firstIndex { $0.name.lowercased() == lowercasedName }
327
+    }
328
+}
329
+
330
+// MARK: - Defaults
331
+
332
+public extension HTTPHeaders {
333
+    /// The default set of `HTTPHeaders` used by Alamofire. Includes `Accept-Encoding`, `Accept-Language`, and
334
+    /// `User-Agent`.
335
+    static let `default`: HTTPHeaders = [.defaultAcceptEncoding,
336
+                                         .defaultAcceptLanguage,
337
+                                         .defaultUserAgent]
338
+}
339
+
340
+extension HTTPHeader {
341
+    /// Returns Alamofire's default `Accept-Encoding` header, appropriate for the encodings supported by particular OS
342
+    /// versions.
343
+    ///
344
+    /// See the [Accept-Encoding HTTP header documentation](https://tools.ietf.org/html/rfc7230#section-4.2.3) .
345
+    public static let defaultAcceptEncoding: HTTPHeader = {
346
+        let encodings: [String]
347
+        if #available(iOS 11.0, macOS 10.13, tvOS 11.0, watchOS 4.0, *) {
348
+            encodings = ["br", "gzip", "deflate"]
349
+        } else {
350
+            encodings = ["gzip", "deflate"]
351
+        }
352
+
353
+        return .acceptEncoding(encodings.qualityEncoded())
354
+    }()
355
+
356
+    /// Returns Alamofire's default `Accept-Language` header, generated by querying `Locale` for the user's
357
+    /// `preferredLanguages`.
358
+    ///
359
+    /// See the [Accept-Language HTTP header documentation](https://tools.ietf.org/html/rfc7231#section-5.3.5).
360
+    public static let defaultAcceptLanguage: HTTPHeader = {
361
+        .acceptLanguage(Locale.preferredLanguages.prefix(6).qualityEncoded())
362
+    }()
363
+
364
+    /// Returns Alamofire's default `User-Agent` header.
365
+    ///
366
+    /// See the [User-Agent header documentation](https://tools.ietf.org/html/rfc7231#section-5.5.3).
367
+    ///
368
+    /// Example: `iOS Example/1.0 (org.alamofire.iOS-Example; build:1; iOS 13.0.0) Alamofire/5.0.0`
369
+    public static let defaultUserAgent: HTTPHeader = {
370
+        let userAgent: String = {
371
+            if let info = Bundle.main.infoDictionary {
372
+                let executable = info[kCFBundleExecutableKey as String] as? String ?? "Unknown"
373
+                let bundle = info[kCFBundleIdentifierKey as String] as? String ?? "Unknown"
374
+                let appVersion = info["CFBundleShortVersionString"] as? String ?? "Unknown"
375
+                let appBuild = info[kCFBundleVersionKey as String] as? String ?? "Unknown"
376
+
377
+                let osNameVersion: String = {
378
+                    let version = ProcessInfo.processInfo.operatingSystemVersion
379
+                    let versionString = "\(version.majorVersion).\(version.minorVersion).\(version.patchVersion)"
380
+                    // swiftformat:disable indent
381
+                    let osName: String = {
382
+                    #if os(iOS)
383
+                        return "iOS"
384
+                    #elseif os(watchOS)
385
+                        return "watchOS"
386
+                    #elseif os(tvOS)
387
+                        return "tvOS"
388
+                    #elseif os(macOS)
389
+                        return "macOS"
390
+                    #elseif os(Linux)
391
+                        return "Linux"
392
+                    #else
393
+                        return "Unknown"
394
+                    #endif
395
+                    }()
396
+                    // swiftformat:enable indent
397
+
398
+                    return "\(osName) \(versionString)"
399
+                }()
400
+
401
+                let alamofireVersion = "Alamofire/\(AF.version)"
402
+
403
+                return "\(executable)/\(appVersion) (\(bundle); build:\(appBuild); \(osNameVersion)) \(alamofireVersion)"
404
+            }
405
+
406
+            return "Alamofire"
407
+        }()
408
+
409
+        return .userAgent(userAgent)
410
+    }()
411
+}
412
+
413
+extension Collection where Element == String {
414
+    func qualityEncoded() -> String {
415
+        return enumerated().map { index, encoding in
416
+            let quality = 1.0 - (Double(index) * 0.1)
417
+            return "\(encoding);q=\(quality)"
418
+        }.joined(separator: ", ")
419
+    }
420
+}
421
+
422
+// MARK: - System Type Extensions
423
+
424
+extension URLRequest {
425
+    /// Returns `allHTTPHeaderFields` as `HTTPHeaders`.
426
+    public var headers: HTTPHeaders {
427
+        get { return allHTTPHeaderFields.map(HTTPHeaders.init) ?? HTTPHeaders() }
428
+        set { allHTTPHeaderFields = newValue.dictionary }
429
+    }
430
+}
431
+
432
+extension HTTPURLResponse {
433
+    /// Returns `allHeaderFields` as `HTTPHeaders`.
434
+    public var headers: HTTPHeaders {
435
+        return (allHeaderFields as? [String: String]).map(HTTPHeaders.init) ?? HTTPHeaders()
436
+    }
437
+}
438
+
439
+public extension URLSessionConfiguration {
440
+    /// Returns `httpAdditionalHeaders` as `HTTPHeaders`.
441
+    var headers: HTTPHeaders {
442
+        get { return (httpAdditionalHeaders as? [String: String]).map(HTTPHeaders.init) ?? HTTPHeaders() }
443
+        set { httpAdditionalHeaders = newValue.dictionary }
444
+    }
445
+}

+ 54
- 0
trolley/Pods/Alamofire/Source/HTTPMethod.swift 查看文件

@@ -0,0 +1,54 @@
1
+//
2
+//  HTTPMethod.swift
3
+//
4
+//  Copyright (c) 2014-2018 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
+/// Type representing HTTP methods. Raw `String` value is stored and compared case-sensitively, so
26
+/// `HTTPMethod.get != HTTPMethod(rawValue: "get")`.
27
+///
28
+/// See https://tools.ietf.org/html/rfc7231#section-4.3
29
+public struct HTTPMethod: RawRepresentable, Equatable, Hashable {
30
+    /// `CONNECT` method.
31
+    public static let connect = HTTPMethod(rawValue: "CONNECT")
32
+    /// `DELETE` method.
33
+    public static let delete = HTTPMethod(rawValue: "DELETE")
34
+    /// `GET` method.
35
+    public static let get = HTTPMethod(rawValue: "GET")
36
+    /// `HEAD` method.
37
+    public static let head = HTTPMethod(rawValue: "HEAD")
38
+    /// `OPTIONS` method.
39
+    public static let options = HTTPMethod(rawValue: "OPTIONS")
40
+    /// `PATCH` method.
41
+    public static let patch = HTTPMethod(rawValue: "PATCH")
42
+    /// `POST` method.
43
+    public static let post = HTTPMethod(rawValue: "POST")
44
+    /// `PUT` method.
45
+    public static let put = HTTPMethod(rawValue: "PUT")
46
+    /// `TRACE` method.
47
+    public static let trace = HTTPMethod(rawValue: "TRACE")
48
+
49
+    public let rawValue: String
50
+
51
+    public init(rawValue: String) {
52
+        self.rawValue = rawValue
53
+    }
54
+}

+ 544
- 0
trolley/Pods/Alamofire/Source/MultipartFormData.swift 查看文件

@@ -0,0 +1,544 @@
1
+//
2
+//  MultipartFormData.swift
3
+//
4
+//  Copyright (c) 2014-2018 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(iOS) || os(watchOS) || os(tvOS)
28
+import MobileCoreServices
29
+#elseif os(macOS)
30
+import CoreServices
31
+#endif
32
+
33
+/// Constructs `multipart/form-data` for uploads within an HTTP or HTTPS body. There are currently two ways to encode
34
+/// multipart form data. The first way is to encode the data directly in memory. This is very efficient, but can lead
35
+/// to memory issues if the dataset is too large. The second way is designed for larger datasets and will write all the
36
+/// data to a single file on disk with all the proper boundary segmentation. The second approach MUST be used for
37
+/// larger datasets such as video content, otherwise your app may run out of memory when trying to encode the dataset.
38
+///
39
+/// For more information on `multipart/form-data` in general, please refer to the RFC-2388 and RFC-2045 specs as well
40
+/// and the w3 form documentation.
41
+///
42
+/// - https://www.ietf.org/rfc/rfc2388.txt
43
+/// - https://www.ietf.org/rfc/rfc2045.txt
44
+/// - https://www.w3.org/TR/html401/interact/forms.html#h-17.13
45
+open class MultipartFormData {
46
+    // MARK: - Helper Types
47
+
48
+    struct EncodingCharacters {
49
+        static let crlf = "\r\n"
50
+    }
51
+
52
+    struct BoundaryGenerator {
53
+        enum BoundaryType {
54
+            case initial, encapsulated, final
55
+        }
56
+
57
+        static func randomBoundary() -> String {
58
+            return String(format: "alamofire.boundary.%08x%08x", arc4random(), arc4random())
59
+        }
60
+
61
+        static func boundaryData(forBoundaryType boundaryType: BoundaryType, boundary: String) -> Data {
62
+            let boundaryText: String
63
+
64
+            switch boundaryType {
65
+            case .initial:
66
+                boundaryText = "--\(boundary)\(EncodingCharacters.crlf)"
67
+            case .encapsulated:
68
+                boundaryText = "\(EncodingCharacters.crlf)--\(boundary)\(EncodingCharacters.crlf)"
69
+            case .final:
70
+                boundaryText = "\(EncodingCharacters.crlf)--\(boundary)--\(EncodingCharacters.crlf)"
71
+            }
72
+
73
+            return Data(boundaryText.utf8)
74
+        }
75
+    }
76
+
77
+    class BodyPart {
78
+        let headers: HTTPHeaders
79
+        let bodyStream: InputStream
80
+        let bodyContentLength: UInt64
81
+        var hasInitialBoundary = false
82
+        var hasFinalBoundary = false
83
+
84
+        init(headers: HTTPHeaders, bodyStream: InputStream, bodyContentLength: UInt64) {
85
+            self.headers = headers
86
+            self.bodyStream = bodyStream
87
+            self.bodyContentLength = bodyContentLength
88
+        }
89
+    }
90
+
91
+    // MARK: - Properties
92
+
93
+    /// Default memory threshold used when encoding `MultipartFormData`, in bytes.
94
+    public static let encodingMemoryThreshold: UInt64 = 10_000_000
95
+
96
+    /// The `Content-Type` header value containing the boundary used to generate the `multipart/form-data`.
97
+    open lazy var contentType: String = "multipart/form-data; boundary=\(self.boundary)"
98
+
99
+    /// The content length of all body parts used to generate the `multipart/form-data` not including the boundaries.
100
+    public var contentLength: UInt64 { return bodyParts.reduce(0) { $0 + $1.bodyContentLength } }
101
+
102
+    /// The boundary used to separate the body parts in the encoded form data.
103
+    public let boundary: String
104
+
105
+    let fileManager: FileManager
106
+
107
+    private var bodyParts: [BodyPart]
108
+    private var bodyPartError: AFError?
109
+    private let streamBufferSize: Int
110
+
111
+    // MARK: - Lifecycle
112
+
113
+    /// Creates an instance.
114
+    ///
115
+    /// - Parameters:
116
+    ///   - fileManager: `FileManager` to use for file operations, if needed.
117
+    ///   - boundary: Boundary `String` used to separate body parts.
118
+    public init(fileManager: FileManager = .default, boundary: String? = nil) {
119
+        self.fileManager = fileManager
120
+        self.boundary = boundary ?? BoundaryGenerator.randomBoundary()
121
+        bodyParts = []
122
+
123
+        //
124
+        // The optimal read/write buffer size in bytes for input and output streams is 1024 (1KB). For more
125
+        // information, please refer to the following article:
126
+        //   - https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Streams/Articles/ReadingInputStreams.html
127
+        //
128
+        streamBufferSize = 1024
129
+    }
130
+
131
+    // MARK: - Body Parts
132
+
133
+    /// Creates a body part from the data and appends it to the instance.
134
+    ///
135
+    /// The body part data will be encoded using the following format:
136
+    ///
137
+    /// - `Content-Disposition: form-data; name=#{name}; filename=#{filename}` (HTTP Header)
138
+    /// - `Content-Type: #{mimeType}` (HTTP Header)
139
+    /// - Encoded file data
140
+    /// - Multipart form boundary
141
+    ///
142
+    /// - Parameters:
143
+    ///   - data:     `Data` to encoding into the instance.
144
+    ///   - name:     Name to associate with the `Data` in the `Content-Disposition` HTTP header.
145
+    ///   - fileName: Filename to associate with the `Data` in the `Content-Disposition` HTTP header.
146
+    ///   - mimeType: MIME type to associate with the data in the `Content-Type` HTTP header.
147
+    public func append(_ data: Data, withName name: String, fileName: String? = nil, mimeType: String? = nil) {
148
+        let headers = contentHeaders(withName: name, fileName: fileName, mimeType: mimeType)
149
+        let stream = InputStream(data: data)
150
+        let length = UInt64(data.count)
151
+
152
+        append(stream, withLength: length, headers: headers)
153
+    }
154
+
155
+    /// Creates a body part from the file and appends it to the instance.
156
+    ///
157
+    /// The body part data will be encoded using the following format:
158
+    ///
159
+    /// - `Content-Disposition: form-data; name=#{name}; filename=#{generated filename}` (HTTP Header)
160
+    /// - `Content-Type: #{generated mimeType}` (HTTP Header)
161
+    /// - Encoded file data
162
+    /// - Multipart form boundary
163
+    ///
164
+    /// The filename in the `Content-Disposition` HTTP header is generated from the last path component of the
165
+    /// `fileURL`. The `Content-Type` HTTP header MIME type is generated by mapping the `fileURL` extension to the
166
+    /// system associated MIME type.
167
+    ///
168
+    /// - Parameters:
169
+    ///   - fileURL: `URL` of the file whose content will be encoded into the instance.
170
+    ///   - name:    Name to associate with the file content in the `Content-Disposition` HTTP header.
171
+    public func append(_ fileURL: URL, withName name: String) {
172
+        let fileName = fileURL.lastPathComponent
173
+        let pathExtension = fileURL.pathExtension
174
+
175
+        if !fileName.isEmpty && !pathExtension.isEmpty {
176
+            let mime = mimeType(forPathExtension: pathExtension)
177
+            append(fileURL, withName: name, fileName: fileName, mimeType: mime)
178
+        } else {
179
+            setBodyPartError(withReason: .bodyPartFilenameInvalid(in: fileURL))
180
+        }
181
+    }
182
+
183
+    /// Creates a body part from the file and appends it to the instance.
184
+    ///
185
+    /// The body part data will be encoded using the following format:
186
+    ///
187
+    /// - Content-Disposition: form-data; name=#{name}; filename=#{filename} (HTTP Header)
188
+    /// - Content-Type: #{mimeType} (HTTP Header)
189
+    /// - Encoded file data
190
+    /// - Multipart form boundary
191
+    ///
192
+    /// - Parameters:
193
+    ///   - fileURL:  `URL` of the file whose content will be encoded into the instance.
194
+    ///   - name:     Name to associate with the file content in the `Content-Disposition` HTTP header.
195
+    ///   - fileName: Filename to associate with the file content in the `Content-Disposition` HTTP header.
196
+    ///   - mimeType: MIME type to associate with the file content in the `Content-Type` HTTP header.
197
+    public func append(_ fileURL: URL, withName name: String, fileName: String, mimeType: String) {
198
+        let headers = contentHeaders(withName: name, fileName: fileName, mimeType: mimeType)
199
+
200
+        //============================================================
201
+        //                 Check 1 - is file URL?
202
+        //============================================================
203
+
204
+        guard fileURL.isFileURL else {
205
+            setBodyPartError(withReason: .bodyPartURLInvalid(url: fileURL))
206
+            return
207
+        }
208
+
209
+        //============================================================
210
+        //              Check 2 - is file URL reachable?
211
+        //============================================================
212
+
213
+        do {
214
+            let isReachable = try fileURL.checkPromisedItemIsReachable()
215
+            guard isReachable else {
216
+                setBodyPartError(withReason: .bodyPartFileNotReachable(at: fileURL))
217
+                return
218
+            }
219
+        } catch {
220
+            setBodyPartError(withReason: .bodyPartFileNotReachableWithError(atURL: fileURL, error: error))
221
+            return
222
+        }
223
+
224
+        //============================================================
225
+        //            Check 3 - is file URL a directory?
226
+        //============================================================
227
+
228
+        var isDirectory: ObjCBool = false
229
+        let path = fileURL.path
230
+
231
+        guard fileManager.fileExists(atPath: path, isDirectory: &isDirectory) && !isDirectory.boolValue else {
232
+            setBodyPartError(withReason: .bodyPartFileIsDirectory(at: fileURL))
233
+            return
234
+        }
235
+
236
+        //============================================================
237
+        //          Check 4 - can the file size be extracted?
238
+        //============================================================
239
+
240
+        let bodyContentLength: UInt64
241
+
242
+        do {
243
+            guard let fileSize = try fileManager.attributesOfItem(atPath: path)[.size] as? NSNumber else {
244
+                setBodyPartError(withReason: .bodyPartFileSizeNotAvailable(at: fileURL))
245
+                return
246
+            }
247
+
248
+            bodyContentLength = fileSize.uint64Value
249
+        } catch {
250
+            setBodyPartError(withReason: .bodyPartFileSizeQueryFailedWithError(forURL: fileURL, error: error))
251
+            return
252
+        }
253
+
254
+        //============================================================
255
+        //       Check 5 - can a stream be created from file URL?
256
+        //============================================================
257
+
258
+        guard let stream = InputStream(url: fileURL) else {
259
+            setBodyPartError(withReason: .bodyPartInputStreamCreationFailed(for: fileURL))
260
+            return
261
+        }
262
+
263
+        append(stream, withLength: bodyContentLength, headers: headers)
264
+    }
265
+
266
+    /// Creates a body part from the stream and appends it to the instance.
267
+    ///
268
+    /// The body part data will be encoded using the following format:
269
+    ///
270
+    /// - `Content-Disposition: form-data; name=#{name}; filename=#{filename}` (HTTP Header)
271
+    /// - `Content-Type: #{mimeType}` (HTTP Header)
272
+    /// - Encoded stream data
273
+    /// - Multipart form boundary
274
+    ///
275
+    /// - Parameters:
276
+    ///   - stream:   `InputStream` to encode into the instance.
277
+    ///   - length:   Length, in bytes, of the stream.
278
+    ///   - name:     Name to associate with the stream content in the `Content-Disposition` HTTP header.
279
+    ///   - fileName: Filename to associate with the stream content in the `Content-Disposition` HTTP header.
280
+    ///   - mimeType: MIME type to associate with the stream content in the `Content-Type` HTTP header.
281
+    public func append(_ stream: InputStream,
282
+                       withLength length: UInt64,
283
+                       name: String,
284
+                       fileName: String,
285
+                       mimeType: String) {
286
+        let headers = contentHeaders(withName: name, fileName: fileName, mimeType: mimeType)
287
+        append(stream, withLength: length, headers: headers)
288
+    }
289
+
290
+    /// Creates a body part with the stream, length, and headers and appends it to the instance.
291
+    ///
292
+    /// The body part data will be encoded using the following format:
293
+    ///
294
+    /// - HTTP headers
295
+    /// - Encoded stream data
296
+    /// - Multipart form boundary
297
+    ///
298
+    /// - Parameters:
299
+    ///   - stream:  `InputStream` to encode into the instance.
300
+    ///   - length:  Length, in bytes, of the stream.
301
+    ///   - headers: `HTTPHeaders` for the body part.
302
+    public func append(_ stream: InputStream, withLength length: UInt64, headers: HTTPHeaders) {
303
+        let bodyPart = BodyPart(headers: headers, bodyStream: stream, bodyContentLength: length)
304
+        bodyParts.append(bodyPart)
305
+    }
306
+
307
+    // MARK: - Data Encoding
308
+
309
+    /// Encodes all appended body parts into a single `Data` value.
310
+    ///
311
+    /// - Note: This method will load all the appended body parts into memory all at the same time. This method should
312
+    ///         only be used when the encoded data will have a small memory footprint. For large data cases, please use
313
+    ///         the `writeEncodedData(to:))` method.
314
+    ///
315
+    /// - Returns: The encoded `Data`, if encoding is successful.
316
+    /// - Throws:  An `AFError` if encoding encounters an error.
317
+    public func encode() throws -> Data {
318
+        if let bodyPartError = bodyPartError {
319
+            throw bodyPartError
320
+        }
321
+
322
+        var encoded = Data()
323
+
324
+        bodyParts.first?.hasInitialBoundary = true
325
+        bodyParts.last?.hasFinalBoundary = true
326
+
327
+        for bodyPart in bodyParts {
328
+            let encodedData = try encode(bodyPart)
329
+            encoded.append(encodedData)
330
+        }
331
+
332
+        return encoded
333
+    }
334
+
335
+    /// Writes all appended body parts to the given file `URL`.
336
+    ///
337
+    /// This process is facilitated by reading and writing with input and output streams, respectively. Thus,
338
+    /// this approach is very memory efficient and should be used for large body part data.
339
+    ///
340
+    /// - Parameter fileURL: File `URL` to which to write the form data.
341
+    /// - Throws:            An `AFError` if encoding encounters an error.
342
+    public func writeEncodedData(to fileURL: URL) throws {
343
+        if let bodyPartError = bodyPartError {
344
+            throw bodyPartError
345
+        }
346
+
347
+        if fileManager.fileExists(atPath: fileURL.path) {
348
+            throw AFError.multipartEncodingFailed(reason: .outputStreamFileAlreadyExists(at: fileURL))
349
+        } else if !fileURL.isFileURL {
350
+            throw AFError.multipartEncodingFailed(reason: .outputStreamURLInvalid(url: fileURL))
351
+        }
352
+
353
+        guard let outputStream = OutputStream(url: fileURL, append: false) else {
354
+            throw AFError.multipartEncodingFailed(reason: .outputStreamCreationFailed(for: fileURL))
355
+        }
356
+
357
+        outputStream.open()
358
+        defer { outputStream.close() }
359
+
360
+        bodyParts.first?.hasInitialBoundary = true
361
+        bodyParts.last?.hasFinalBoundary = true
362
+
363
+        for bodyPart in bodyParts {
364
+            try write(bodyPart, to: outputStream)
365
+        }
366
+    }
367
+
368
+    // MARK: - Private - Body Part Encoding
369
+
370
+    private func encode(_ bodyPart: BodyPart) throws -> Data {
371
+        var encoded = Data()
372
+
373
+        let initialData = bodyPart.hasInitialBoundary ? initialBoundaryData() : encapsulatedBoundaryData()
374
+        encoded.append(initialData)
375
+
376
+        let headerData = encodeHeaders(for: bodyPart)
377
+        encoded.append(headerData)
378
+
379
+        let bodyStreamData = try encodeBodyStream(for: bodyPart)
380
+        encoded.append(bodyStreamData)
381
+
382
+        if bodyPart.hasFinalBoundary {
383
+            encoded.append(finalBoundaryData())
384
+        }
385
+
386
+        return encoded
387
+    }
388
+
389
+    private func encodeHeaders(for bodyPart: BodyPart) -> Data {
390
+        let headerText = bodyPart.headers.map { "\($0.name): \($0.value)\(EncodingCharacters.crlf)" }
391
+            .joined()
392
+            + EncodingCharacters.crlf
393
+
394
+        return Data(headerText.utf8)
395
+    }
396
+
397
+    private func encodeBodyStream(for bodyPart: BodyPart) throws -> Data {
398
+        let inputStream = bodyPart.bodyStream
399
+        inputStream.open()
400
+        defer { inputStream.close() }
401
+
402
+        var encoded = Data()
403
+
404
+        while inputStream.hasBytesAvailable {
405
+            var buffer = [UInt8](repeating: 0, count: streamBufferSize)
406
+            let bytesRead = inputStream.read(&buffer, maxLength: streamBufferSize)
407
+
408
+            if let error = inputStream.streamError {
409
+                throw AFError.multipartEncodingFailed(reason: .inputStreamReadFailed(error: error))
410
+            }
411
+
412
+            if bytesRead > 0 {
413
+                encoded.append(buffer, count: bytesRead)
414
+            } else {
415
+                break
416
+            }
417
+        }
418
+
419
+        return encoded
420
+    }
421
+
422
+    // MARK: - Private - Writing Body Part to Output Stream
423
+
424
+    private func write(_ bodyPart: BodyPart, to outputStream: OutputStream) throws {
425
+        try writeInitialBoundaryData(for: bodyPart, to: outputStream)
426
+        try writeHeaderData(for: bodyPart, to: outputStream)
427
+        try writeBodyStream(for: bodyPart, to: outputStream)
428
+        try writeFinalBoundaryData(for: bodyPart, to: outputStream)
429
+    }
430
+
431
+    private func writeInitialBoundaryData(for bodyPart: BodyPart, to outputStream: OutputStream) throws {
432
+        let initialData = bodyPart.hasInitialBoundary ? initialBoundaryData() : encapsulatedBoundaryData()
433
+        return try write(initialData, to: outputStream)
434
+    }
435
+
436
+    private func writeHeaderData(for bodyPart: BodyPart, to outputStream: OutputStream) throws {
437
+        let headerData = encodeHeaders(for: bodyPart)
438
+        return try write(headerData, to: outputStream)
439
+    }
440
+
441
+    private func writeBodyStream(for bodyPart: BodyPart, to outputStream: OutputStream) throws {
442
+        let inputStream = bodyPart.bodyStream
443
+
444
+        inputStream.open()
445
+        defer { inputStream.close() }
446
+
447
+        while inputStream.hasBytesAvailable {
448
+            var buffer = [UInt8](repeating: 0, count: streamBufferSize)
449
+            let bytesRead = inputStream.read(&buffer, maxLength: streamBufferSize)
450
+
451
+            if let streamError = inputStream.streamError {
452
+                throw AFError.multipartEncodingFailed(reason: .inputStreamReadFailed(error: streamError))
453
+            }
454
+
455
+            if bytesRead > 0 {
456
+                if buffer.count != bytesRead {
457
+                    buffer = Array(buffer[0..<bytesRead])
458
+                }
459
+
460
+                try write(&buffer, to: outputStream)
461
+            } else {
462
+                break
463
+            }
464
+        }
465
+    }
466
+
467
+    private func writeFinalBoundaryData(for bodyPart: BodyPart, to outputStream: OutputStream) throws {
468
+        if bodyPart.hasFinalBoundary {
469
+            return try write(finalBoundaryData(), to: outputStream)
470
+        }
471
+    }
472
+
473
+    // MARK: - Private - Writing Buffered Data to Output Stream
474
+
475
+    private func write(_ data: Data, to outputStream: OutputStream) throws {
476
+        var buffer = [UInt8](repeating: 0, count: data.count)
477
+        data.copyBytes(to: &buffer, count: data.count)
478
+
479
+        return try write(&buffer, to: outputStream)
480
+    }
481
+
482
+    private func write(_ buffer: inout [UInt8], to outputStream: OutputStream) throws {
483
+        var bytesToWrite = buffer.count
484
+
485
+        while bytesToWrite > 0, outputStream.hasSpaceAvailable {
486
+            let bytesWritten = outputStream.write(buffer, maxLength: bytesToWrite)
487
+
488
+            if let error = outputStream.streamError {
489
+                throw AFError.multipartEncodingFailed(reason: .outputStreamWriteFailed(error: error))
490
+            }
491
+
492
+            bytesToWrite -= bytesWritten
493
+
494
+            if bytesToWrite > 0 {
495
+                buffer = Array(buffer[bytesWritten..<buffer.count])
496
+            }
497
+        }
498
+    }
499
+
500
+    // MARK: - Private - Mime Type
501
+
502
+    private func mimeType(forPathExtension pathExtension: String) -> String {
503
+        if
504
+            let id = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, pathExtension as CFString, nil)?.takeRetainedValue(),
505
+            let contentType = UTTypeCopyPreferredTagWithClass(id, kUTTagClassMIMEType)?.takeRetainedValue() {
506
+            return contentType as String
507
+        }
508
+
509
+        return "application/octet-stream"
510
+    }
511
+
512
+    // MARK: - Private - Content Headers
513
+
514
+    private func contentHeaders(withName name: String, fileName: String? = nil, mimeType: String? = nil) -> HTTPHeaders {
515
+        var disposition = "form-data; name=\"\(name)\""
516
+        if let fileName = fileName { disposition += "; filename=\"\(fileName)\"" }
517
+
518
+        var headers: HTTPHeaders = [.contentDisposition(disposition)]
519
+        if let mimeType = mimeType { headers.add(.contentType(mimeType)) }
520
+
521
+        return headers
522
+    }
523
+
524
+    // MARK: - Private - Boundary Encoding
525
+
526
+    private func initialBoundaryData() -> Data {
527
+        return BoundaryGenerator.boundaryData(forBoundaryType: .initial, boundary: boundary)
528
+    }
529
+
530
+    private func encapsulatedBoundaryData() -> Data {
531
+        return BoundaryGenerator.boundaryData(forBoundaryType: .encapsulated, boundary: boundary)
532
+    }
533
+
534
+    private func finalBoundaryData() -> Data {
535
+        return BoundaryGenerator.boundaryData(forBoundaryType: .final, boundary: boundary)
536
+    }
537
+
538
+    // MARK: - Private - Errors
539
+
540
+    private func setBodyPartError(withReason reason: AFError.MultipartEncodingFailureReason) {
541
+        guard bodyPartError == nil else { return }
542
+        bodyPartError = AFError.multipartEncodingFailed(reason: reason)
543
+    }
544
+}

+ 87
- 0
trolley/Pods/Alamofire/Source/MultipartUpload.swift 查看文件

@@ -0,0 +1,87 @@
1
+//
2
+//  MultipartUpload.swift
3
+//
4
+//  Copyright (c) 2014-2018 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
+/// Internal type which encapsulates a `MultipartFormData` upload.
28
+final class MultipartUpload {
29
+    lazy var result = Result { try build() }
30
+
31
+    let isInBackgroundSession: Bool
32
+    let multipartFormData: MultipartFormData
33
+    let encodingMemoryThreshold: UInt64
34
+    let request: URLRequestConvertible
35
+    let fileManager: FileManager
36
+
37
+    init(isInBackgroundSession: Bool,
38
+         encodingMemoryThreshold: UInt64,
39
+         request: URLRequestConvertible,
40
+         multipartFormData: MultipartFormData) {
41
+        self.isInBackgroundSession = isInBackgroundSession
42
+        self.encodingMemoryThreshold = encodingMemoryThreshold
43
+        self.request = request
44
+        fileManager = multipartFormData.fileManager
45
+        self.multipartFormData = multipartFormData
46
+    }
47
+
48
+    func build() throws -> (request: URLRequest, uploadable: UploadRequest.Uploadable) {
49
+        var urlRequest = try request.asURLRequest()
50
+        urlRequest.setValue(multipartFormData.contentType, forHTTPHeaderField: "Content-Type")
51
+
52
+        let uploadable: UploadRequest.Uploadable
53
+        if multipartFormData.contentLength < encodingMemoryThreshold && !isInBackgroundSession {
54
+            let data = try multipartFormData.encode()
55
+
56
+            uploadable = .data(data)
57
+        } else {
58
+            let tempDirectoryURL = fileManager.temporaryDirectory
59
+            let directoryURL = tempDirectoryURL.appendingPathComponent("org.alamofire.manager/multipart.form.data")
60
+            let fileName = UUID().uuidString
61
+            let fileURL = directoryURL.appendingPathComponent(fileName)
62
+
63
+            try fileManager.createDirectory(at: directoryURL, withIntermediateDirectories: true, attributes: nil)
64
+
65
+            do {
66
+                try multipartFormData.writeEncodedData(to: fileURL)
67
+            } catch {
68
+                // Cleanup after attempted write if it fails.
69
+                try? fileManager.removeItem(at: fileURL)
70
+            }
71
+
72
+            uploadable = .file(fileURL, shouldRemove: true)
73
+        }
74
+
75
+        return (request: urlRequest, uploadable: uploadable)
76
+    }
77
+}
78
+
79
+extension MultipartUpload: UploadConvertible {
80
+    func asURLRequest() throws -> URLRequest {
81
+        return try result.get().request
82
+    }
83
+
84
+    func createUploadable() throws -> UploadRequest.Uploadable {
85
+        return try result.get().uploadable
86
+    }
87
+}

+ 266
- 0
trolley/Pods/Alamofire/Source/NetworkReachabilityManager.swift 查看文件

@@ -0,0 +1,266 @@
1
+//
2
+//  NetworkReachabilityManager.swift
3
+//
4
+//  Copyright (c) 2014-2018 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) || os(Linux))
26
+
27
+import Foundation
28
+import SystemConfiguration
29
+
30
+/// The `NetworkReachabilityManager` class listens for reachability changes of hosts and addresses for both cellular and
31
+/// WiFi network interfaces.
32
+///
33
+/// Reachability can be used to determine background information about why a network operation failed, or to retry
34
+/// network requests when a connection is established. It should not be used to prevent a user from initiating a network
35
+/// request, as it's possible that an initial request may be required to establish reachability.
36
+open class NetworkReachabilityManager {
37
+    /// Defines the various states of network reachability.
38
+    public enum NetworkReachabilityStatus {
39
+        /// It is unknown whether the network is reachable.
40
+        case unknown
41
+        /// The network is not reachable.
42
+        case notReachable
43
+        /// The network is reachable on the associated `ConnectionType`.
44
+        case reachable(ConnectionType)
45
+
46
+        init(_ flags: SCNetworkReachabilityFlags) {
47
+            guard flags.isActuallyReachable else { self = .notReachable; return }
48
+
49
+            var networkStatus: NetworkReachabilityStatus = .reachable(.ethernetOrWiFi)
50
+
51
+            if flags.isCellular { networkStatus = .reachable(.cellular) }
52
+
53
+            self = networkStatus
54
+        }
55
+
56
+        /// Defines the various connection types detected by reachability flags.
57
+        public enum ConnectionType {
58
+            /// The connection type is either over Ethernet or WiFi.
59
+            case ethernetOrWiFi
60
+            /// The connection type is a cellular connection.
61
+            case cellular
62
+        }
63
+    }
64
+
65
+    /// A closure executed when the network reachability status changes. The closure takes a single argument: the
66
+    /// network reachability status.
67
+    public typealias Listener = (NetworkReachabilityStatus) -> Void
68
+
69
+    /// Default `NetworkReachabilityManager` for the zero address and a `listenerQueue` of `.main`.
70
+    public static let `default` = NetworkReachabilityManager()
71
+
72
+    // MARK: - Properties
73
+
74
+    /// Whether the network is currently reachable.
75
+    open var isReachable: Bool { return isReachableOnCellular || isReachableOnEthernetOrWiFi }
76
+
77
+    /// Whether the network is currently reachable over the cellular interface.
78
+    ///
79
+    /// - Note: Using this property to decide whether to make a high or low bandwidth request is not recommended.
80
+    ///         Instead, set the `allowsCellularAccess` on any `URLRequest`s being issued.
81
+    ///
82
+    open var isReachableOnCellular: Bool { return status == .reachable(.cellular) }
83
+
84
+    /// Whether the network is currently reachable over Ethernet or WiFi interface.
85
+    open var isReachableOnEthernetOrWiFi: Bool { return status == .reachable(.ethernetOrWiFi) }
86
+
87
+    /// `DispatchQueue` on which reachability will update.
88
+    public let reachabilityQueue = DispatchQueue(label: "org.alamofire.reachabilityQueue")
89
+
90
+    /// Flags of the current reachability type, if any.
91
+    open var flags: SCNetworkReachabilityFlags? {
92
+        var flags = SCNetworkReachabilityFlags()
93
+
94
+        return (SCNetworkReachabilityGetFlags(reachability, &flags)) ? flags : nil
95
+    }
96
+
97
+    /// The current network reachability status.
98
+    open var status: NetworkReachabilityStatus {
99
+        return flags.map(NetworkReachabilityStatus.init) ?? .unknown
100
+    }
101
+
102
+    /// Mutable state storage.
103
+    struct MutableState {
104
+        /// A closure executed when the network reachability status changes.
105
+        var listener: Listener?
106
+        /// `DispatchQueue` on which listeners will be called.
107
+        var listenerQueue: DispatchQueue?
108
+        /// Previously calculated status.
109
+        var previousStatus: NetworkReachabilityStatus?
110
+    }
111
+
112
+    /// `SCNetworkReachability` instance providing notifications.
113
+    private let reachability: SCNetworkReachability
114
+
115
+    /// Protected storage for mutable state.
116
+    private let mutableState = Protector(MutableState())
117
+
118
+    // MARK: - Initialization
119
+
120
+    /// Creates an instance with the specified host.
121
+    ///
122
+    /// - Note: The `host` value must *not* contain a scheme, just the hostname.
123
+    ///
124
+    /// - Parameters:
125
+    ///   - host:          Host used to evaluate network reachability. Must *not* include the scheme (e.g. `https`).
126
+    public convenience init?(host: String) {
127
+        guard let reachability = SCNetworkReachabilityCreateWithName(nil, host) else { return nil }
128
+
129
+        self.init(reachability: reachability)
130
+    }
131
+
132
+    /// Creates an instance that monitors the address 0.0.0.0.
133
+    ///
134
+    /// Reachability treats the 0.0.0.0 address as a special token that causes it to monitor the general routing
135
+    /// status of the device, both IPv4 and IPv6.
136
+    public convenience init?() {
137
+        var zero = sockaddr()
138
+        zero.sa_len = UInt8(MemoryLayout<sockaddr>.size)
139
+        zero.sa_family = sa_family_t(AF_INET)
140
+
141
+        guard let reachability = SCNetworkReachabilityCreateWithAddress(nil, &zero) else { return nil }
142
+
143
+        self.init(reachability: reachability)
144
+    }
145
+
146
+    private init(reachability: SCNetworkReachability) {
147
+        self.reachability = reachability
148
+    }
149
+
150
+    deinit {
151
+        stopListening()
152
+    }
153
+
154
+    // MARK: - Listening
155
+
156
+    /// Starts listening for changes in network reachability status.
157
+    ///
158
+    /// - Note: Stops and removes any existing listener.
159
+    ///
160
+    /// - Parameters:
161
+    ///   - queue:    `DispatchQueue` on which to call the `listener` closure. `.main` by default.
162
+    ///   - listener: `Listener` closure called when reachability changes.
163
+    ///
164
+    /// - Returns: `true` if listening was started successfully, `false` otherwise.
165
+    @discardableResult
166
+    open func startListening(onQueue queue: DispatchQueue = .main,
167
+                             onUpdatePerforming listener: @escaping Listener) -> Bool {
168
+        stopListening()
169
+
170
+        mutableState.write { state in
171
+            state.listenerQueue = queue
172
+            state.listener = listener
173
+        }
174
+
175
+        var context = SCNetworkReachabilityContext(version: 0,
176
+                                                   info: Unmanaged.passRetained(self).toOpaque(),
177
+                                                   retain: nil,
178
+                                                   release: nil,
179
+                                                   copyDescription: nil)
180
+        let callback: SCNetworkReachabilityCallBack = { _, flags, info in
181
+            guard let info = info else { return }
182
+
183
+            let instance = Unmanaged<NetworkReachabilityManager>.fromOpaque(info).takeUnretainedValue()
184
+            instance.notifyListener(flags)
185
+        }
186
+
187
+        let queueAdded = SCNetworkReachabilitySetDispatchQueue(reachability, reachabilityQueue)
188
+        let callbackAdded = SCNetworkReachabilitySetCallback(reachability, callback, &context)
189
+
190
+        // Manually call listener to give initial state, since the framework may not.
191
+        if let currentFlags = flags {
192
+            reachabilityQueue.async {
193
+                self.notifyListener(currentFlags)
194
+            }
195
+        }
196
+
197
+        return callbackAdded && queueAdded
198
+    }
199
+
200
+    /// Stops listening for changes in network reachability status.
201
+    open func stopListening() {
202
+        SCNetworkReachabilitySetCallback(reachability, nil, nil)
203
+        SCNetworkReachabilitySetDispatchQueue(reachability, nil)
204
+        mutableState.write { state in
205
+            state.listener = nil
206
+            state.listenerQueue = nil
207
+            state.previousStatus = nil
208
+        }
209
+    }
210
+
211
+    // MARK: - Internal - Listener Notification
212
+
213
+    /// Calls the `listener` closure of the `listenerQueue` if the computed status hasn't changed.
214
+    ///
215
+    /// - Note: Should only be called from the `reachabilityQueue`.
216
+    ///
217
+    /// - Parameter flags: `SCNetworkReachabilityFlags` to use to calculate the status.
218
+    func notifyListener(_ flags: SCNetworkReachabilityFlags) {
219
+        let newStatus = NetworkReachabilityStatus(flags)
220
+
221
+        mutableState.write { state in
222
+            guard state.previousStatus != newStatus else { return }
223
+
224
+            state.previousStatus = newStatus
225
+
226
+            let listener = state.listener
227
+            state.listenerQueue?.async { listener?(newStatus) }
228
+        }
229
+    }
230
+}
231
+
232
+// MARK: -
233
+
234
+extension NetworkReachabilityManager.NetworkReachabilityStatus: Equatable {}
235
+
236
+extension SCNetworkReachabilityFlags {
237
+    var isReachable: Bool { return contains(.reachable) }
238
+    var isConnectionRequired: Bool { return contains(.connectionRequired) }
239
+    var canConnectAutomatically: Bool { return contains(.connectionOnDemand) || contains(.connectionOnTraffic) }
240
+    var canConnectWithoutUserInteraction: Bool { return canConnectAutomatically && !contains(.interventionRequired) }
241
+    var isActuallyReachable: Bool { return isReachable && (!isConnectionRequired || canConnectWithoutUserInteraction) }
242
+    var isCellular: Bool {
243
+#if os(iOS) || os(tvOS)
244
+        return contains(.isWWAN)
245
+#else
246
+        return false
247
+#endif
248
+    }
249
+
250
+    /// Human readable `String` for all states, to help with debugging.
251
+    var readableDescription: String {
252
+        let W = isCellular ? "W" : "-"
253
+        let R = isReachable ? "R" : "-"
254
+        let c = isConnectionRequired ? "c" : "-"
255
+        let t = contains(.transientConnection) ? "t" : "-"
256
+        let i = contains(.interventionRequired) ? "i" : "-"
257
+        let C = contains(.connectionOnTraffic) ? "C" : "-"
258
+        let D = contains(.connectionOnDemand) ? "D" : "-"
259
+        let l = contains(.isLocalAddress) ? "l" : "-"
260
+        let d = contains(.isDirect) ? "d" : "-"
261
+        let a = contains(.connectionAutomatic) ? "a" : "-"
262
+
263
+        return "\(W)\(R) \(c)\(t)\(i)\(C)\(D)\(l)\(d)\(a)"
264
+    }
265
+}
266
+#endif

+ 115
- 0
trolley/Pods/Alamofire/Source/Notifications.swift 查看文件

@@ -0,0 +1,115 @@
1
+//
2
+//  Notifications.swift
3
+//
4
+//  Copyright (c) 2014-2018 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
+public extension Request {
28
+    /// Posted when a `Request` is resumed. The `Notification` contains the resumed `Request`.
29
+    static let didResumeNotification = Notification.Name(rawValue: "org.alamofire.notification.name.request.didResume")
30
+    /// Posted when a `Request` is suspended. The `Notification` contains the suspended `Request`.
31
+    static let didSuspendNotification = Notification.Name(rawValue: "org.alamofire.notification.name.request.didSuspend")
32
+    /// Posted when a `Request` is cancelled. The `Notification` contains the cancelled `Request`.
33
+    static let didCancelNotification = Notification.Name(rawValue: "org.alamofire.notification.name.request.didCancel")
34
+    /// Posted when a `Request` is finished. The `Notification` contains the completed `Request`.
35
+    static let didFinishNotification = Notification.Name(rawValue: "org.alamofire.notification.name.request.didFinish")
36
+
37
+    /// Posted when a `URLSessionTask` is resumed. The `Notification` contains the `Request` associated with the `URLSessionTask`.
38
+    static let didResumeTaskNotification = Notification.Name(rawValue: "org.alamofire.notification.name.request.didResumeTask")
39
+    /// Posted when a `URLSessionTask` is suspended. The `Notification` contains the `Request` associated with the `URLSessionTask`.
40
+    static let didSuspendTaskNotification = Notification.Name(rawValue: "org.alamofire.notification.name.request.didSuspendTask")
41
+    /// Posted when a `URLSessionTask` is cancelled. The `Notification` contains the `Request` associated with the `URLSessionTask`.
42
+    static let didCancelTaskNotification = Notification.Name(rawValue: "org.alamofire.notification.name.request.didCancelTask")
43
+    /// Posted when a `URLSessionTask` is completed. The `Notification` contains the `Request` associated with the `URLSessionTask`.
44
+    static let didCompleteTaskNotification = Notification.Name(rawValue: "org.alamofire.notification.name.request.didCompleteTask")
45
+}
46
+
47
+// MARK: -
48
+
49
+extension Notification {
50
+    /// The `Request` contained by the instance's `userInfo`, `nil` otherwise.
51
+    public var request: Request? {
52
+        return userInfo?[String.requestKey] as? Request
53
+    }
54
+
55
+    /// Convenience initializer for a `Notification` containing a `Request` payload.
56
+    ///
57
+    /// - Parameters:
58
+    ///   - name:    The name of the notification.
59
+    ///   - request: The `Request` payload.
60
+    init(name: Notification.Name, request: Request) {
61
+        self.init(name: name, object: nil, userInfo: [String.requestKey: request])
62
+    }
63
+}
64
+
65
+extension NotificationCenter {
66
+    /// Convenience function for posting notifications with `Request` payloads.
67
+    ///
68
+    /// - Parameters:
69
+    ///   - name:    The name of the notification.
70
+    ///   - request: The `Request` payload.
71
+    func postNotification(named name: Notification.Name, with request: Request) {
72
+        let notification = Notification(name: name, request: request)
73
+        post(notification)
74
+    }
75
+}
76
+
77
+extension String {
78
+    /// User info dictionary key representing the `Request` associated with the notification.
79
+    fileprivate static let requestKey = "org.alamofire.notification.key.request"
80
+}
81
+
82
+/// `EventMonitor` that provides Alamofire's notifications.
83
+public final class AlamofireNotifications: EventMonitor {
84
+    public func requestDidResume(_ request: Request) {
85
+        NotificationCenter.default.postNotification(named: Request.didResumeNotification, with: request)
86
+    }
87
+
88
+    public func requestDidSuspend(_ request: Request) {
89
+        NotificationCenter.default.postNotification(named: Request.didSuspendNotification, with: request)
90
+    }
91
+
92
+    public func requestDidCancel(_ request: Request) {
93
+        NotificationCenter.default.postNotification(named: Request.didCancelNotification, with: request)
94
+    }
95
+
96
+    public func requestDidFinish(_ request: Request) {
97
+        NotificationCenter.default.postNotification(named: Request.didFinishNotification, with: request)
98
+    }
99
+
100
+    public func request(_ request: Request, didResumeTask task: URLSessionTask) {
101
+        NotificationCenter.default.postNotification(named: Request.didResumeTaskNotification, with: request)
102
+    }
103
+
104
+    public func request(_ request: Request, didSuspendTask task: URLSessionTask) {
105
+        NotificationCenter.default.postNotification(named: Request.didSuspendTaskNotification, with: request)
106
+    }
107
+
108
+    public func request(_ request: Request, didCancelTask task: URLSessionTask) {
109
+        NotificationCenter.default.postNotification(named: Request.didCancelTaskNotification, with: request)
110
+    }
111
+
112
+    public func request(_ request: Request, didCompleteTask task: URLSessionTask, with error: AFError?) {
113
+        NotificationCenter.default.postNotification(named: Request.didCompleteTaskNotification, with: request)
114
+    }
115
+}

+ 49
- 0
trolley/Pods/Alamofire/Source/OperationQueue+Alamofire.swift 查看文件

@@ -0,0 +1,49 @@
1
+//
2
+//  OperationQueue+Alamofire.swift
3
+//
4
+//  Copyright (c) 2014-2018 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 OperationQueue {
28
+    /// Creates an instance using the provided parameters.
29
+    ///
30
+    /// - Parameters:
31
+    ///   - qualityOfService:            `QualityOfService` to be applied to the queue. `.default` by default.
32
+    ///   - maxConcurrentOperationCount: Maximum concurrent operations.
33
+    ///                                  `OperationQueue.defaultMaxConcurrentOperationCount` by default.
34
+    ///   - underlyingQueue: Underlying  `DispatchQueue`. `nil` by default.
35
+    ///   - name:                        Name for the queue. `nil` by default.
36
+    ///   - startSuspended:              Whether the queue starts suspended. `false` by default.
37
+    convenience init(qualityOfService: QualityOfService = .default,
38
+                     maxConcurrentOperationCount: Int = OperationQueue.defaultMaxConcurrentOperationCount,
39
+                     underlyingQueue: DispatchQueue? = nil,
40
+                     name: String? = nil,
41
+                     startSuspended: Bool = false) {
42
+        self.init()
43
+        self.qualityOfService = qualityOfService
44
+        self.maxConcurrentOperationCount = maxConcurrentOperationCount
45
+        self.underlyingQueue = underlyingQueue
46
+        self.name = name
47
+        isSuspended = startSuspended
48
+    }
49
+}

+ 184
- 0
trolley/Pods/Alamofire/Source/ParameterEncoder.swift 查看文件

@@ -0,0 +1,184 @@
1
+//
2
+//  ParameterEncoder.swift
3
+//
4
+//  Copyright (c) 2014-2018 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
+/// A type that can encode any `Encodable` type into a `URLRequest`.
28
+public protocol ParameterEncoder {
29
+    /// Encode the provided `Encodable` parameters into `request`.
30
+    ///
31
+    /// - Parameters:
32
+    ///   - parameters: The `Encodable` parameter value.
33
+    ///   - request:    The `URLRequest` into which to encode the parameters.
34
+    ///
35
+    /// - Returns:      A `URLRequest` with the result of the encoding.
36
+    /// - Throws:       An `Error` when encoding fails. For Alamofire provided encoders, this will be an instance of
37
+    ///                 `AFError.parameterEncoderFailed` with an associated `ParameterEncoderFailureReason`.
38
+    func encode<Parameters: Encodable>(_ parameters: Parameters?, into request: URLRequest) throws -> URLRequest
39
+}
40
+
41
+/// A `ParameterEncoder` that encodes types as JSON body data.
42
+///
43
+/// If no `Content-Type` header is already set on the provided `URLRequest`s, it's set to `application/json`.
44
+open class JSONParameterEncoder: ParameterEncoder {
45
+    /// Returns an encoder with default parameters.
46
+    public static var `default`: JSONParameterEncoder { return JSONParameterEncoder() }
47
+
48
+    /// Returns an encoder with `JSONEncoder.outputFormatting` set to `.prettyPrinted`.
49
+    public static var prettyPrinted: JSONParameterEncoder {
50
+        let encoder = JSONEncoder()
51
+        encoder.outputFormatting = .prettyPrinted
52
+
53
+        return JSONParameterEncoder(encoder: encoder)
54
+    }
55
+
56
+    /// Returns an encoder with `JSONEncoder.outputFormatting` set to `.sortedKeys`.
57
+    @available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
58
+    public static var sortedKeys: JSONParameterEncoder {
59
+        let encoder = JSONEncoder()
60
+        encoder.outputFormatting = .sortedKeys
61
+
62
+        return JSONParameterEncoder(encoder: encoder)
63
+    }
64
+
65
+    /// `JSONEncoder` used to encode parameters.
66
+    public let encoder: JSONEncoder
67
+
68
+    /// Creates an instance with the provided `JSONEncoder`.
69
+    ///
70
+    /// - Parameter encoder: The `JSONEncoder`. `JSONEncoder()` by default.
71
+    public init(encoder: JSONEncoder = JSONEncoder()) {
72
+        self.encoder = encoder
73
+    }
74
+
75
+    open func encode<Parameters: Encodable>(_ parameters: Parameters?,
76
+                                            into request: URLRequest) throws -> URLRequest {
77
+        guard let parameters = parameters else { return request }
78
+
79
+        var request = request
80
+
81
+        do {
82
+            let data = try encoder.encode(parameters)
83
+            request.httpBody = data
84
+            if request.headers["Content-Type"] == nil {
85
+                request.headers.update(.contentType("application/json"))
86
+            }
87
+        } catch {
88
+            throw AFError.parameterEncodingFailed(reason: .jsonEncodingFailed(error: error))
89
+        }
90
+
91
+        return request
92
+    }
93
+}
94
+
95
+/// A `ParameterEncoder` that encodes types as URL-encoded query strings to be set on the URL or as body data, depending
96
+/// on the `Destination` set.
97
+///
98
+/// If no `Content-Type` header is already set on the provided `URLRequest`s, it will be set to
99
+/// `application/x-www-form-urlencoded; charset=utf-8`.
100
+///
101
+/// Encoding behavior can be customized by passing an instance of `URLEncodedFormEncoder` to the initializer.
102
+open class URLEncodedFormParameterEncoder: ParameterEncoder {
103
+    /// Defines where the URL-encoded string should be set for each `URLRequest`.
104
+    public enum Destination {
105
+        /// Applies the encoded query string to any existing query string for `.get`, `.head`, and `.delete` request.
106
+        /// Sets it to the `httpBody` for all other methods.
107
+        case methodDependent
108
+        /// Applies the encoded query string to any existing query string from the `URLRequest`.
109
+        case queryString
110
+        /// Applies the encoded query string to the `httpBody` of the `URLRequest`.
111
+        case httpBody
112
+
113
+        /// Determines whether the URL-encoded string should be applied to the `URLRequest`'s `url`.
114
+        ///
115
+        /// - Parameter method: The `HTTPMethod`.
116
+        ///
117
+        /// - Returns:          Whether the URL-encoded string should be applied to a `URL`.
118
+        func encodesParametersInURL(for method: HTTPMethod) -> Bool {
119
+            switch self {
120
+            case .methodDependent: return [.get, .head, .delete].contains(method)
121
+            case .queryString: return true
122
+            case .httpBody: return false
123
+            }
124
+        }
125
+    }
126
+
127
+    /// Returns an encoder with default parameters.
128
+    public static var `default`: URLEncodedFormParameterEncoder { return URLEncodedFormParameterEncoder() }
129
+
130
+    /// The `URLEncodedFormEncoder` to use.
131
+    public let encoder: URLEncodedFormEncoder
132
+
133
+    /// The `Destination` for the URL-encoded string.
134
+    public let destination: Destination
135
+
136
+    /// Creates an instance with the provided `URLEncodedFormEncoder` instance and `Destination` value.
137
+    ///
138
+    /// - Parameters:
139
+    ///   - encoder:     The `URLEncodedFormEncoder`. `URLEncodedFormEncoder()` by default.
140
+    ///   - destination: The `Destination`. `.methodDependent` by default.
141
+    public init(encoder: URLEncodedFormEncoder = URLEncodedFormEncoder(), destination: Destination = .methodDependent) {
142
+        self.encoder = encoder
143
+        self.destination = destination
144
+    }
145
+
146
+    open func encode<Parameters: Encodable>(_ parameters: Parameters?,
147
+                                            into request: URLRequest) throws -> URLRequest {
148
+        guard let parameters = parameters else { return request }
149
+
150
+        var request = request
151
+
152
+        guard let url = request.url else {
153
+            throw AFError.parameterEncoderFailed(reason: .missingRequiredComponent(.url))
154
+        }
155
+
156
+        guard let method = request.method else {
157
+            let rawValue = request.method?.rawValue ?? "nil"
158
+            throw AFError.parameterEncoderFailed(reason: .missingRequiredComponent(.httpMethod(rawValue: rawValue)))
159
+        }
160
+
161
+        if destination.encodesParametersInURL(for: method),
162
+            var components = URLComponents(url: url, resolvingAgainstBaseURL: false) {
163
+            let query: String = try Result<String, Error> { try encoder.encode(parameters) }
164
+                .mapError { AFError.parameterEncoderFailed(reason: .encoderFailed(error: $0)) }.get()
165
+            let newQueryString = [components.percentEncodedQuery, query].compactMap { $0 }.joinedWithAmpersands()
166
+            components.percentEncodedQuery = newQueryString.isEmpty ? nil : newQueryString
167
+
168
+            guard let newURL = components.url else {
169
+                throw AFError.parameterEncoderFailed(reason: .missingRequiredComponent(.url))
170
+            }
171
+
172
+            request.url = newURL
173
+        } else {
174
+            if request.headers["Content-Type"] == nil {
175
+                request.headers.update(.contentType("application/x-www-form-urlencoded; charset=utf-8"))
176
+            }
177
+
178
+            request.httpBody = try Result<Data, Error> { try encoder.encode(parameters) }
179
+                .mapError { AFError.parameterEncoderFailed(reason: .encoderFailed(error: $0)) }.get()
180
+        }
181
+
182
+        return request
183
+    }
184
+}

+ 314
- 0
trolley/Pods/Alamofire/Source/ParameterEncoding.swift 查看文件

@@ -0,0 +1,314 @@
1
+//
2
+//  ParameterEncoding.swift
3
+//
4
+//  Copyright (c) 2014-2018 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
+/// A dictionary of parameters to apply to a `URLRequest`.
28
+public typealias Parameters = [String: Any]
29
+
30
+/// A type used to define how a set of parameters are applied to a `URLRequest`.
31
+public protocol ParameterEncoding {
32
+    /// Creates a `URLRequest` by encoding parameters and applying them on the passed request.
33
+    ///
34
+    /// - Parameters:
35
+    ///   - urlRequest: `URLRequestConvertible` value onto which parameters will be encoded.
36
+    ///   - parameters: `Parameters` to encode onto the request.
37
+    ///
38
+    /// - Returns:      The encoded `URLRequest`.
39
+    /// - Throws:       Any `Error` produced during parameter encoding.
40
+    func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest
41
+}
42
+
43
+// MARK: -
44
+
45
+/// Creates a url-encoded query string to be set as or appended to any existing URL query string or set as the HTTP
46
+/// body of the URL request. Whether the query string is set or appended to any existing URL query string or set as
47
+/// the HTTP body depends on the destination of the encoding.
48
+///
49
+/// The `Content-Type` HTTP header field of an encoded request with HTTP body is set to
50
+/// `application/x-www-form-urlencoded; charset=utf-8`.
51
+///
52
+/// There is no published specification for how to encode collection types. By default the convention of appending
53
+/// `[]` to the key for array values (`foo[]=1&foo[]=2`), and appending the key surrounded by square brackets for
54
+/// nested dictionary values (`foo[bar]=baz`) is used. Optionally, `ArrayEncoding` can be used to omit the
55
+/// square brackets appended to array keys.
56
+///
57
+/// `BoolEncoding` can be used to configure how boolean values are encoded. The default behavior is to encode
58
+/// `true` as 1 and `false` as 0.
59
+public struct URLEncoding: ParameterEncoding {
60
+    // MARK: Helper Types
61
+
62
+    /// Defines whether the url-encoded query string is applied to the existing query string or HTTP body of the
63
+    /// resulting URL request.
64
+    public enum Destination {
65
+        /// Applies encoded query string result to existing query string for `GET`, `HEAD` and `DELETE` requests and
66
+        /// sets as the HTTP body for requests with any other HTTP method.
67
+        case methodDependent
68
+        /// Sets or appends encoded query string result to existing query string.
69
+        case queryString
70
+        /// Sets encoded query string result as the HTTP body of the URL request.
71
+        case httpBody
72
+
73
+        func encodesParametersInURL(for method: HTTPMethod) -> Bool {
74
+            switch self {
75
+            case .methodDependent: return [.get, .head, .delete].contains(method)
76
+            case .queryString: return true
77
+            case .httpBody: return false
78
+            }
79
+        }
80
+    }
81
+
82
+    /// Configures how `Array` parameters are encoded.
83
+    public enum ArrayEncoding {
84
+        /// An empty set of square brackets is appended to the key for every value. This is the default behavior.
85
+        case brackets
86
+        /// No brackets are appended. The key is encoded as is.
87
+        case noBrackets
88
+
89
+        func encode(key: String) -> String {
90
+            switch self {
91
+            case .brackets:
92
+                return "\(key)[]"
93
+            case .noBrackets:
94
+                return key
95
+            }
96
+        }
97
+    }
98
+
99
+    /// Configures how `Bool` parameters are encoded.
100
+    public enum BoolEncoding {
101
+        /// Encode `true` as `1` and `false` as `0`. This is the default behavior.
102
+        case numeric
103
+        /// Encode `true` and `false` as string literals.
104
+        case literal
105
+
106
+        func encode(value: Bool) -> String {
107
+            switch self {
108
+            case .numeric:
109
+                return value ? "1" : "0"
110
+            case .literal:
111
+                return value ? "true" : "false"
112
+            }
113
+        }
114
+    }
115
+
116
+    // MARK: Properties
117
+
118
+    /// Returns a default `URLEncoding` instance with a `.methodDependent` destination.
119
+    public static var `default`: URLEncoding { return URLEncoding() }
120
+
121
+    /// Returns a `URLEncoding` instance with a `.queryString` destination.
122
+    public static var queryString: URLEncoding { return URLEncoding(destination: .queryString) }
123
+
124
+    /// Returns a `URLEncoding` instance with an `.httpBody` destination.
125
+    public static var httpBody: URLEncoding { return URLEncoding(destination: .httpBody) }
126
+
127
+    /// The destination defining where the encoded query string is to be applied to the URL request.
128
+    public let destination: Destination
129
+
130
+    /// The encoding to use for `Array` parameters.
131
+    public let arrayEncoding: ArrayEncoding
132
+
133
+    /// The encoding to use for `Bool` parameters.
134
+    public let boolEncoding: BoolEncoding
135
+
136
+    // MARK: Initialization
137
+
138
+    /// Creates an instance using the specified parameters.
139
+    ///
140
+    /// - Parameters:
141
+    ///   - destination:   `Destination` defining where the encoded query string will be applied. `.methodDependent` by
142
+    ///                    default.
143
+    ///   - arrayEncoding: `ArrayEncoding` to use. `.brackets` by default.
144
+    ///   - boolEncoding:  `BoolEncoding` to use. `.numeric` by default.
145
+    public init(destination: Destination = .methodDependent,
146
+                arrayEncoding: ArrayEncoding = .brackets,
147
+                boolEncoding: BoolEncoding = .numeric) {
148
+        self.destination = destination
149
+        self.arrayEncoding = arrayEncoding
150
+        self.boolEncoding = boolEncoding
151
+    }
152
+
153
+    // MARK: Encoding
154
+
155
+    public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
156
+        var urlRequest = try urlRequest.asURLRequest()
157
+
158
+        guard let parameters = parameters else { return urlRequest }
159
+
160
+        if let method = urlRequest.method, destination.encodesParametersInURL(for: method) {
161
+            guard let url = urlRequest.url else {
162
+                throw AFError.parameterEncodingFailed(reason: .missingURL)
163
+            }
164
+
165
+            if var urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false), !parameters.isEmpty {
166
+                let percentEncodedQuery = (urlComponents.percentEncodedQuery.map { $0 + "&" } ?? "") + query(parameters)
167
+                urlComponents.percentEncodedQuery = percentEncodedQuery
168
+                urlRequest.url = urlComponents.url
169
+            }
170
+        } else {
171
+            if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil {
172
+                urlRequest.setValue("application/x-www-form-urlencoded; charset=utf-8", forHTTPHeaderField: "Content-Type")
173
+            }
174
+
175
+            urlRequest.httpBody = Data(query(parameters).utf8)
176
+        }
177
+
178
+        return urlRequest
179
+    }
180
+
181
+    /// Creates a percent-escaped, URL encoded query string components from the given key-value pair recursively.
182
+    ///
183
+    /// - Parameters:
184
+    ///   - key:   Key of the query component.
185
+    ///   - value: Value of the query component.
186
+    ///
187
+    /// - Returns: The percent-escaped, URL encoded query string components.
188
+    public func queryComponents(fromKey key: String, value: Any) -> [(String, String)] {
189
+        var components: [(String, String)] = []
190
+
191
+        if let dictionary = value as? [String: Any] {
192
+            for (nestedKey, value) in dictionary {
193
+                components += queryComponents(fromKey: "\(key)[\(nestedKey)]", value: value)
194
+            }
195
+        } else if let array = value as? [Any] {
196
+            for value in array {
197
+                components += queryComponents(fromKey: arrayEncoding.encode(key: key), value: value)
198
+            }
199
+        } else if let value = value as? NSNumber {
200
+            if value.isBool {
201
+                components.append((escape(key), escape(boolEncoding.encode(value: value.boolValue))))
202
+            } else {
203
+                components.append((escape(key), escape("\(value)")))
204
+            }
205
+        } else if let bool = value as? Bool {
206
+            components.append((escape(key), escape(boolEncoding.encode(value: bool))))
207
+        } else {
208
+            components.append((escape(key), escape("\(value)")))
209
+        }
210
+
211
+        return components
212
+    }
213
+
214
+    /// Creates a percent-escaped string following RFC 3986 for a query string key or value.
215
+    ///
216
+    /// - Parameter string: `String` to be percent-escaped.
217
+    ///
218
+    /// - Returns:          The percent-escaped `String`.
219
+    public func escape(_ string: String) -> String {
220
+        return string.addingPercentEncoding(withAllowedCharacters: .afURLQueryAllowed) ?? string
221
+    }
222
+
223
+    private func query(_ parameters: [String: Any]) -> String {
224
+        var components: [(String, String)] = []
225
+
226
+        for key in parameters.keys.sorted(by: <) {
227
+            let value = parameters[key]!
228
+            components += queryComponents(fromKey: key, value: value)
229
+        }
230
+        return components.map { "\($0)=\($1)" }.joined(separator: "&")
231
+    }
232
+}
233
+
234
+// MARK: -
235
+
236
+/// Uses `JSONSerialization` to create a JSON representation of the parameters object, which is set as the body of the
237
+/// request. The `Content-Type` HTTP header field of an encoded request is set to `application/json`.
238
+public struct JSONEncoding: ParameterEncoding {
239
+    // MARK: Properties
240
+
241
+    /// Returns a `JSONEncoding` instance with default writing options.
242
+    public static var `default`: JSONEncoding { return JSONEncoding() }
243
+
244
+    /// Returns a `JSONEncoding` instance with `.prettyPrinted` writing options.
245
+    public static var prettyPrinted: JSONEncoding { return JSONEncoding(options: .prettyPrinted) }
246
+
247
+    /// The options for writing the parameters as JSON data.
248
+    public let options: JSONSerialization.WritingOptions
249
+
250
+    // MARK: Initialization
251
+
252
+    /// Creates an instance using the specified `WritingOptions`.
253
+    ///
254
+    /// - Parameter options: `JSONSerialization.WritingOptions` to use.
255
+    public init(options: JSONSerialization.WritingOptions = []) {
256
+        self.options = options
257
+    }
258
+
259
+    // MARK: Encoding
260
+
261
+    public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
262
+        var urlRequest = try urlRequest.asURLRequest()
263
+
264
+        guard let parameters = parameters else { return urlRequest }
265
+
266
+        do {
267
+            let data = try JSONSerialization.data(withJSONObject: parameters, options: options)
268
+
269
+            if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil {
270
+                urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
271
+            }
272
+
273
+            urlRequest.httpBody = data
274
+        } catch {
275
+            throw AFError.parameterEncodingFailed(reason: .jsonEncodingFailed(error: error))
276
+        }
277
+
278
+        return urlRequest
279
+    }
280
+
281
+    /// Encodes any JSON compatible object into a `URLRequest`.
282
+    ///
283
+    /// - Parameters:
284
+    ///   - urlRequest: `URLRequestConvertible` value into which the object will be encoded.
285
+    ///   - jsonObject: `Any` value (must be JSON compatible` to be encoded into the `URLRequest`. `nil` by default.
286
+    ///
287
+    /// - Returns:      The encoded `URLRequest`.
288
+    /// - Throws:       Any `Error` produced during encoding.
289
+    public func encode(_ urlRequest: URLRequestConvertible, withJSONObject jsonObject: Any? = nil) throws -> URLRequest {
290
+        var urlRequest = try urlRequest.asURLRequest()
291
+
292
+        guard let jsonObject = jsonObject else { return urlRequest }
293
+
294
+        do {
295
+            let data = try JSONSerialization.data(withJSONObject: jsonObject, options: options)
296
+
297
+            if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil {
298
+                urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
299
+            }
300
+
301
+            urlRequest.httpBody = data
302
+        } catch {
303
+            throw AFError.parameterEncodingFailed(reason: .jsonEncodingFailed(error: error))
304
+        }
305
+
306
+        return urlRequest
307
+    }
308
+}
309
+
310
+// MARK: -
311
+
312
+extension NSNumber {
313
+    fileprivate var isBool: Bool { return CFBooleanGetTypeID() == CFGetTypeID(self) }
314
+}

+ 167
- 0
trolley/Pods/Alamofire/Source/Protector.swift 查看文件

@@ -0,0 +1,167 @@
1
+//
2
+//  Protector.swift
3
+//
4
+//  Copyright (c) 2014-2018 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: -
28
+
29
+/// An `os_unfair_lock` wrapper.
30
+final class UnfairLock {
31
+    private let unfairLock: os_unfair_lock_t
32
+
33
+    init() {
34
+        unfairLock = .allocate(capacity: 1)
35
+        unfairLock.initialize(to: os_unfair_lock())
36
+    }
37
+
38
+    deinit {
39
+        unfairLock.deinitialize(count: 1)
40
+        unfairLock.deallocate()
41
+    }
42
+
43
+    private func lock() {
44
+        os_unfair_lock_lock(unfairLock)
45
+    }
46
+
47
+    private func unlock() {
48
+        os_unfair_lock_unlock(unfairLock)
49
+    }
50
+
51
+    /// Executes a closure returning a value while acquiring the lock.
52
+    ///
53
+    /// - Parameter closure: The closure to run.
54
+    ///
55
+    /// - Returns:           The value the closure generated.
56
+    func around<T>(_ closure: () -> T) -> T {
57
+        lock(); defer { unlock() }
58
+        return closure()
59
+    }
60
+
61
+    /// Execute a closure while acquiring the lock.
62
+    ///
63
+    /// - Parameter closure: The closure to run.
64
+    func around(_ closure: () -> Void) {
65
+        lock(); defer { unlock() }
66
+        return closure()
67
+    }
68
+}
69
+
70
+/// A thread-safe wrapper around a value.
71
+final class Protector<T> {
72
+    private let lock = UnfairLock()
73
+    private var value: T
74
+
75
+    init(_ value: T) {
76
+        self.value = value
77
+    }
78
+
79
+    /// The contained value. Unsafe for anything more than direct read or write.
80
+    var directValue: T {
81
+        get { return lock.around { value } }
82
+        set { lock.around { value = newValue } }
83
+    }
84
+
85
+    /// Synchronously read or transform the contained value.
86
+    ///
87
+    /// - Parameter closure: The closure to execute.
88
+    ///
89
+    /// - Returns:           The return value of the closure passed.
90
+    func read<U>(_ closure: (T) -> U) -> U {
91
+        return lock.around { closure(self.value) }
92
+    }
93
+
94
+    /// Synchronously modify the protected value.
95
+    ///
96
+    /// - Parameter closure: The closure to execute.
97
+    ///
98
+    /// - Returns:           The modified value.
99
+    @discardableResult
100
+    func write<U>(_ closure: (inout T) -> U) -> U {
101
+        return lock.around { closure(&self.value) }
102
+    }
103
+}
104
+
105
+extension Protector where T: RangeReplaceableCollection {
106
+    /// Adds a new element to the end of this protected collection.
107
+    ///
108
+    /// - Parameter newElement: The `Element` to append.
109
+    func append(_ newElement: T.Element) {
110
+        write { (ward: inout T) in
111
+            ward.append(newElement)
112
+        }
113
+    }
114
+
115
+    /// Adds the elements of a sequence to the end of this protected collection.
116
+    ///
117
+    /// - Parameter newElements: The `Sequence` to append.
118
+    func append<S: Sequence>(contentsOf newElements: S) where S.Element == T.Element {
119
+        write { (ward: inout T) in
120
+            ward.append(contentsOf: newElements)
121
+        }
122
+    }
123
+
124
+    /// Add the elements of a collection to the end of the protected collection.
125
+    ///
126
+    /// - Parameter newElements: The `Collection` to append.
127
+    func append<C: Collection>(contentsOf newElements: C) where C.Element == T.Element {
128
+        write { (ward: inout T) in
129
+            ward.append(contentsOf: newElements)
130
+        }
131
+    }
132
+}
133
+
134
+extension Protector where T == Data? {
135
+    /// Adds the contents of a `Data` value to the end of the protected `Data`.
136
+    ///
137
+    /// - Parameter data: The `Data` to be appended.
138
+    func append(_ data: Data) {
139
+        write { (ward: inout T) in
140
+            ward?.append(data)
141
+        }
142
+    }
143
+}
144
+
145
+extension Protector where T == Request.MutableState {
146
+    /// Attempts to transition to the passed `State`.
147
+    ///
148
+    /// - Parameter state: The `State` to attempt transition to.
149
+    ///
150
+    /// - Returns:         Whether the transition occurred.
151
+    func attemptToTransitionTo(_ state: Request.State) -> Bool {
152
+        return lock.around {
153
+            guard value.state.canTransitionTo(state) else { return false }
154
+
155
+            value.state = state
156
+
157
+            return true
158
+        }
159
+    }
160
+
161
+    /// Perform a closure while locked with the provided `Request.State`.
162
+    ///
163
+    /// - Parameter perform: The closure to perform while locked.
164
+    func withState(perform: (Request.State) -> Void) {
165
+        lock.around { perform(value.state) }
166
+    }
167
+}

+ 95
- 0
trolley/Pods/Alamofire/Source/RedirectHandler.swift 查看文件

@@ -0,0 +1,95 @@
1
+//
2
+//  RedirectHandler.swift
3
+//
4
+//  Copyright (c) 2014-2018 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
+/// A type that handles how an HTTP redirect response from a remote server should be redirected to the new request.
28
+public protocol RedirectHandler {
29
+    /// Determines how the HTTP redirect response should be redirected to the new request.
30
+    ///
31
+    /// The `completion` closure should be passed one of three possible options:
32
+    ///
33
+    ///   1. The new request specified by the redirect (this is the most common use case).
34
+    ///   2. A modified version of the new request (you may want to route it somewhere else).
35
+    ///   3. A `nil` value to deny the redirect request and return the body of the redirect response.
36
+    ///
37
+    /// - Parameters:
38
+    ///   - task:       The task whose request resulted in a redirect.
39
+    ///   - request:    The URL request object to the new location specified by the redirect response.
40
+    ///   - response:   The response containing the server's response to the original request.
41
+    ///   - completion: The closure to execute containing the new request, a modified request, or `nil`.
42
+    func task(_ task: URLSessionTask,
43
+              willBeRedirectedTo request: URLRequest,
44
+              for response: HTTPURLResponse,
45
+              completion: @escaping (URLRequest?) -> Void)
46
+}
47
+
48
+// MARK: -
49
+
50
+/// `Redirector` is a convenience `RedirectHandler` making it easy to follow, not follow, or modify a redirect.
51
+public struct Redirector {
52
+    /// Defines the behavior of the `Redirector` type.
53
+    public enum Behavior {
54
+        /// Follow the redirect as defined in the response.
55
+        case follow
56
+        /// Do not follow the redirect defined in the response.
57
+        case doNotFollow
58
+        /// Modify the redirect request defined in the response.
59
+        case modify((URLSessionTask, URLRequest, HTTPURLResponse) -> URLRequest?)
60
+    }
61
+
62
+    /// Returns a `Redirector` with a `.follow` `Behavior`.
63
+    public static let follow = Redirector(behavior: .follow)
64
+    /// Returns a `Redirector` with a `.doNotFollow` `Behavior`.
65
+    public static let doNotFollow = Redirector(behavior: .doNotFollow)
66
+
67
+    /// The `Behavior` of the `Redirector`.
68
+    public let behavior: Behavior
69
+
70
+    /// Creates a `Redirector` instance from the `Behavior`.
71
+    ///
72
+    /// - Parameter behavior: The `Behavior`.
73
+    public init(behavior: Behavior) {
74
+        self.behavior = behavior
75
+    }
76
+}
77
+
78
+// MARK: -
79
+
80
+extension Redirector: RedirectHandler {
81
+    public func task(_ task: URLSessionTask,
82
+                     willBeRedirectedTo request: URLRequest,
83
+                     for response: HTTPURLResponse,
84
+                     completion: @escaping (URLRequest?) -> Void) {
85
+        switch behavior {
86
+        case .follow:
87
+            completion(request)
88
+        case .doNotFollow:
89
+            completion(nil)
90
+        case let .modify(closure):
91
+            let request = closure(task, request, response)
92
+            completion(request)
93
+        }
94
+    }
95
+}

+ 1461
- 0
trolley/Pods/Alamofire/Source/Request.swift
文件差异内容过多而无法显示
查看文件


+ 243
- 0
trolley/Pods/Alamofire/Source/RequestInterceptor.swift 查看文件

@@ -0,0 +1,243 @@
1
+//
2
+//  RequestInterceptor.swift
3
+//
4
+//  Copyright (c) 2019 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
+/// A type that can inspect and optionally adapt a `URLRequest` in some manner if necessary.
28
+public protocol RequestAdapter {
29
+    /// Inspects and adapts the specified `URLRequest` in some manner and calls the completion handler with the Result.
30
+    ///
31
+    /// - Parameters:
32
+    ///   - urlRequest: The `URLRequest` to adapt.
33
+    ///   - session:    The `Session` that will execute the `URLRequest`.
34
+    ///   - completion: The completion handler that must be called when adaptation is complete.
35
+    func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void)
36
+}
37
+
38
+// MARK: -
39
+
40
+/// Outcome of determination whether retry is necessary.
41
+public enum RetryResult {
42
+    /// Retry should be attempted immediately.
43
+    case retry
44
+    /// Retry should be attempted after the associated `TimeInterval`.
45
+    case retryWithDelay(TimeInterval)
46
+    /// Do not retry.
47
+    case doNotRetry
48
+    /// Do not retry due to the associated `AFError`.
49
+    case doNotRetryWithError(Error)
50
+}
51
+
52
+extension RetryResult {
53
+    var retryRequired: Bool {
54
+        switch self {
55
+        case .retry, .retryWithDelay: return true
56
+        default: return false
57
+        }
58
+    }
59
+
60
+    var delay: TimeInterval? {
61
+        switch self {
62
+        case let .retryWithDelay(delay): return delay
63
+        default: return nil
64
+        }
65
+    }
66
+
67
+    var error: Error? {
68
+        guard case let .doNotRetryWithError(error) = self else { return nil }
69
+        return error
70
+    }
71
+}
72
+
73
+/// A type that determines whether a request should be retried after being executed by the specified session manager
74
+/// and encountering an error.
75
+public protocol RequestRetrier {
76
+    /// Determines whether the `Request` should be retried by calling the `completion` closure.
77
+    ///
78
+    /// This operation is fully asynchronous. Any amount of time can be taken to determine whether the request needs
79
+    /// to be retried. The one requirement is that the completion closure is called to ensure the request is properly
80
+    /// cleaned up after.
81
+    ///
82
+    /// - Parameters:
83
+    ///   - request:    `Request` that failed due to the provided `Error`.
84
+    ///   - session:    `Session` that produced the `Request`.
85
+    ///   - error:      `Error` encountered while executing the `Request`.
86
+    ///   - completion: Completion closure to be executed when a retry decision has been determined.
87
+    func retry(_ request: Request, for session: Session, dueTo error: Error, completion: @escaping (RetryResult) -> Void)
88
+}
89
+
90
+// MARK: -
91
+
92
+/// Type that provides both `RequestAdapter` and `RequestRetrier` functionality.
93
+public protocol RequestInterceptor: RequestAdapter, RequestRetrier {}
94
+
95
+extension RequestInterceptor {
96
+    public func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
97
+        completion(.success(urlRequest))
98
+    }
99
+
100
+    public func retry(_ request: Request,
101
+                      for session: Session,
102
+                      dueTo error: Error,
103
+                      completion: @escaping (RetryResult) -> Void) {
104
+        completion(.doNotRetry)
105
+    }
106
+}
107
+
108
+/// `RequestAdapter` closure definition.
109
+public typealias AdaptHandler = (URLRequest, Session, _ completion: @escaping (Result<URLRequest, Error>) -> Void) -> Void
110
+/// `RequestRetrier` closure definition.
111
+public typealias RetryHandler = (Request, Session, Error, _ completion: @escaping (RetryResult) -> Void) -> Void
112
+
113
+// MARK: -
114
+
115
+/// Closure-based `RequestAdapter`.
116
+open class Adapter: RequestInterceptor {
117
+    private let adaptHandler: AdaptHandler
118
+
119
+    /// Creates an instance using the provided closure.
120
+    ///
121
+    /// - Parameter adaptHandler: `AdaptHandler` closure to be executed when handling request adaptation.
122
+    public init(_ adaptHandler: @escaping AdaptHandler) {
123
+        self.adaptHandler = adaptHandler
124
+    }
125
+
126
+    open func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
127
+        adaptHandler(urlRequest, session, completion)
128
+    }
129
+}
130
+
131
+// MARK: -
132
+
133
+/// Closure-based `RequestRetrier`.
134
+open class Retrier: RequestInterceptor {
135
+    private let retryHandler: RetryHandler
136
+
137
+    /// Creates an instance using the provided closure.
138
+    ///
139
+    /// - Parameter retryHandler: `RetryHandler` closure to be executed when handling request retry.
140
+    public init(_ retryHandler: @escaping RetryHandler) {
141
+        self.retryHandler = retryHandler
142
+    }
143
+
144
+    open func retry(_ request: Request,
145
+                    for session: Session,
146
+                    dueTo error: Error,
147
+                    completion: @escaping (RetryResult) -> Void) {
148
+        retryHandler(request, session, error, completion)
149
+    }
150
+}
151
+
152
+// MARK: -
153
+
154
+/// `RequestInterceptor` which can use multiple `RequestAdapter` and `RequestRetrier` values.
155
+open class Interceptor: RequestInterceptor {
156
+    /// All `RequestAdapter`s associated with the instance. These adapters will be run until one fails.
157
+    public let adapters: [RequestAdapter]
158
+    /// All `RequestRetrier`s associated with the instance. These retriers will be run one at a time until one triggers retry.
159
+    public let retriers: [RequestRetrier]
160
+
161
+    /// Creates an instance from `AdaptHandler` and `RetryHandler` closures.
162
+    ///
163
+    /// - Parameters:
164
+    ///   - adaptHandler: `AdaptHandler` closure to be used.
165
+    ///   - retryHandler: `RetryHandler` closure to be used.
166
+    public init(adaptHandler: @escaping AdaptHandler, retryHandler: @escaping RetryHandler) {
167
+        adapters = [Adapter(adaptHandler)]
168
+        retriers = [Retrier(retryHandler)]
169
+    }
170
+
171
+    /// Creates an instance from `RequestAdapter` and `RequestRetrier` values.
172
+    ///
173
+    /// - Parameters:
174
+    ///   - adapter: `RequestAdapter` value to be used.
175
+    ///   - retrier: `RequestRetrier` value to be used.
176
+    public init(adapter: RequestAdapter, retrier: RequestRetrier) {
177
+        adapters = [adapter]
178
+        retriers = [retrier]
179
+    }
180
+
181
+    /// Creates an instance from the arrays of `RequestAdapter` and `RequestRetrier` values.
182
+    ///
183
+    /// - Parameters:
184
+    ///   - adapters: `RequestAdapter` values to be used.
185
+    ///   - retriers: `RequestRetrier` values to be used.
186
+    public init(adapters: [RequestAdapter] = [], retriers: [RequestRetrier] = []) {
187
+        self.adapters = adapters
188
+        self.retriers = retriers
189
+    }
190
+
191
+    open func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
192
+        adapt(urlRequest, for: session, using: adapters, completion: completion)
193
+    }
194
+
195
+    private func adapt(_ urlRequest: URLRequest,
196
+                       for session: Session,
197
+                       using adapters: [RequestAdapter],
198
+                       completion: @escaping (Result<URLRequest, Error>) -> Void) {
199
+        var pendingAdapters = adapters
200
+
201
+        guard !pendingAdapters.isEmpty else { completion(.success(urlRequest)); return }
202
+
203
+        let adapter = pendingAdapters.removeFirst()
204
+
205
+        adapter.adapt(urlRequest, for: session) { result in
206
+            switch result {
207
+            case let .success(urlRequest):
208
+                self.adapt(urlRequest, for: session, using: pendingAdapters, completion: completion)
209
+            case .failure:
210
+                completion(result)
211
+            }
212
+        }
213
+    }
214
+
215
+    open func retry(_ request: Request,
216
+                    for session: Session,
217
+                    dueTo error: Error,
218
+                    completion: @escaping (RetryResult) -> Void) {
219
+        retry(request, for: session, dueTo: error, using: retriers, completion: completion)
220
+    }
221
+
222
+    private func retry(_ request: Request,
223
+                       for session: Session,
224
+                       dueTo error: Error,
225
+                       using retriers: [RequestRetrier],
226
+                       completion: @escaping (RetryResult) -> Void) {
227
+        var pendingRetriers = retriers
228
+
229
+        guard !pendingRetriers.isEmpty else { completion(.doNotRetry); return }
230
+
231
+        let retrier = pendingRetriers.removeFirst()
232
+
233
+        retrier.retry(request, for: session, dueTo: error) { result in
234
+            switch result {
235
+            case .retry, .retryWithDelay, .doNotRetryWithError:
236
+                completion(result)
237
+            case .doNotRetry:
238
+                // Only continue to the next retrier if retry was not triggered and no error was encountered
239
+                self.retry(request, for: session, dueTo: error, using: pendingRetriers, completion: completion)
240
+            }
241
+        }
242
+    }
243
+}

+ 136
- 0
trolley/Pods/Alamofire/Source/RequestTaskMap.swift 查看文件

@@ -0,0 +1,136 @@
1
+//
2
+//  RequestTaskMap.swift
3
+//
4
+//  Copyright (c) 2014-2018 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
+/// A type that maintains a two way, one to one map of `URLSessionTask`s to `Request`s.
28
+struct RequestTaskMap {
29
+    private var tasksToRequests: [URLSessionTask: Request]
30
+    private var requestsToTasks: [Request: URLSessionTask]
31
+    private var taskEvents: [URLSessionTask: (completed: Bool, metricsGathered: Bool)]
32
+
33
+    var requests: [Request] {
34
+        return Array(tasksToRequests.values)
35
+    }
36
+
37
+    init(tasksToRequests: [URLSessionTask: Request] = [:],
38
+         requestsToTasks: [Request: URLSessionTask] = [:],
39
+         taskEvents: [URLSessionTask: (completed: Bool, metricsGathered: Bool)] = [:]) {
40
+        self.tasksToRequests = tasksToRequests
41
+        self.requestsToTasks = requestsToTasks
42
+        self.taskEvents = taskEvents
43
+    }
44
+
45
+    subscript(_ request: Request) -> URLSessionTask? {
46
+        get { return requestsToTasks[request] }
47
+        set {
48
+            guard let newValue = newValue else {
49
+                guard let task = requestsToTasks[request] else {
50
+                    fatalError("RequestTaskMap consistency error: no task corresponding to request found.")
51
+                }
52
+
53
+                requestsToTasks.removeValue(forKey: request)
54
+                tasksToRequests.removeValue(forKey: task)
55
+                taskEvents.removeValue(forKey: task)
56
+
57
+                return
58
+            }
59
+
60
+            requestsToTasks[request] = newValue
61
+            tasksToRequests[newValue] = request
62
+            taskEvents[newValue] = (completed: false, metricsGathered: false)
63
+        }
64
+    }
65
+
66
+    subscript(_ task: URLSessionTask) -> Request? {
67
+        get { return tasksToRequests[task] }
68
+        set {
69
+            guard let newValue = newValue else {
70
+                guard let request = tasksToRequests[task] else {
71
+                    fatalError("RequestTaskMap consistency error: no request corresponding to task found.")
72
+                }
73
+
74
+                tasksToRequests.removeValue(forKey: task)
75
+                requestsToTasks.removeValue(forKey: request)
76
+                taskEvents.removeValue(forKey: task)
77
+
78
+                return
79
+            }
80
+
81
+            tasksToRequests[task] = newValue
82
+            requestsToTasks[newValue] = task
83
+            taskEvents[task] = (completed: false, metricsGathered: false)
84
+        }
85
+    }
86
+
87
+    var count: Int {
88
+        precondition(tasksToRequests.count == requestsToTasks.count,
89
+                     "RequestTaskMap.count invalid, requests.count: \(tasksToRequests.count) != tasks.count: \(requestsToTasks.count)")
90
+
91
+        return tasksToRequests.count
92
+    }
93
+
94
+    var eventCount: Int {
95
+        precondition(taskEvents.count == count, "RequestTaskMap.eventCount invalid, count: \(count) != taskEvents.count: \(taskEvents.count)")
96
+
97
+        return taskEvents.count
98
+    }
99
+
100
+    var isEmpty: Bool {
101
+        precondition(tasksToRequests.isEmpty == requestsToTasks.isEmpty,
102
+                     "RequestTaskMap.isEmpty invalid, requests.isEmpty: \(tasksToRequests.isEmpty) != tasks.isEmpty: \(requestsToTasks.isEmpty)")
103
+
104
+        return tasksToRequests.isEmpty
105
+    }
106
+
107
+    var isEventsEmpty: Bool {
108
+        precondition(taskEvents.isEmpty == isEmpty, "RequestTaskMap.isEventsEmpty invalid, isEmpty: \(isEmpty) != taskEvents.isEmpty: \(taskEvents.isEmpty)")
109
+
110
+        return taskEvents.isEmpty
111
+    }
112
+
113
+    mutating func disassociateIfNecessaryAfterGatheringMetricsForTask(_ task: URLSessionTask) {
114
+        guard let events = taskEvents[task] else {
115
+            fatalError("RequestTaskMap consistency error: no events corresponding to task found.")
116
+        }
117
+
118
+        switch (events.completed, events.metricsGathered) {
119
+        case (_, true): fatalError("RequestTaskMap consistency error: duplicate metricsGatheredForTask call.")
120
+        case (false, false): taskEvents[task] = (completed: false, metricsGathered: true)
121
+        case (true, false): self[task] = nil
122
+        }
123
+    }
124
+
125
+    mutating func disassociateIfNecessaryAfterCompletingTask(_ task: URLSessionTask) {
126
+        guard let events = taskEvents[task] else {
127
+            fatalError("RequestTaskMap consistency error: no events corresponding to task found.")
128
+        }
129
+
130
+        switch (events.completed, events.metricsGathered) {
131
+        case (true, _): fatalError("RequestTaskMap consistency error: duplicate completionReceivedForTask call.")
132
+        case (false, false): taskEvents[task] = (completed: true, metricsGathered: false)
133
+        case (false, true): self[task] = nil
134
+        }
135
+    }
136
+}

+ 399
- 0
trolley/Pods/Alamofire/Source/Response.swift 查看文件

@@ -0,0 +1,399 @@
1
+//
2
+//  Response.swift
3
+//
4
+//  Copyright (c) 2014-2018 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
+/// Default type of `DataResponse` returned by Alamofire, with an `AFError` `Failure` type.
28
+public typealias AFDataResponse<Success> = DataResponse<Success, AFError>
29
+/// Default type of `DownloadResponse` returned by Alamofire, with an `AFError` `Failure` type.
30
+public typealias AFDownloadResponse<Success> = DownloadResponse<Success, AFError>
31
+
32
+/// Type used to store all values associated with a serialized response of a `DataRequest` or `UploadRequest`.
33
+public struct DataResponse<Success, Failure: Error> {
34
+    /// The URL request sent to the server.
35
+    public let request: URLRequest?
36
+
37
+    /// The server's response to the URL request.
38
+    public let response: HTTPURLResponse?
39
+
40
+    /// The data returned by the server.
41
+    public let data: Data?
42
+
43
+    /// The final metrics of the response.
44
+    public let metrics: URLSessionTaskMetrics?
45
+
46
+    /// The time taken to serialize the response.
47
+    public let serializationDuration: TimeInterval
48
+
49
+    /// The result of response serialization.
50
+    public let result: Result<Success, Failure>
51
+
52
+    /// Returns the associated value of the result if it is a success, `nil` otherwise.
53
+    public var value: Success? { return result.success }
54
+
55
+    /// Returns the associated error value if the result if it is a failure, `nil` otherwise.
56
+    public var error: Failure? { return result.failure }
57
+
58
+    /// Creates a `DataResponse` instance with the specified parameters derived from the response serialization.
59
+    ///
60
+    /// - Parameters:
61
+    ///   - request:               The `URLRequest` sent to the server.
62
+    ///   - response:              The `HTTPURLResponse` from the server.
63
+    ///   - data:                  The `Data` returned by the server.
64
+    ///   - metrics:               The `URLSessionTaskMetrics` of the `DataRequest` or `UploadRequest`.
65
+    ///   - serializationDuration: The duration taken by serialization.
66
+    ///   - result:                The `Result` of response serialization.
67
+    public init(request: URLRequest?,
68
+                response: HTTPURLResponse?,
69
+                data: Data?,
70
+                metrics: URLSessionTaskMetrics?,
71
+                serializationDuration: TimeInterval,
72
+                result: Result<Success, Failure>) {
73
+        self.request = request
74
+        self.response = response
75
+        self.data = data
76
+        self.metrics = metrics
77
+        self.serializationDuration = serializationDuration
78
+        self.result = result
79
+    }
80
+}
81
+
82
+// MARK: -
83
+
84
+extension DataResponse: CustomStringConvertible, CustomDebugStringConvertible {
85
+    /// The textual representation used when written to an output stream, which includes whether the result was a
86
+    /// success or failure.
87
+    public var description: String {
88
+        return "\(result)"
89
+    }
90
+
91
+    /// The debug textual representation used when written to an output stream, which includes the URL request, the URL
92
+    /// response, the server data, the duration of the network and serialization actions, and the response serialization
93
+    /// result.
94
+    public var debugDescription: String {
95
+        let requestDescription = request.map { "\($0.httpMethod!) \($0)" } ?? "nil"
96
+        let requestBody = request?.httpBody.map { String(decoding: $0, as: UTF8.self) } ?? "None"
97
+        let responseDescription = response.map { response in
98
+            let sortedHeaders = response.headers.sorted()
99
+
100
+            return """
101
+            [Status Code]: \(response.statusCode)
102
+            [Headers]:
103
+            \(sortedHeaders)
104
+            """
105
+        } ?? "nil"
106
+        let responseBody = data.map { String(decoding: $0, as: UTF8.self) } ?? "None"
107
+        let metricsDescription = metrics.map { "\($0.taskInterval.duration)s" } ?? "None"
108
+
109
+        return """
110
+        [Request]: \(requestDescription)
111
+        [Request Body]: \n\(requestBody)
112
+        [Response]: \n\(responseDescription)
113
+        [Response Body]: \n\(responseBody)
114
+        [Data]: \(data?.description ?? "None")
115
+        [Network Duration]: \(metricsDescription)
116
+        [Serialization Duration]: \(serializationDuration)s
117
+        [Result]: \(result)
118
+        """
119
+    }
120
+}
121
+
122
+// MARK: -
123
+
124
+extension DataResponse {
125
+    /// Evaluates the specified closure when the result of this `DataResponse` is a success, passing the unwrapped
126
+    /// result value as a parameter.
127
+    ///
128
+    /// Use the `map` method with a closure that does not throw. For example:
129
+    ///
130
+    ///     let possibleData: DataResponse<Data> = ...
131
+    ///     let possibleInt = possibleData.map { $0.count }
132
+    ///
133
+    /// - parameter transform: A closure that takes the success value of the instance's result.
134
+    ///
135
+    /// - returns: A `DataResponse` whose result wraps the value returned by the given closure. If this instance's
136
+    ///            result is a failure, returns a response wrapping the same failure.
137
+    public func map<NewSuccess>(_ transform: (Success) -> NewSuccess) -> DataResponse<NewSuccess, Failure> {
138
+        return DataResponse<NewSuccess, Failure>(request: request,
139
+                                                 response: response,
140
+                                                 data: data,
141
+                                                 metrics: metrics,
142
+                                                 serializationDuration: serializationDuration,
143
+                                                 result: result.map(transform))
144
+    }
145
+
146
+    /// Evaluates the given closure when the result of this `DataResponse` is a success, passing the unwrapped result
147
+    /// value as a parameter.
148
+    ///
149
+    /// Use the `tryMap` method with a closure that may throw an error. For example:
150
+    ///
151
+    ///     let possibleData: DataResponse<Data> = ...
152
+    ///     let possibleObject = possibleData.tryMap {
153
+    ///         try JSONSerialization.jsonObject(with: $0)
154
+    ///     }
155
+    ///
156
+    /// - parameter transform: A closure that takes the success value of the instance's result.
157
+    ///
158
+    /// - returns: A success or failure `DataResponse` depending on the result of the given closure. If this instance's
159
+    ///            result is a failure, returns the same failure.
160
+    public func tryMap<NewSuccess>(_ transform: (Success) throws -> NewSuccess) -> DataResponse<NewSuccess, Error> {
161
+        return DataResponse<NewSuccess, Error>(request: request,
162
+                                               response: response,
163
+                                               data: data,
164
+                                               metrics: metrics,
165
+                                               serializationDuration: serializationDuration,
166
+                                               result: result.tryMap(transform))
167
+    }
168
+
169
+    /// Evaluates the specified closure when the `DataResponse` is a failure, passing the unwrapped error as a parameter.
170
+    ///
171
+    /// Use the `mapError` function with a closure that does not throw. For example:
172
+    ///
173
+    ///     let possibleData: DataResponse<Data> = ...
174
+    ///     let withMyError = possibleData.mapError { MyError.error($0) }
175
+    ///
176
+    /// - Parameter transform: A closure that takes the error of the instance.
177
+    ///
178
+    /// - Returns: A `DataResponse` instance containing the result of the transform.
179
+    public func mapError<NewFailure: Error>(_ transform: (Failure) -> NewFailure) -> DataResponse<Success, NewFailure> {
180
+        return DataResponse<Success, NewFailure>(request: request,
181
+                                                 response: response,
182
+                                                 data: data,
183
+                                                 metrics: metrics,
184
+                                                 serializationDuration: serializationDuration,
185
+                                                 result: result.mapError(transform))
186
+    }
187
+
188
+    /// Evaluates the specified closure when the `DataResponse` is a failure, passing the unwrapped error as a parameter.
189
+    ///
190
+    /// Use the `tryMapError` function with a closure that may throw an error. For example:
191
+    ///
192
+    ///     let possibleData: DataResponse<Data> = ...
193
+    ///     let possibleObject = possibleData.tryMapError {
194
+    ///         try someFailableFunction(taking: $0)
195
+    ///     }
196
+    ///
197
+    /// - Parameter transform: A throwing closure that takes the error of the instance.
198
+    ///
199
+    /// - Returns: A `DataResponse` instance containing the result of the transform.
200
+    public func tryMapError<NewFailure: Error>(_ transform: (Failure) throws -> NewFailure) -> DataResponse<Success, Error> {
201
+        return DataResponse<Success, Error>(request: request,
202
+                                            response: response,
203
+                                            data: data,
204
+                                            metrics: metrics,
205
+                                            serializationDuration: serializationDuration,
206
+                                            result: result.tryMapError(transform))
207
+    }
208
+}
209
+
210
+// MARK: -
211
+
212
+/// Used to store all data associated with a serialized response of a download request.
213
+public struct DownloadResponse<Success, Failure: Error> {
214
+    /// The URL request sent to the server.
215
+    public let request: URLRequest?
216
+
217
+    /// The server's response to the URL request.
218
+    public let response: HTTPURLResponse?
219
+
220
+    /// The final destination URL of the data returned from the server after it is moved.
221
+    public let fileURL: URL?
222
+
223
+    /// The resume data generated if the request was cancelled.
224
+    public let resumeData: Data?
225
+
226
+    /// The final metrics of the response.
227
+    public let metrics: URLSessionTaskMetrics?
228
+
229
+    /// The time taken to serialize the response.
230
+    public let serializationDuration: TimeInterval
231
+
232
+    /// The result of response serialization.
233
+    public let result: Result<Success, Failure>
234
+
235
+    /// Returns the associated value of the result if it is a success, `nil` otherwise.
236
+    public var value: Success? { return result.success }
237
+
238
+    /// Returns the associated error value if the result if it is a failure, `nil` otherwise.
239
+    public var error: Failure? { return result.failure }
240
+
241
+    /// Creates a `DownloadResponse` instance with the specified parameters derived from response serialization.
242
+    ///
243
+    /// - Parameters:
244
+    ///   - request:               The `URLRequest` sent to the server.
245
+    ///   - response:              The `HTTPURLResponse` from the server.
246
+    ///   - temporaryURL:          The temporary destination `URL` of the data returned from the server.
247
+    ///   - destinationURL:        The final destination `URL` of the data returned from the server, if it was moved.
248
+    ///   - resumeData:            The resume `Data` generated if the request was cancelled.
249
+    ///   - metrics:               The `URLSessionTaskMetrics` of the `DownloadRequest`.
250
+    ///   - serializationDuration: The duration taken by serialization.
251
+    ///   - result:                The `Result` of response serialization.
252
+    public init(request: URLRequest?,
253
+                response: HTTPURLResponse?,
254
+                fileURL: URL?,
255
+                resumeData: Data?,
256
+                metrics: URLSessionTaskMetrics?,
257
+                serializationDuration: TimeInterval,
258
+                result: Result<Success, Failure>) {
259
+        self.request = request
260
+        self.response = response
261
+        self.fileURL = fileURL
262
+        self.resumeData = resumeData
263
+        self.metrics = metrics
264
+        self.serializationDuration = serializationDuration
265
+        self.result = result
266
+    }
267
+}
268
+
269
+// MARK: -
270
+
271
+extension DownloadResponse: CustomStringConvertible, CustomDebugStringConvertible {
272
+    /// The textual representation used when written to an output stream, which includes whether the result was a
273
+    /// success or failure.
274
+    public var description: String {
275
+        return "\(result)"
276
+    }
277
+
278
+    /// The debug textual representation used when written to an output stream, which includes the URL request, the URL
279
+    /// response, the temporary and destination URLs, the resume data, the durations of the network and serialization
280
+    /// actions, and the response serialization result.
281
+    public var debugDescription: String {
282
+        let requestDescription = request.map { "\($0.httpMethod!) \($0)" } ?? "nil"
283
+        let requestBody = request?.httpBody.map { String(decoding: $0, as: UTF8.self) } ?? "None"
284
+        let responseDescription = response.map { response in
285
+            let sortedHeaders = response.headers.sorted()
286
+
287
+            return """
288
+            [Status Code]: \(response.statusCode)
289
+            [Headers]:
290
+            \(sortedHeaders)
291
+            """
292
+        } ?? "nil"
293
+        let metricsDescription = metrics.map { "\($0.taskInterval.duration)s" } ?? "None"
294
+        let resumeDataDescription = resumeData.map { "\($0)" } ?? "None"
295
+
296
+        return """
297
+        [Request]: \(requestDescription)
298
+        [Request Body]: \n\(requestBody)
299
+        [Response]: \n\(responseDescription)
300
+        [File URL]: \(fileURL?.path ?? "nil")
301
+        [ResumeData]: \(resumeDataDescription)
302
+        [Network Duration]: \(metricsDescription)
303
+        [Serialization Duration]: \(serializationDuration)s
304
+        [Result]: \(result)
305
+        """
306
+    }
307
+}
308
+
309
+// MARK: -
310
+
311
+extension DownloadResponse {
312
+    /// Evaluates the given closure when the result of this `DownloadResponse` is a success, passing the unwrapped
313
+    /// result value as a parameter.
314
+    ///
315
+    /// Use the `map` method with a closure that does not throw. For example:
316
+    ///
317
+    ///     let possibleData: DownloadResponse<Data> = ...
318
+    ///     let possibleInt = possibleData.map { $0.count }
319
+    ///
320
+    /// - parameter transform: A closure that takes the success value of the instance's result.
321
+    ///
322
+    /// - returns: A `DownloadResponse` whose result wraps the value returned by the given closure. If this instance's
323
+    ///            result is a failure, returns a response wrapping the same failure.
324
+    public func map<NewSuccess>(_ transform: (Success) -> NewSuccess) -> DownloadResponse<NewSuccess, Failure> {
325
+        return DownloadResponse<NewSuccess, Failure>(request: request,
326
+                                                     response: response,
327
+                                                     fileURL: fileURL,
328
+                                                     resumeData: resumeData,
329
+                                                     metrics: metrics,
330
+                                                     serializationDuration: serializationDuration,
331
+                                                     result: result.map(transform))
332
+    }
333
+
334
+    /// Evaluates the given closure when the result of this `DownloadResponse` is a success, passing the unwrapped
335
+    /// result value as a parameter.
336
+    ///
337
+    /// Use the `tryMap` method with a closure that may throw an error. For example:
338
+    ///
339
+    ///     let possibleData: DownloadResponse<Data> = ...
340
+    ///     let possibleObject = possibleData.tryMap {
341
+    ///         try JSONSerialization.jsonObject(with: $0)
342
+    ///     }
343
+    ///
344
+    /// - parameter transform: A closure that takes the success value of the instance's result.
345
+    ///
346
+    /// - returns: A success or failure `DownloadResponse` depending on the result of the given closure. If this
347
+    /// instance's result is a failure, returns the same failure.
348
+    public func tryMap<NewSuccess>(_ transform: (Success) throws -> NewSuccess) -> DownloadResponse<NewSuccess, Error> {
349
+        return DownloadResponse<NewSuccess, Error>(request: request,
350
+                                                   response: response,
351
+                                                   fileURL: fileURL,
352
+                                                   resumeData: resumeData,
353
+                                                   metrics: metrics,
354
+                                                   serializationDuration: serializationDuration,
355
+                                                   result: result.tryMap(transform))
356
+    }
357
+
358
+    /// Evaluates the specified closure when the `DownloadResponse` is a failure, passing the unwrapped error as a parameter.
359
+    ///
360
+    /// Use the `mapError` function with a closure that does not throw. For example:
361
+    ///
362
+    ///     let possibleData: DownloadResponse<Data> = ...
363
+    ///     let withMyError = possibleData.mapError { MyError.error($0) }
364
+    ///
365
+    /// - Parameter transform: A closure that takes the error of the instance.
366
+    ///
367
+    /// - Returns: A `DownloadResponse` instance containing the result of the transform.
368
+    public func mapError<NewFailure: Error>(_ transform: (Failure) -> NewFailure) -> DownloadResponse<Success, NewFailure> {
369
+        return DownloadResponse<Success, NewFailure>(request: request,
370
+                                                     response: response,
371
+                                                     fileURL: fileURL,
372
+                                                     resumeData: resumeData,
373
+                                                     metrics: metrics,
374
+                                                     serializationDuration: serializationDuration,
375
+                                                     result: result.mapError(transform))
376
+    }
377
+
378
+    /// Evaluates the specified closure when the `DownloadResponse` is a failure, passing the unwrapped error as a parameter.
379
+    ///
380
+    /// Use the `tryMapError` function with a closure that may throw an error. For example:
381
+    ///
382
+    ///     let possibleData: DownloadResponse<Data> = ...
383
+    ///     let possibleObject = possibleData.tryMapError {
384
+    ///         try someFailableFunction(taking: $0)
385
+    ///     }
386
+    ///
387
+    /// - Parameter transform: A throwing closure that takes the error of the instance.
388
+    ///
389
+    /// - Returns: A `DownloadResponse` instance containing the result of the transform.
390
+    public func tryMapError<NewFailure: Error>(_ transform: (Failure) throws -> NewFailure) -> DownloadResponse<Success, Error> {
391
+        return DownloadResponse<Success, Error>(request: request,
392
+                                                response: response,
393
+                                                fileURL: fileURL,
394
+                                                resumeData: resumeData,
395
+                                                metrics: metrics,
396
+                                                serializationDuration: serializationDuration,
397
+                                                result: result.tryMapError(transform))
398
+    }
399
+}

+ 779
- 0
trolley/Pods/Alamofire/Source/ResponseSerialization.swift 查看文件

@@ -0,0 +1,779 @@
1
+//
2
+//  ResponseSerialization.swift
3
+//
4
+//  Copyright (c) 2014-2018 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: Protocols
28
+
29
+/// The type to which all data response serializers must conform in order to serialize a response.
30
+public protocol DataResponseSerializerProtocol {
31
+    /// The type of serialized object to be created.
32
+    associatedtype SerializedObject
33
+
34
+    /// Serialize the response `Data` into the provided type..
35
+    ///
36
+    /// - Parameters:
37
+    ///   - request:  `URLRequest` which was used to perform the request, if any.
38
+    ///   - response: `HTTPURLResponse` received from the server, if any.
39
+    ///   - data:     `Data` returned from the server, if any.
40
+    ///   - error:    `Error` produced by Alamofire or the underlying `URLSession` during the request.
41
+    ///
42
+    /// - Returns:    The `SerializedObject`.
43
+    /// - Throws:     Any `Error` produced during serialization.
44
+    func serialize(request: URLRequest?, response: HTTPURLResponse?, data: Data?, error: Error?) throws -> SerializedObject
45
+}
46
+
47
+/// The type to which all download response serializers must conform in order to serialize a response.
48
+public protocol DownloadResponseSerializerProtocol {
49
+    /// The type of serialized object to be created.
50
+    associatedtype SerializedObject
51
+
52
+    /// Serialize the downloaded response `Data` from disk into the provided type..
53
+    ///
54
+    /// - Parameters:
55
+    ///   - request:  `URLRequest` which was used to perform the request, if any.
56
+    ///   - response: `HTTPURLResponse` received from the server, if any.
57
+    ///   - fileURL:  File `URL` to which the response data was downloaded.
58
+    ///   - error:    `Error` produced by Alamofire or the underlying `URLSession` during the request.
59
+    ///
60
+    /// - Returns:    The `SerializedObject`.
61
+    /// - Throws:     Any `Error` produced during serialization.
62
+    func serializeDownload(request: URLRequest?, response: HTTPURLResponse?, fileURL: URL?, error: Error?) throws -> SerializedObject
63
+}
64
+
65
+/// A serializer that can handle both data and download responses.
66
+public protocol ResponseSerializer: DataResponseSerializerProtocol & DownloadResponseSerializerProtocol {
67
+    /// `DataPreprocessor` used to prepare incoming `Data` for serialization.
68
+    var dataPreprocessor: DataPreprocessor { get }
69
+    /// `HTTPMethod`s for which empty response bodies are considered appropriate.
70
+    var emptyRequestMethods: Set<HTTPMethod> { get }
71
+    /// HTTP response codes for which empty response bodies are considered appropriate.
72
+    var emptyResponseCodes: Set<Int> { get }
73
+}
74
+
75
+/// Type used to preprocess `Data` before it handled by a serializer.
76
+public protocol DataPreprocessor {
77
+    /// Process           `Data` before it's handled by a serializer.
78
+    /// - Parameter data: The raw `Data` to process.
79
+    func preprocess(_ data: Data) throws -> Data
80
+}
81
+
82
+/// `DataPreprocessor` that returns passed `Data` without any transform.
83
+public struct PassthroughPreprocessor: DataPreprocessor {
84
+    public init() {}
85
+
86
+    public func preprocess(_ data: Data) throws -> Data { return data }
87
+}
88
+
89
+/// `DataPreprocessor` that trims Google's typical `)]}',\n` XSSI JSON header.
90
+public struct GoogleXSSIPreprocessor: DataPreprocessor {
91
+    public init() {}
92
+
93
+    public func preprocess(_ data: Data) throws -> Data {
94
+        return (data.prefix(6) == Data(")]}',\n".utf8)) ? data.dropFirst(6) : data
95
+    }
96
+}
97
+
98
+extension ResponseSerializer {
99
+    /// Default `DataPreprocessor`. `PassthroughPreprocessor` by default.
100
+    public static var defaultDataPreprocessor: DataPreprocessor { return PassthroughPreprocessor() }
101
+    /// Default `HTTPMethod`s for which empty response bodies are considered appropriate. `[.head]` by default.
102
+    public static var defaultEmptyRequestMethods: Set<HTTPMethod> { return [.head] }
103
+    /// HTTP response codes for which empty response bodies are considered appropriate. `[204, 205]` by default.
104
+    public static var defaultEmptyResponseCodes: Set<Int> { return [204, 205] }
105
+
106
+    public var dataPreprocessor: DataPreprocessor { return Self.defaultDataPreprocessor }
107
+    public var emptyRequestMethods: Set<HTTPMethod> { return Self.defaultEmptyRequestMethods }
108
+    public var emptyResponseCodes: Set<Int> { return Self.defaultEmptyResponseCodes }
109
+
110
+    /// Determines whether the `request` allows empty response bodies, if `request` exists.
111
+    ///
112
+    /// - Parameter request: `URLRequest` to evaluate.
113
+    ///
114
+    /// - Returns:           `Bool` representing the outcome of the evaluation, or `nil` if `request` was `nil`.
115
+    public func requestAllowsEmptyResponseData(_ request: URLRequest?) -> Bool? {
116
+        return request.flatMap { $0.httpMethod }
117
+            .flatMap(HTTPMethod.init)
118
+            .map { emptyRequestMethods.contains($0) }
119
+    }
120
+
121
+    /// Determines whether the `response` allows empty response bodies, if `response` exists`.
122
+    ///
123
+    /// - Parameter response: `HTTPURLResponse` to evaluate.
124
+    ///
125
+    /// - Returns:            `Bool` representing the outcome of the evaluation, or `nil` if `response` was `nil`.
126
+    public func responseAllowsEmptyResponseData(_ response: HTTPURLResponse?) -> Bool? {
127
+        return response.flatMap { $0.statusCode }
128
+            .map { emptyResponseCodes.contains($0) }
129
+    }
130
+
131
+    /// Determines whether `request` and `response` allow empty response bodies.
132
+    ///
133
+    /// - Parameters:
134
+    ///   - request:  `URLRequest` to evaluate.
135
+    ///   - response: `HTTPURLResponse` to evaluate.
136
+    ///
137
+    /// - Returns:    `true` if `request` or `response` allow empty bodies, `false` otherwise.
138
+    public func emptyResponseAllowed(forRequest request: URLRequest?, response: HTTPURLResponse?) -> Bool {
139
+        return (requestAllowsEmptyResponseData(request) == true) || (responseAllowsEmptyResponseData(response) == true)
140
+    }
141
+}
142
+
143
+/// By default, any serializer declared to conform to both types will get file serialization for free, as it just feeds
144
+/// the data read from disk into the data response serializer.
145
+public extension DownloadResponseSerializerProtocol where Self: DataResponseSerializerProtocol {
146
+    func serializeDownload(request: URLRequest?, response: HTTPURLResponse?, fileURL: URL?, error: Error?) throws -> Self.SerializedObject {
147
+        guard error == nil else { throw error! }
148
+
149
+        guard let fileURL = fileURL else {
150
+            throw AFError.responseSerializationFailed(reason: .inputFileNil)
151
+        }
152
+
153
+        let data: Data
154
+        do {
155
+            data = try Data(contentsOf: fileURL)
156
+        } catch {
157
+            throw AFError.responseSerializationFailed(reason: .inputFileReadFailed(at: fileURL))
158
+        }
159
+
160
+        do {
161
+            return try serialize(request: request, response: response, data: data, error: error)
162
+        } catch {
163
+            throw error
164
+        }
165
+    }
166
+}
167
+
168
+// MARK: - Default
169
+
170
+extension DataRequest {
171
+    /// Adds a handler to be called once the request has finished.
172
+    ///
173
+    /// - Parameters:
174
+    ///   - queue:             The queue on which the completion handler is dispatched. `.main` by default.
175
+    ///   - completionHandler: The code to be executed once the request has finished.
176
+    ///
177
+    /// - Returns:             The request.
178
+    @discardableResult
179
+    public func response(queue: DispatchQueue = .main, completionHandler: @escaping (AFDataResponse<Data?>) -> Void) -> Self {
180
+        appendResponseSerializer {
181
+            // Start work that should be on the serialization queue.
182
+            let result = AFResult<Data?>(value: self.data, error: self.error)
183
+            // End work that should be on the serialization queue.
184
+
185
+            self.underlyingQueue.async {
186
+                let response = DataResponse(request: self.request,
187
+                                            response: self.response,
188
+                                            data: self.data,
189
+                                            metrics: self.metrics,
190
+                                            serializationDuration: 0,
191
+                                            result: result)
192
+
193
+                self.eventMonitor?.request(self, didParseResponse: response)
194
+
195
+                self.responseSerializerDidComplete { queue.async { completionHandler(response) } }
196
+            }
197
+        }
198
+
199
+        return self
200
+    }
201
+
202
+    /// Adds a handler to be called once the request has finished.
203
+    ///
204
+    /// - Parameters:
205
+    ///   - queue:              The queue on which the completion handler is dispatched. `.main` by default
206
+    ///   - responseSerializer: The response serializer responsible for serializing the request, response, and data.
207
+    ///   - completionHandler:  The code to be executed once the request has finished.
208
+    ///
209
+    /// - Returns:              The request.
210
+    @discardableResult
211
+    public func response<Serializer: DataResponseSerializerProtocol>(queue: DispatchQueue = .main,
212
+                                                                     responseSerializer: Serializer,
213
+                                                                     completionHandler: @escaping (AFDataResponse<Serializer.SerializedObject>) -> Void)
214
+        -> Self {
215
+        appendResponseSerializer {
216
+            // Start work that should be on the serialization queue.
217
+            let start = CFAbsoluteTimeGetCurrent()
218
+            let result: AFResult<Serializer.SerializedObject> = Result {
219
+                try responseSerializer.serialize(request: self.request,
220
+                                                 response: self.response,
221
+                                                 data: self.data,
222
+                                                 error: self.error)
223
+            }.mapError { error in
224
+                error.asAFError(or: .responseSerializationFailed(reason: .customSerializationFailed(error: error)))
225
+            }
226
+
227
+            let end = CFAbsoluteTimeGetCurrent()
228
+            // End work that should be on the serialization queue.
229
+
230
+            self.underlyingQueue.async {
231
+                let response = DataResponse(request: self.request,
232
+                                            response: self.response,
233
+                                            data: self.data,
234
+                                            metrics: self.metrics,
235
+                                            serializationDuration: end - start,
236
+                                            result: result)
237
+
238
+                self.eventMonitor?.request(self, didParseResponse: response)
239
+
240
+                guard let serializerError = result.failure, let delegate = self.delegate else {
241
+                    self.responseSerializerDidComplete { queue.async { completionHandler(response) } }
242
+                    return
243
+                }
244
+
245
+                delegate.retryResult(for: self, dueTo: serializerError) { retryResult in
246
+                    var didComplete: (() -> Void)?
247
+
248
+                    defer {
249
+                        if let didComplete = didComplete {
250
+                            self.responseSerializerDidComplete { queue.async { didComplete() } }
251
+                        }
252
+                    }
253
+
254
+                    switch retryResult {
255
+                    case .doNotRetry:
256
+                        didComplete = { completionHandler(response) }
257
+
258
+                    case let .doNotRetryWithError(retryError):
259
+                        let result: AFResult<Serializer.SerializedObject> = .failure(retryError.asAFError(orFailWith: "Received retryError was not already AFError"))
260
+
261
+                        let response = DataResponse(request: self.request,
262
+                                                    response: self.response,
263
+                                                    data: self.data,
264
+                                                    metrics: self.metrics,
265
+                                                    serializationDuration: end - start,
266
+                                                    result: result)
267
+
268
+                        didComplete = { completionHandler(response) }
269
+
270
+                    case .retry, .retryWithDelay:
271
+                        delegate.retryRequest(self, withDelay: retryResult.delay)
272
+                    }
273
+                }
274
+            }
275
+        }
276
+
277
+        return self
278
+    }
279
+}
280
+
281
+extension DownloadRequest {
282
+    /// Adds a handler to be called once the request has finished.
283
+    ///
284
+    /// - Parameters:
285
+    ///   - queue:             The queue on which the completion handler is dispatched. `.main` by default.
286
+    ///   - completionHandler: The code to be executed once the request has finished.
287
+    ///
288
+    /// - Returns:             The request.
289
+    @discardableResult
290
+    public func response(queue: DispatchQueue = .main,
291
+                         completionHandler: @escaping (AFDownloadResponse<URL?>) -> Void)
292
+        -> Self {
293
+        appendResponseSerializer {
294
+            // Start work that should be on the serialization queue.
295
+            let result = AFResult<URL?>(value: self.fileURL, error: self.error)
296
+            // End work that should be on the serialization queue.
297
+
298
+            self.underlyingQueue.async {
299
+                let response = DownloadResponse(request: self.request,
300
+                                                response: self.response,
301
+                                                fileURL: self.fileURL,
302
+                                                resumeData: self.resumeData,
303
+                                                metrics: self.metrics,
304
+                                                serializationDuration: 0,
305
+                                                result: result)
306
+
307
+                self.eventMonitor?.request(self, didParseResponse: response)
308
+
309
+                self.responseSerializerDidComplete { queue.async { completionHandler(response) } }
310
+            }
311
+        }
312
+
313
+        return self
314
+    }
315
+
316
+    /// Adds a handler to be called once the request has finished.
317
+    ///
318
+    /// - Parameters:
319
+    ///   - queue:              The queue on which the completion handler is dispatched. `.main` by default.
320
+    ///   - responseSerializer: The response serializer responsible for serializing the request, response, and data
321
+    ///                         contained in the destination `URL`.
322
+    ///   - completionHandler:  The code to be executed once the request has finished.
323
+    ///
324
+    /// - Returns:              The request.
325
+    @discardableResult
326
+    public func response<T: DownloadResponseSerializerProtocol>(queue: DispatchQueue = .main,
327
+                                                                responseSerializer: T,
328
+                                                                completionHandler: @escaping (AFDownloadResponse<T.SerializedObject>) -> Void)
329
+        -> Self {
330
+        appendResponseSerializer {
331
+            // Start work that should be on the serialization queue.
332
+            let start = CFAbsoluteTimeGetCurrent()
333
+            let result: AFResult<T.SerializedObject> = Result {
334
+                try responseSerializer.serializeDownload(request: self.request,
335
+                                                         response: self.response,
336
+                                                         fileURL: self.fileURL,
337
+                                                         error: self.error)
338
+            }.mapError { error in
339
+                error.asAFError(or: .responseSerializationFailed(reason: .customSerializationFailed(error: error)))
340
+            }
341
+            let end = CFAbsoluteTimeGetCurrent()
342
+            // End work that should be on the serialization queue.
343
+
344
+            self.underlyingQueue.async {
345
+                let response = DownloadResponse(request: self.request,
346
+                                                response: self.response,
347
+                                                fileURL: self.fileURL,
348
+                                                resumeData: self.resumeData,
349
+                                                metrics: self.metrics,
350
+                                                serializationDuration: end - start,
351
+                                                result: result)
352
+
353
+                self.eventMonitor?.request(self, didParseResponse: response)
354
+
355
+                guard let serializerError = result.failure, let delegate = self.delegate else {
356
+                    self.responseSerializerDidComplete { queue.async { completionHandler(response) } }
357
+                    return
358
+                }
359
+
360
+                delegate.retryResult(for: self, dueTo: serializerError) { retryResult in
361
+                    var didComplete: (() -> Void)?
362
+
363
+                    defer {
364
+                        if let didComplete = didComplete {
365
+                            self.responseSerializerDidComplete { queue.async { didComplete() } }
366
+                        }
367
+                    }
368
+
369
+                    switch retryResult {
370
+                    case .doNotRetry:
371
+                        didComplete = { completionHandler(response) }
372
+
373
+                    case let .doNotRetryWithError(retryError):
374
+                        let result: AFResult<T.SerializedObject> = .failure(retryError.asAFError(orFailWith: "Received retryError was not already AFError"))
375
+
376
+                        let response = DownloadResponse(request: self.request,
377
+                                                        response: self.response,
378
+                                                        fileURL: self.fileURL,
379
+                                                        resumeData: self.resumeData,
380
+                                                        metrics: self.metrics,
381
+                                                        serializationDuration: end - start,
382
+                                                        result: result)
383
+
384
+                        didComplete = { completionHandler(response) }
385
+
386
+                    case .retry, .retryWithDelay:
387
+                        delegate.retryRequest(self, withDelay: retryResult.delay)
388
+                    }
389
+                }
390
+            }
391
+        }
392
+
393
+        return self
394
+    }
395
+}
396
+
397
+// MARK: - Data
398
+
399
+extension DataRequest {
400
+    /// Adds a handler to be called once the request has finished.
401
+    ///
402
+    /// - Parameters:
403
+    ///   - queue:             The queue on which the completion handler is dispatched. `.main` by default.
404
+    ///   - completionHandler: The code to be executed once the request has finished.
405
+    ///
406
+    /// - Returns:             The request.
407
+    @discardableResult
408
+    public func responseData(queue: DispatchQueue = .main,
409
+                             completionHandler: @escaping (AFDataResponse<Data>) -> Void)
410
+        -> Self {
411
+        return response(queue: queue,
412
+                        responseSerializer: DataResponseSerializer(),
413
+                        completionHandler: completionHandler)
414
+    }
415
+}
416
+
417
+/// A `ResponseSerializer` that performs minimal response checking and returns any response data as-is. By default, a
418
+/// request returning `nil` or no data is considered an error. However, if the response is has a status code valid for
419
+/// empty responses (`204`, `205`), then an empty `Data` value is returned.
420
+public final class DataResponseSerializer: ResponseSerializer {
421
+    public let dataPreprocessor: DataPreprocessor
422
+    public let emptyResponseCodes: Set<Int>
423
+    public let emptyRequestMethods: Set<HTTPMethod>
424
+
425
+    /// Creates an instance using the provided values.
426
+    ///
427
+    /// - Parameters:
428
+    ///   - dataPreprocessor:    `DataPreprocessor` used to prepare the received `Data` for serialization.
429
+    ///   - emptyResponseCodes:  The HTTP response codes for which empty responses are allowed. `[204, 205]` by default.
430
+    ///   - emptyRequestMethods: The HTTP request methods for which empty responses are allowed. `[.head]` by default.
431
+    public init(dataPreprocessor: DataPreprocessor = DataResponseSerializer.defaultDataPreprocessor,
432
+                emptyResponseCodes: Set<Int> = DataResponseSerializer.defaultEmptyResponseCodes,
433
+                emptyRequestMethods: Set<HTTPMethod> = DataResponseSerializer.defaultEmptyRequestMethods) {
434
+        self.dataPreprocessor = dataPreprocessor
435
+        self.emptyResponseCodes = emptyResponseCodes
436
+        self.emptyRequestMethods = emptyRequestMethods
437
+    }
438
+
439
+    public func serialize(request: URLRequest?, response: HTTPURLResponse?, data: Data?, error: Error?) throws -> Data {
440
+        guard error == nil else { throw error! }
441
+
442
+        guard var data = data, !data.isEmpty else {
443
+            guard emptyResponseAllowed(forRequest: request, response: response) else {
444
+                throw AFError.responseSerializationFailed(reason: .inputDataNilOrZeroLength)
445
+            }
446
+
447
+            return Data()
448
+        }
449
+
450
+        data = try dataPreprocessor.preprocess(data)
451
+
452
+        return data
453
+    }
454
+}
455
+
456
+extension DownloadRequest {
457
+    /// Adds a handler to be called once the request has finished.
458
+    ///
459
+    /// - Parameters:
460
+    ///   - queue:             The queue on which the completion handler is dispatched. `.main` by default.
461
+    ///   - completionHandler: The code to be executed once the request has finished.
462
+    ///
463
+    /// - Returns:             The request.
464
+    @discardableResult
465
+    public func responseData(queue: DispatchQueue = .main,
466
+                             completionHandler: @escaping (AFDownloadResponse<Data>) -> Void)
467
+        -> Self {
468
+        return response(queue: queue,
469
+                        responseSerializer: DataResponseSerializer(),
470
+                        completionHandler: completionHandler)
471
+    }
472
+}
473
+
474
+// MARK: - String
475
+
476
+/// A `ResponseSerializer` that decodes the response data as a `String`. By default, a request returning `nil` or no
477
+/// data is considered an error. However, if the response is has a status code valid for empty responses (`204`, `205`),
478
+/// then an empty `String` is returned.
479
+public final class StringResponseSerializer: ResponseSerializer {
480
+    public let dataPreprocessor: DataPreprocessor
481
+    /// Optional string encoding used to validate the response.
482
+    public let encoding: String.Encoding?
483
+    public let emptyResponseCodes: Set<Int>
484
+    public let emptyRequestMethods: Set<HTTPMethod>
485
+
486
+    /// Creates an instance with the provided values.
487
+    ///
488
+    /// - Parameters:
489
+    ///   - dataPreprocessor:    `DataPreprocessor` used to prepare the received `Data` for serialization.
490
+    ///   - encoding:            A string encoding. Defaults to `nil`, in which case the encoding will be determined
491
+    ///                          from the server response, falling back to the default HTTP character set, `ISO-8859-1`.
492
+    ///   - emptyResponseCodes:  The HTTP response codes for which empty responses are allowed. `[204, 205]` by default.
493
+    ///   - emptyRequestMethods: The HTTP request methods for which empty responses are allowed. `[.head]` by default.
494
+    public init(dataPreprocessor: DataPreprocessor = StringResponseSerializer.defaultDataPreprocessor,
495
+                encoding: String.Encoding? = nil,
496
+                emptyResponseCodes: Set<Int> = StringResponseSerializer.defaultEmptyResponseCodes,
497
+                emptyRequestMethods: Set<HTTPMethod> = StringResponseSerializer.defaultEmptyRequestMethods) {
498
+        self.dataPreprocessor = dataPreprocessor
499
+        self.encoding = encoding
500
+        self.emptyResponseCodes = emptyResponseCodes
501
+        self.emptyRequestMethods = emptyRequestMethods
502
+    }
503
+
504
+    public func serialize(request: URLRequest?, response: HTTPURLResponse?, data: Data?, error: Error?) throws -> String {
505
+        guard error == nil else { throw error! }
506
+
507
+        guard var data = data, !data.isEmpty else {
508
+            guard emptyResponseAllowed(forRequest: request, response: response) else {
509
+                throw AFError.responseSerializationFailed(reason: .inputDataNilOrZeroLength)
510
+            }
511
+
512
+            return ""
513
+        }
514
+
515
+        data = try dataPreprocessor.preprocess(data)
516
+
517
+        var convertedEncoding = encoding
518
+
519
+        if let encodingName = response?.textEncodingName as CFString?, convertedEncoding == nil {
520
+            let ianaCharSet = CFStringConvertIANACharSetNameToEncoding(encodingName)
521
+            let nsStringEncoding = CFStringConvertEncodingToNSStringEncoding(ianaCharSet)
522
+            convertedEncoding = String.Encoding(rawValue: nsStringEncoding)
523
+        }
524
+
525
+        let actualEncoding = convertedEncoding ?? .isoLatin1
526
+
527
+        guard let string = String(data: data, encoding: actualEncoding) else {
528
+            throw AFError.responseSerializationFailed(reason: .stringSerializationFailed(encoding: actualEncoding))
529
+        }
530
+
531
+        return string
532
+    }
533
+}
534
+
535
+extension DataRequest {
536
+    /// Adds a handler to be called once the request has finished.
537
+    ///
538
+    /// - Parameters:
539
+    ///   - queue:             The queue on which the completion handler is dispatched. `.main` by default.
540
+    ///   - encoding:          The string encoding. Defaults to `nil`, in which case the encoding will be determined from
541
+    ///                        the server response, falling back to the default HTTP character set, `ISO-8859-1`.
542
+    ///   - completionHandler: A closure to be executed once the request has finished.
543
+    ///
544
+    /// - Returns:             The request.
545
+    @discardableResult
546
+    public func responseString(queue: DispatchQueue = .main,
547
+                               encoding: String.Encoding? = nil,
548
+                               completionHandler: @escaping (AFDataResponse<String>) -> Void) -> Self {
549
+        return response(queue: queue,
550
+                        responseSerializer: StringResponseSerializer(encoding: encoding),
551
+                        completionHandler: completionHandler)
552
+    }
553
+}
554
+
555
+extension DownloadRequest {
556
+    /// Adds a handler to be called once the request has finished.
557
+    ///
558
+    /// - Parameters:
559
+    ///   - queue:             The queue on which the completion handler is dispatched. `.main` by default.
560
+    ///   - encoding:          The string encoding. Defaults to `nil`, in which case the encoding will be determined from
561
+    ///                        the server response, falling back to the default HTTP character set, `ISO-8859-1`.
562
+    ///   - completionHandler: A closure to be executed once the request has finished.
563
+    ///
564
+    /// - Returns:             The request.
565
+    @discardableResult
566
+    public func responseString(queue: DispatchQueue = .main,
567
+                               encoding: String.Encoding? = nil,
568
+                               completionHandler: @escaping (AFDownloadResponse<String>) -> Void)
569
+        -> Self {
570
+        return response(queue: queue,
571
+                        responseSerializer: StringResponseSerializer(encoding: encoding),
572
+                        completionHandler: completionHandler)
573
+    }
574
+}
575
+
576
+// MARK: - JSON
577
+
578
+/// A `ResponseSerializer` that decodes the response data using `JSONSerialization`. By default, a request returning
579
+/// `nil` or no data is considered an error. However, if the response is has a status code valid for empty responses
580
+/// (`204`, `205`), then an `NSNull`  value is returned.
581
+public final class JSONResponseSerializer: ResponseSerializer {
582
+    public let dataPreprocessor: DataPreprocessor
583
+    public let emptyResponseCodes: Set<Int>
584
+    public let emptyRequestMethods: Set<HTTPMethod>
585
+    /// `JSONSerialization.ReadingOptions` used when serializing a response.
586
+    public let options: JSONSerialization.ReadingOptions
587
+
588
+    /// Creates an instance with the provided values.
589
+    ///
590
+    /// - Parameters:
591
+    ///   - dataPreprocessor:    `DataPreprocessor` used to prepare the received `Data` for serialization.
592
+    ///   - emptyResponseCodes:  The HTTP response codes for which empty responses are allowed. `[204, 205]` by default.
593
+    ///   - emptyRequestMethods: The HTTP request methods for which empty responses are allowed. `[.head]` by default.
594
+    ///   - options:             The options to use. `.allowFragments` by default.
595
+    public init(dataPreprocessor: DataPreprocessor = JSONResponseSerializer.defaultDataPreprocessor,
596
+                emptyResponseCodes: Set<Int> = JSONResponseSerializer.defaultEmptyResponseCodes,
597
+                emptyRequestMethods: Set<HTTPMethod> = JSONResponseSerializer.defaultEmptyRequestMethods,
598
+                options: JSONSerialization.ReadingOptions = .allowFragments) {
599
+        self.dataPreprocessor = dataPreprocessor
600
+        self.emptyResponseCodes = emptyResponseCodes
601
+        self.emptyRequestMethods = emptyRequestMethods
602
+        self.options = options
603
+    }
604
+
605
+    public func serialize(request: URLRequest?, response: HTTPURLResponse?, data: Data?, error: Error?) throws -> Any {
606
+        guard error == nil else { throw error! }
607
+
608
+        guard var data = data, !data.isEmpty else {
609
+            guard emptyResponseAllowed(forRequest: request, response: response) else {
610
+                throw AFError.responseSerializationFailed(reason: .inputDataNilOrZeroLength)
611
+            }
612
+
613
+            return NSNull()
614
+        }
615
+
616
+        data = try dataPreprocessor.preprocess(data)
617
+
618
+        do {
619
+            return try JSONSerialization.jsonObject(with: data, options: options)
620
+        } catch {
621
+            throw AFError.responseSerializationFailed(reason: .jsonSerializationFailed(error: error))
622
+        }
623
+    }
624
+}
625
+
626
+extension DataRequest {
627
+    /// Adds a handler to be called once the request has finished.
628
+    ///
629
+    /// - Parameters:
630
+    ///   - queue:             The queue on which the completion handler is dispatched. `.main` by default.
631
+    ///   - options:           The JSON serialization reading options. `.allowFragments` by default.
632
+    ///   - completionHandler: A closure to be executed once the request has finished.
633
+    ///
634
+    /// - Returns:             The request.
635
+    @discardableResult
636
+    public func responseJSON(queue: DispatchQueue = .main,
637
+                             options: JSONSerialization.ReadingOptions = .allowFragments,
638
+                             completionHandler: @escaping (AFDataResponse<Any>) -> Void) -> Self {
639
+        return response(queue: queue,
640
+                        responseSerializer: JSONResponseSerializer(options: options),
641
+                        completionHandler: completionHandler)
642
+    }
643
+}
644
+
645
+extension DownloadRequest {
646
+    /// Adds a handler to be called once the request has finished.
647
+    ///
648
+    /// - Parameters:
649
+    ///   - queue:             The queue on which the completion handler is dispatched. `.main` by default.
650
+    ///   - options:           The JSON serialization reading options. `.allowFragments` by default.
651
+    ///   - completionHandler: A closure to be executed once the request has finished.
652
+    ///
653
+    /// - Returns:             The request.
654
+    @discardableResult
655
+    public func responseJSON(queue: DispatchQueue = .main,
656
+                             options: JSONSerialization.ReadingOptions = .allowFragments,
657
+                             completionHandler: @escaping (AFDownloadResponse<Any>) -> Void)
658
+        -> Self {
659
+        return response(queue: queue,
660
+                        responseSerializer: JSONResponseSerializer(options: options),
661
+                        completionHandler: completionHandler)
662
+    }
663
+}
664
+
665
+// MARK: - Empty
666
+
667
+/// Protocol representing an empty response. Use `T.emptyValue()` to get an instance.
668
+public protocol EmptyResponse {
669
+    /// Empty value for the conforming type.
670
+    ///
671
+    /// - Returns: Value of `Self` to use for empty values.
672
+    static func emptyValue() -> Self
673
+}
674
+
675
+/// Type representing an empty response. Use `Empty.value` to get the static instance.
676
+public struct Empty: Decodable {
677
+    /// Static `Empty` instance used for all `Empty` responses.
678
+    public static let value = Empty()
679
+}
680
+
681
+extension Empty: EmptyResponse {
682
+    public static func emptyValue() -> Empty {
683
+        return value
684
+    }
685
+}
686
+
687
+// MARK: - DataDecoder Protocol
688
+
689
+/// Any type which can decode `Data` into a `Decodable` type.
690
+public protocol DataDecoder {
691
+    /// Decode `Data` into the provided type.
692
+    ///
693
+    /// - Parameters:
694
+    ///   - type:  The `Type` to be decoded.
695
+    ///   - data:  The `Data` to be decoded.
696
+    ///
697
+    /// - Returns: The decoded value of type `D`.
698
+    /// - Throws:  Any error that occurs during decode.
699
+    func decode<D: Decodable>(_ type: D.Type, from data: Data) throws -> D
700
+}
701
+
702
+/// `JSONDecoder` automatically conforms to `DataDecoder`.
703
+extension JSONDecoder: DataDecoder {}
704
+
705
+// MARK: - Decodable
706
+
707
+/// A `ResponseSerializer` that decodes the response data as a generic value using any type that conforms to
708
+/// `DataDecoder`. By default, this is an instance of `JSONDecoder`. Additionally, a request returning `nil` or no data
709
+/// is considered an error. However, if the response is has a status code valid for empty responses (`204`, `205`), then
710
+/// the `Empty.value` value is returned.
711
+public final class DecodableResponseSerializer<T: Decodable>: ResponseSerializer {
712
+    public let dataPreprocessor: DataPreprocessor
713
+    /// The `DataDecoder` instance used to decode responses.
714
+    public let decoder: DataDecoder
715
+    public let emptyResponseCodes: Set<Int>
716
+    public let emptyRequestMethods: Set<HTTPMethod>
717
+
718
+    /// Creates an instance using the values provided.
719
+    ///
720
+    /// - Parameters:
721
+    ///   - dataPreprocessor:    `DataPreprocessor` used to prepare the received `Data` for serialization.
722
+    ///   - decoder:             The `DataDecoder`. `JSONDecoder()` by default.
723
+    ///   - emptyResponseCodes:  The HTTP response codes for which empty responses are allowed. `[204, 205]` by default.
724
+    ///   - emptyRequestMethods: The HTTP request methods for which empty responses are allowed. `[.head]` by default.
725
+    public init(dataPreprocessor: DataPreprocessor = DecodableResponseSerializer.defaultDataPreprocessor,
726
+                decoder: DataDecoder = JSONDecoder(),
727
+                emptyResponseCodes: Set<Int> = DecodableResponseSerializer.defaultEmptyResponseCodes,
728
+                emptyRequestMethods: Set<HTTPMethod> = DecodableResponseSerializer.defaultEmptyRequestMethods) {
729
+        self.dataPreprocessor = dataPreprocessor
730
+        self.decoder = decoder
731
+        self.emptyResponseCodes = emptyResponseCodes
732
+        self.emptyRequestMethods = emptyRequestMethods
733
+    }
734
+
735
+    public func serialize(request: URLRequest?, response: HTTPURLResponse?, data: Data?, error: Error?) throws -> T {
736
+        guard error == nil else { throw error! }
737
+
738
+        guard var data = data, !data.isEmpty else {
739
+            guard emptyResponseAllowed(forRequest: request, response: response) else {
740
+                throw AFError.responseSerializationFailed(reason: .inputDataNilOrZeroLength)
741
+            }
742
+
743
+            guard let emptyResponseType = T.self as? EmptyResponse.Type, let emptyValue = emptyResponseType.emptyValue() as? T else {
744
+                throw AFError.responseSerializationFailed(reason: .invalidEmptyResponse(type: "\(T.self)"))
745
+            }
746
+
747
+            return emptyValue
748
+        }
749
+
750
+        data = try dataPreprocessor.preprocess(data)
751
+
752
+        do {
753
+            return try decoder.decode(T.self, from: data)
754
+        } catch {
755
+            throw AFError.responseSerializationFailed(reason: .decodingFailed(error: error))
756
+        }
757
+    }
758
+}
759
+
760
+extension DataRequest {
761
+    /// Adds a handler to be called once the request has finished.
762
+    ///
763
+    /// - Parameters:
764
+    ///   - type:              `Decodable` type to decode from response data.
765
+    ///   - queue:             The queue on which the completion handler is dispatched. `.main` by default.
766
+    ///   - decoder:           `DataDecoder` to use to decode the response. `JSONDecoder()` by default.
767
+    ///   - completionHandler: A closure to be executed once the request has finished.
768
+    ///
769
+    /// - Returns:             The request.
770
+    @discardableResult
771
+    public func responseDecodable<T: Decodable>(of type: T.Type = T.self,
772
+                                                queue: DispatchQueue = .main,
773
+                                                decoder: DataDecoder = JSONDecoder(),
774
+                                                completionHandler: @escaping (AFDataResponse<T>) -> Void) -> Self {
775
+        return response(queue: queue,
776
+                        responseSerializer: DecodableResponseSerializer(decoder: decoder),
777
+                        completionHandler: completionHandler)
778
+    }
779
+}

+ 109
- 0
trolley/Pods/Alamofire/Source/Result+Alamofire.swift 查看文件

@@ -0,0 +1,109 @@
1
+//
2
+//  Result+Alamofire.swift
3
+//
4
+//  Copyright (c) 2019 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
+/// Default type of `Result` returned by Alamofire, with an `AFError` `Failure` type.
28
+public typealias AFResult<Success> = Result<Success, AFError>
29
+
30
+// MARK: - Internal APIs
31
+
32
+extension Result {
33
+    /// Returns the associated value if the result is a success, `nil` otherwise.
34
+    var success: Success? {
35
+        guard case let .success(value) = self else { return nil }
36
+        return value
37
+    }
38
+
39
+    /// Returns the associated error value if the result is a failure, `nil` otherwise.
40
+    var failure: Failure? {
41
+        guard case let .failure(error) = self else { return nil }
42
+        return error
43
+    }
44
+
45
+    /// Initializes a `Result` from value or error. Returns `.failure` if the error is non-nil, `.success` otherwise.
46
+    ///
47
+    /// - Parameters:
48
+    ///   - value: A value.
49
+    ///   - error: An `Error`.
50
+    init(value: Success, error: Failure?) {
51
+        if let error = error {
52
+            self = .failure(error)
53
+        } else {
54
+            self = .success(value)
55
+        }
56
+    }
57
+
58
+    /// Evaluates the specified closure when the `Result` is a success, passing the unwrapped value as a parameter.
59
+    ///
60
+    /// Use the `tryMap` method with a closure that may throw an error. For example:
61
+    ///
62
+    ///     let possibleData: Result<Data, Error> = .success(Data(...))
63
+    ///     let possibleObject = possibleData.tryMap {
64
+    ///         try JSONSerialization.jsonObject(with: $0)
65
+    ///     }
66
+    ///
67
+    /// - parameter transform: A closure that takes the success value of the instance.
68
+    ///
69
+    /// - returns: A `Result` containing the result of the given closure. If this instance is a failure, returns the
70
+    ///            same failure.
71
+    func tryMap<NewSuccess>(_ transform: (Success) throws -> NewSuccess) -> Result<NewSuccess, Error> {
72
+        switch self {
73
+        case let .success(value):
74
+            do {
75
+                return try .success(transform(value))
76
+            } catch {
77
+                return .failure(error)
78
+            }
79
+        case let .failure(error):
80
+            return .failure(error)
81
+        }
82
+    }
83
+
84
+    /// Evaluates the specified closure when the `Result` is a failure, passing the unwrapped error as a parameter.
85
+    ///
86
+    /// Use the `tryMapError` function with a closure that may throw an error. For example:
87
+    ///
88
+    ///     let possibleData: Result<Data, Error> = .success(Data(...))
89
+    ///     let possibleObject = possibleData.tryMapError {
90
+    ///         try someFailableFunction(taking: $0)
91
+    ///     }
92
+    ///
93
+    /// - Parameter transform: A throwing closure that takes the error of the instance.
94
+    ///
95
+    /// - Returns: A `Result` instance containing the result of the transform. If this instance is a success, returns
96
+    ///            the same success.
97
+    func tryMapError<NewFailure: Error>(_ transform: (Failure) throws -> NewFailure) -> Result<Success, Error> {
98
+        switch self {
99
+        case let .failure(error):
100
+            do {
101
+                return try .failure(transform(error))
102
+            } catch {
103
+                return .failure(error)
104
+            }
105
+        case let .success(value):
106
+            return .success(value)
107
+        }
108
+    }
109
+}

+ 363
- 0
trolley/Pods/Alamofire/Source/RetryPolicy.swift 查看文件

@@ -0,0 +1,363 @@
1
+//
2
+//  RetryPolicy.swift
3
+//
4
+//  Copyright (c) 2019 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
+/// A retry policy that retries requests using an exponential backoff for allowed HTTP methods and HTTP status codes
28
+/// as well as certain types of networking errors.
29
+open class RetryPolicy: RequestInterceptor {
30
+    /// The default retry limit for retry policies.
31
+    public static let defaultRetryLimit: UInt = 2
32
+
33
+    /// The default exponential backoff base for retry policies (must be a minimum of 2).
34
+    public static let defaultExponentialBackoffBase: UInt = 2
35
+
36
+    /// The default exponential backoff scale for retry policies.
37
+    public static let defaultExponentialBackoffScale: Double = 0.5
38
+
39
+    /// The default HTTP methods to retry.
40
+    /// See [RFC 2616 - Section 9.1.2](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html) for more information.
41
+    public static let defaultRetryableHTTPMethods: Set<HTTPMethod> = [.delete, // [Delete](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.7) - not always idempotent
42
+                                                                      .get, // [GET](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.3) - generally idempotent
43
+                                                                      .head, // [HEAD](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.4) - generally idempotent
44
+                                                                      .options, // [OPTIONS](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.2) - inherently idempotent
45
+                                                                      .put, // [PUT](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.6) - not always idempotent
46
+                                                                      .trace // [TRACE](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.8) - inherently idempotent
47
+    ]
48
+
49
+    /// The default HTTP status codes to retry.
50
+    /// See [RFC 2616 - Section 10](https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10) for more information.
51
+    public static let defaultRetryableHTTPStatusCodes: Set<Int> = [408, // [Request Timeout](https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.9)
52
+                                                                   500, // [Internal Server Error](https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.1)
53
+                                                                   502, // [Bad Gateway](https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.3)
54
+                                                                   503, // [Service Unavailable](https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.4)
55
+                                                                   504 // [Gateway Timeout](https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.5)
56
+    ]
57
+
58
+    /// The default URL error codes to retry.
59
+    public static let defaultRetryableURLErrorCodes: Set<URLError.Code> = [// [Security] App Transport Security disallowed a connection because there is no secure network connection.
60
+        //   - [Disabled] ATS settings do not change at runtime.
61
+        // .appTransportSecurityRequiresSecureConnection,
62
+
63
+        // [System] An app or app extension attempted to connect to a background session that is already connected to a
64
+        // process.
65
+        //   - [Enabled] The other process could release the background session.
66
+        .backgroundSessionInUseByAnotherProcess,
67
+                                                                           
68
+        // [System] The shared container identifier of the URL session configuration is needed but has not been set.
69
+        //   - [Disabled] Cannot change at runtime.
70
+        // .backgroundSessionRequiresSharedContainer,
71
+
72
+        // [System] The app is suspended or exits while a background data task is processing.
73
+        //   - [Enabled] App can be foregrounded or launched to recover.
74
+        .backgroundSessionWasDisconnected,
75
+                                                                           
76
+        // [Network] The URL Loading system received bad data from the server.
77
+        //   - [Enabled] Server could return valid data when retrying.
78
+        .badServerResponse,
79
+                                                                           
80
+        // [Resource] A malformed URL prevented a URL request from being initiated.
81
+        //   - [Disabled] URL was most likely constructed incorrectly.
82
+        // .badURL,
83
+
84
+        // [System] A connection was attempted while a phone call is active on a network that does not support
85
+        // simultaneous phone and data communication (EDGE or GPRS).
86
+        //   - [Enabled] Phone call could be ended to allow request to recover.
87
+        .callIsActive,
88
+                                                                           
89
+        // [Client] An asynchronous load has been canceled.
90
+        //   - [Disabled] Request was cancelled by the client.
91
+        // .cancelled,
92
+
93
+        // [File System] A download task couldn’t close the downloaded file on disk.
94
+        //   - [Disabled] File system error is unlikely to recover with retry.
95
+        // .cannotCloseFile,
96
+
97
+        // [Network] An attempt to connect to a host failed.
98
+        //   - [Enabled] Server or DNS lookup could recover during retry.
99
+        .cannotConnectToHost,
100
+                                                                           
101
+        // [File System] A download task couldn’t create the downloaded file on disk because of an I/O failure.
102
+        //   - [Disabled] File system error is unlikely to recover with retry.
103
+        // .cannotCreateFile,
104
+
105
+        // [Data] Content data received during a connection request had an unknown content encoding.
106
+        //   - [Disabled] Server is unlikely to modify the content encoding during a retry.
107
+        // .cannotDecodeContentData,
108
+
109
+        // [Data] Content data received during a connection request could not be decoded for a known content encoding.
110
+        //   - [Disabled] Server is unlikely to modify the content encoding during a retry.
111
+        // .cannotDecodeRawData,
112
+
113
+        // [Network] The host name for a URL could not be resolved.
114
+        //   - [Enabled] Server or DNS lookup could recover during retry.
115
+        .cannotFindHost,
116
+                                                                           
117
+        // [Network] A request to load an item only from the cache could not be satisfied.
118
+        //   - [Enabled] Cache could be populated during a retry.
119
+        .cannotLoadFromNetwork,
120
+                                                                           
121
+        // [File System] A download task was unable to move a downloaded file on disk.
122
+        //   - [Disabled] File system error is unlikely to recover with retry.
123
+        // .cannotMoveFile,
124
+
125
+        // [File System] A download task was unable to open the downloaded file on disk.
126
+        //   - [Disabled] File system error is unlikely to recover with retry.
127
+        // .cannotOpenFile,
128
+
129
+        // [Data] A task could not parse a response.
130
+        //   - [Disabled] Invalid response is unlikely to recover with retry.
131
+        // .cannotParseResponse,
132
+
133
+        // [File System] A download task was unable to remove a downloaded file from disk.
134
+        //   - [Disabled] File system error is unlikely to recover with retry.
135
+        // .cannotRemoveFile,
136
+
137
+        // [File System] A download task was unable to write to the downloaded file on disk.
138
+        //   - [Disabled] File system error is unlikely to recover with retry.
139
+        // .cannotWriteToFile,
140
+
141
+        // [Security] A client certificate was rejected.
142
+        //   - [Disabled] Client certificate is unlikely to change with retry.
143
+        // .clientCertificateRejected,
144
+
145
+        // [Security] A client certificate was required to authenticate an SSL connection during a request.
146
+        //   - [Disabled] Client certificate is unlikely to be provided with retry.
147
+        // .clientCertificateRequired,
148
+
149
+        // [Data] The length of the resource data exceeds the maximum allowed.
150
+        //   - [Disabled] Resource will likely still exceed the length maximum on retry.
151
+        // .dataLengthExceedsMaximum,
152
+
153
+        // [System] The cellular network disallowed a connection.
154
+        //   - [Enabled] WiFi connection could be established during retry.
155
+        .dataNotAllowed,
156
+                                                                           
157
+        // [Network] The host address could not be found via DNS lookup.
158
+        //   - [Enabled] DNS lookup could succeed during retry.
159
+        .dnsLookupFailed,
160
+                                                                           
161
+        // [Data] A download task failed to decode an encoded file during the download.
162
+        //   - [Enabled] Server could correct the decoding issue with retry.
163
+        .downloadDecodingFailedMidStream,
164
+                                                                           
165
+        // [Data] A download task failed to decode an encoded file after downloading.
166
+        //   - [Enabled] Server could correct the decoding issue with retry.
167
+        .downloadDecodingFailedToComplete,
168
+                                                                           
169
+        // [File System] A file does not exist.
170
+        //   - [Disabled] File system error is unlikely to recover with retry.
171
+        // .fileDoesNotExist,
172
+
173
+        // [File System] A request for an FTP file resulted in the server responding that the file is not a plain file,
174
+        // but a directory.
175
+        //   - [Disabled] FTP directory is not likely to change to a file during a retry.
176
+        // .fileIsDirectory,
177
+
178
+        // [Network] A redirect loop has been detected or the threshold for number of allowable redirects has been
179
+        // exceeded (currently 16).
180
+        //   - [Disabled] The redirect loop is unlikely to be resolved within the retry window.
181
+        // .httpTooManyRedirects,
182
+
183
+        // [System] The attempted connection required activating a data context while roaming, but international roaming
184
+        // is disabled.
185
+        //   - [Enabled] WiFi connection could be established during retry.
186
+        .internationalRoamingOff,
187
+                                                                           
188
+        // [Connectivity] A client or server connection was severed in the middle of an in-progress load.
189
+        //   - [Enabled] A network connection could be established during retry.
190
+        .networkConnectionLost,
191
+                                                                           
192
+        // [File System] A resource couldn’t be read because of insufficient permissions.
193
+        //   - [Disabled] Permissions are unlikely to be granted during retry.
194
+        // .noPermissionsToReadFile,
195
+
196
+        // [Connectivity] A network resource was requested, but an internet connection has not been established and
197
+        // cannot be established automatically.
198
+        //   - [Enabled] A network connection could be established during retry.
199
+        .notConnectedToInternet,
200
+                                                                           
201
+        // [Resource] A redirect was specified by way of server response code, but the server did not accompany this
202
+        // code with a redirect URL.
203
+        //   - [Disabled] The redirect URL is unlikely to be supplied during a retry.
204
+        // .redirectToNonExistentLocation,
205
+
206
+        // [Client] A body stream is needed but the client did not provide one.
207
+        //   - [Disabled] The client will be unlikely to supply a body stream during retry.
208
+        // .requestBodyStreamExhausted,
209
+
210
+        // [Resource] A requested resource couldn’t be retrieved.
211
+        //   - [Disabled] The resource is unlikely to become available during the retry window.
212
+        // .resourceUnavailable,
213
+
214
+        // [Security] An attempt to establish a secure connection failed for reasons that can’t be expressed more
215
+        // specifically.
216
+        //   - [Enabled] The secure connection could be established during a retry given the lack of specificity
217
+        //     provided by the error.
218
+        .secureConnectionFailed,
219
+                                                                           
220
+        // [Security] A server certificate had a date which indicates it has expired, or is not yet valid.
221
+        //   - [Enabled] The server certificate could become valid within the retry window.
222
+        .serverCertificateHasBadDate,
223
+                                                                           
224
+        // [Security] A server certificate was not signed by any root server.
225
+        //   - [Disabled] The server certificate is unlikely to change during the retry window.
226
+        // .serverCertificateHasUnknownRoot,
227
+
228
+        // [Security] A server certificate is not yet valid.
229
+        //   - [Enabled] The server certificate could become valid within the retry window.
230
+        .serverCertificateNotYetValid,
231
+                                                                           
232
+        // [Security] A server certificate was signed by a root server that isn’t trusted.
233
+        //   - [Disabled] The server certificate is unlikely to become trusted within the retry window.
234
+        // .serverCertificateUntrusted,
235
+
236
+        // [Network] An asynchronous operation timed out.
237
+        //   - [Enabled] The request timed out for an unknown reason and should be retried.
238
+        .timedOut
239
+
240
+        // [System] The URL Loading System encountered an error that it can’t interpret.
241
+        //   - [Disabled] The error could not be interpreted and is unlikely to be recovered from during a retry.
242
+        // .unknown,
243
+
244
+        // [Resource] A properly formed URL couldn’t be handled by the framework.
245
+        //   - [Disabled] The URL is unlikely to change during a retry.
246
+        // .unsupportedURL,
247
+
248
+        // [Client] Authentication is required to access a resource.
249
+        //   - [Disabled] The user authentication is unlikely to be provided by retrying.
250
+        // .userAuthenticationRequired,
251
+
252
+        // [Client] An asynchronous request for authentication has been canceled by the user.
253
+        //   - [Disabled] The user cancelled authentication and explicitly took action to not retry.
254
+        // .userCancelledAuthentication,
255
+
256
+        // [Resource] A server reported that a URL has a non-zero content length, but terminated the network connection
257
+        // gracefully without sending any data.
258
+        //   - [Disabled] The server is unlikely to provide data during the retry window.
259
+        // .zeroByteResource,
260
+    ]
261
+
262
+    /// The total number of times the request is allowed to be retried.
263
+    public let retryLimit: UInt
264
+
265
+    /// The base of the exponential backoff policy (should always be greater than or equal to 2).
266
+    public let exponentialBackoffBase: UInt
267
+
268
+    /// The scale of the exponential backoff.
269
+    public let exponentialBackoffScale: Double
270
+
271
+    /// The HTTP methods that are allowed to be retried.
272
+    public let retryableHTTPMethods: Set<HTTPMethod>
273
+
274
+    /// The HTTP status codes that are automatically retried by the policy.
275
+    public let retryableHTTPStatusCodes: Set<Int>
276
+
277
+    /// The URL error codes that are automatically retried by the policy.
278
+    public let retryableURLErrorCodes: Set<URLError.Code>
279
+
280
+    /// Creates an `ExponentialBackoffRetryPolicy` from the specified parameters.
281
+    ///
282
+    /// - Parameters:
283
+    ///   - retryLimit:               The total number of times the request is allowed to be retried. `2` by default.
284
+    ///   - exponentialBackoffBase:   The base of the exponential backoff policy. `2` by default.
285
+    ///   - exponentialBackoffScale:  The scale of the exponential backoff. `0.5` by default.
286
+    ///   - retryableHTTPMethods:     The HTTP methods that are allowed to be retried.
287
+    ///                               `RetryPolicy.defaultRetryableHTTPMethods` by default.
288
+    ///   - retryableHTTPStatusCodes: The HTTP status codes that are automatically retried by the policy.
289
+    ///                               `RetryPolicy.defaultRetryableHTTPStatusCodes` by default.
290
+    ///   - retryableURLErrorCodes:   The URL error codes that are automatically retried by the policy.
291
+    ///                               `RetryPolicy.defaultRetryableURLErrorCodes` by default.
292
+    public init(retryLimit: UInt = RetryPolicy.defaultRetryLimit,
293
+                exponentialBackoffBase: UInt = RetryPolicy.defaultExponentialBackoffBase,
294
+                exponentialBackoffScale: Double = RetryPolicy.defaultExponentialBackoffScale,
295
+                retryableHTTPMethods: Set<HTTPMethod> = RetryPolicy.defaultRetryableHTTPMethods,
296
+                retryableHTTPStatusCodes: Set<Int> = RetryPolicy.defaultRetryableHTTPStatusCodes,
297
+                retryableURLErrorCodes: Set<URLError.Code> = RetryPolicy.defaultRetryableURLErrorCodes) {
298
+        precondition(exponentialBackoffBase >= 2, "The `exponentialBackoffBase` must be a minimum of 2.")
299
+
300
+        self.retryLimit = retryLimit
301
+        self.exponentialBackoffBase = exponentialBackoffBase
302
+        self.exponentialBackoffScale = exponentialBackoffScale
303
+        self.retryableHTTPMethods = retryableHTTPMethods
304
+        self.retryableHTTPStatusCodes = retryableHTTPStatusCodes
305
+        self.retryableURLErrorCodes = retryableURLErrorCodes
306
+    }
307
+
308
+    open func retry(_ request: Request,
309
+                    for session: Session,
310
+                    dueTo error: Error,
311
+                    completion: @escaping (RetryResult) -> Void) {
312
+        if
313
+            request.retryCount < retryLimit,
314
+            let httpMethod = request.request?.method,
315
+            retryableHTTPMethods.contains(httpMethod),
316
+            shouldRetry(response: request.response, error: error) {
317
+            let timeDelay = pow(Double(exponentialBackoffBase), Double(request.retryCount)) * exponentialBackoffScale
318
+            completion(.retryWithDelay(timeDelay))
319
+        } else {
320
+            completion(.doNotRetry)
321
+        }
322
+    }
323
+
324
+    private func shouldRetry(response: HTTPURLResponse?, error: Error) -> Bool {
325
+        if let statusCode = response?.statusCode, retryableHTTPStatusCodes.contains(statusCode) {
326
+            return true
327
+        } else if let errorCode = (error as? URLError)?.code, retryableURLErrorCodes.contains(errorCode) {
328
+            return true
329
+        }
330
+
331
+        return false
332
+    }
333
+}
334
+
335
+// MARK: -
336
+
337
+/// A retry policy that automatically retries idempotent requests for network connection lost errors. For more
338
+/// information about retrying network connection lost errors, please refer to Apple's
339
+/// [technical document](https://developer.apple.com/library/content/qa/qa1941/_index.html).
340
+open class ConnectionLostRetryPolicy: RetryPolicy {
341
+    /// Creates a `ConnectionLostRetryPolicy` instance from the specified parameters.
342
+    ///
343
+    /// - Parameters:
344
+    ///   - retryLimit:              The total number of times the request is allowed to be retried.
345
+    ///                              `RetryPolicy.defaultRetryLimit` by default.
346
+    ///   - exponentialBackoffBase:  The base of the exponential backoff policy.
347
+    ///                              `RetryPolicy.defaultExponentialBackoffBase` by default.
348
+    ///   - exponentialBackoffScale: The scale of the exponential backoff.
349
+    ///                              `RetryPolicy.defaultExponentialBackoffScale` by default.
350
+    ///   - retryableHTTPMethods:    The idempotent http methods to retry.
351
+    ///                              `RetryPolicy.defaultRetryableHTTPMethods` by default.
352
+    public init(retryLimit: UInt = RetryPolicy.defaultRetryLimit,
353
+                exponentialBackoffBase: UInt = RetryPolicy.defaultExponentialBackoffBase,
354
+                exponentialBackoffScale: Double = RetryPolicy.defaultExponentialBackoffScale,
355
+                retryableHTTPMethods: Set<HTTPMethod> = RetryPolicy.defaultRetryableHTTPMethods) {
356
+        super.init(retryLimit: retryLimit,
357
+                   exponentialBackoffBase: exponentialBackoffBase,
358
+                   exponentialBackoffScale: exponentialBackoffScale,
359
+                   retryableHTTPMethods: retryableHTTPMethods,
360
+                   retryableHTTPStatusCodes: [],
361
+                   retryableURLErrorCodes: [.networkConnectionLost])
362
+    }
363
+}

+ 606
- 0
trolley/Pods/Alamofire/Source/ServerTrustEvaluation.swift 查看文件

@@ -0,0 +1,606 @@
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 `ServerTrustEvaluating` values to given hosts.
28
+open class ServerTrustManager {
29
+    /// Determines whether all hosts for this `ServerTrustManager` must be evaluated. `true` by default.
30
+    public let allHostsMustBeEvaluated: Bool
31
+
32
+    /// The dictionary of policies mapped to a particular host.
33
+    public let evaluators: [String: ServerTrustEvaluating]
34
+
35
+    /// Initializes the `ServerTrustManager` instance with the given evaluators.
36
+    ///
37
+    /// Since different servers and web services can have different leaf certificates, intermediate and even root
38
+    /// certificates, it is important to have the flexibility to specify evaluation policies on a per host basis. This
39
+    /// allows for scenarios such as using default evaluation for host1, certificate pinning for host2, public key
40
+    /// pinning for host3 and disabling evaluation for host4.
41
+    ///
42
+    /// - Parameters:
43
+    ///   - allHostsMustBeEvaluated: The value determining whether all hosts for this instance must be evaluated. `true`
44
+    ///                              by default.
45
+    ///   - evaluators:              A dictionary of evaluators mapped to hosts.
46
+    public init(allHostsMustBeEvaluated: Bool = true, evaluators: [String: ServerTrustEvaluating]) {
47
+        self.allHostsMustBeEvaluated = allHostsMustBeEvaluated
48
+        self.evaluators = evaluators
49
+    }
50
+
51
+    /// Returns the `ServerTrustEvaluating` value for the given host, if one is set.
52
+    ///
53
+    /// By default, this method will return the policy that perfectly matches the given host. Subclasses could override
54
+    /// this method and implement more complex mapping implementations such as wildcards.
55
+    ///
56
+    /// - Parameter host: The host to use when searching for a matching policy.
57
+    ///
58
+    /// - Returns:        The `ServerTrustEvaluating` value for the given host if found, `nil` otherwise.
59
+    /// - Throws:         `AFError.serverTrustEvaluationFailed` if `allHostsMustBeEvaluated` is `true` and no matching
60
+    ///                   evaluators are found.
61
+    open func serverTrustEvaluator(forHost host: String) throws -> ServerTrustEvaluating? {
62
+        guard let evaluator = evaluators[host] else {
63
+            if allHostsMustBeEvaluated {
64
+                throw AFError.serverTrustEvaluationFailed(reason: .noRequiredEvaluator(host: host))
65
+            }
66
+
67
+            return nil
68
+        }
69
+
70
+        return evaluator
71
+    }
72
+}
73
+
74
+/// A protocol describing the API used to evaluate server trusts.
75
+public protocol ServerTrustEvaluating {
76
+#if os(Linux)
77
+// Implement this once Linux has API for evaluating server trusts.
78
+#else
79
+    /// Evaluates the given `SecTrust` value for the given `host`.
80
+    ///
81
+    /// - Parameters:
82
+    ///   - trust: The `SecTrust` value to evaluate.
83
+    ///   - host:  The host for which to evaluate the `SecTrust` value.
84
+    ///
85
+    /// - Returns: A `Bool` indicating whether the evaluator considers the `SecTrust` value valid for `host`.
86
+    func evaluate(_ trust: SecTrust, forHost host: String) throws
87
+#endif
88
+}
89
+
90
+// MARK: - Server Trust Evaluators
91
+
92
+/// An evaluator which uses the default server trust evaluation while allowing you to control whether to validate the
93
+/// host provided by the challenge. Applications are encouraged to always validate the host in production environments
94
+/// to guarantee the validity of the server's certificate chain.
95
+public final class DefaultTrustEvaluator: ServerTrustEvaluating {
96
+    private let validateHost: Bool
97
+
98
+    /// Creates a `DefaultTrustEvaluator`.
99
+    ///
100
+    /// - Parameter validateHost: Determines whether or not the evaluator should validate the host. `true` by default.
101
+    public init(validateHost: Bool = true) {
102
+        self.validateHost = validateHost
103
+    }
104
+
105
+    public func evaluate(_ trust: SecTrust, forHost host: String) throws {
106
+        if validateHost {
107
+            try trust.af.performValidation(forHost: host)
108
+        }
109
+
110
+        try trust.af.performDefaultValidation(forHost: host)
111
+    }
112
+}
113
+
114
+/// An evaluator which Uses the default and revoked server trust evaluations allowing you to control whether to validate
115
+/// the host provided by the challenge as well as specify the revocation flags for testing for revoked certificates.
116
+/// Apple platforms did not start testing for revoked certificates automatically until iOS 10.1, macOS 10.12 and tvOS
117
+/// 10.1 which is demonstrated in our TLS tests. Applications are encouraged to always validate the host in production
118
+/// environments to guarantee the validity of the server's certificate chain.
119
+public final class RevocationTrustEvaluator: ServerTrustEvaluating {
120
+    /// Represents the options to be use when evaluating the status of a certificate.
121
+    /// Only Revocation Policy Constants are valid, and can be found in [Apple's documentation](https://developer.apple.com/documentation/security/certificate_key_and_trust_services/policies/1563600-revocation_policy_constants).
122
+    public struct Options: OptionSet {
123
+        /// Perform revocation checking using the CRL (Certification Revocation List) method.
124
+        public static let crl = Options(rawValue: kSecRevocationCRLMethod)
125
+        /// Consult only locally cached replies; do not use network access.
126
+        public static let networkAccessDisabled = Options(rawValue: kSecRevocationNetworkAccessDisabled)
127
+        /// Perform revocation checking using OCSP (Online Certificate Status Protocol).
128
+        public static let ocsp = Options(rawValue: kSecRevocationOCSPMethod)
129
+        /// Prefer CRL revocation checking over OCSP; by default, OCSP is preferred.
130
+        public static let preferCRL = Options(rawValue: kSecRevocationPreferCRL)
131
+        /// Require a positive response to pass the policy. If the flag is not set, revocation checking is done on a
132
+        /// "best attempt" basis, where failure to reach the server is not considered fatal.
133
+        public static let requirePositiveResponse = Options(rawValue: kSecRevocationRequirePositiveResponse)
134
+        /// Perform either OCSP or CRL checking. The checking is performed according to the method(s) specified in the
135
+        /// certificate and the value of `preferCRL`.
136
+        public static let any = Options(rawValue: kSecRevocationUseAnyAvailableMethod)
137
+
138
+        /// The raw value of the option.
139
+        public let rawValue: CFOptionFlags
140
+
141
+        /// Creates an `Options` value with the given `CFOptionFlags`.
142
+        ///
143
+        /// - Parameter rawValue: The `CFOptionFlags` value to initialize with.
144
+        public init(rawValue: CFOptionFlags) {
145
+            self.rawValue = rawValue
146
+        }
147
+    }
148
+
149
+    private let performDefaultValidation: Bool
150
+    private let validateHost: Bool
151
+    private let options: Options
152
+
153
+    /// Creates a `RevocationTrustEvaluator`.
154
+    ///
155
+    /// - Note: Default and host validation will fail when using this evaluator with self-signed certificates. Use
156
+    ///         `PinnedCertificatesTrustEvaluator` if you need to use self-signed certificates.
157
+    ///
158
+    /// - Parameters:
159
+    ///   - performDefaultValidation:     Determines whether default validation should be performed in addition to
160
+    ///                                   evaluating the pinned certificates. `true` by default.
161
+    ///   - validateHost:                 Determines whether or not the evaluator should validate the host, in addition
162
+    ///                                   to performing the default evaluation, even if `performDefaultValidation` is
163
+    ///                                   `false`. `true` by default.
164
+    ///   - options:                      The `Options` to use to check the revocation status of the certificate. `.any`
165
+    ///                                   by default.
166
+    public init(performDefaultValidation: Bool = true, validateHost: Bool = true, options: Options = .any) {
167
+        self.performDefaultValidation = performDefaultValidation
168
+        self.validateHost = validateHost
169
+        self.options = options
170
+    }
171
+
172
+    public func evaluate(_ trust: SecTrust, forHost host: String) throws {
173
+        if performDefaultValidation {
174
+            try trust.af.performDefaultValidation(forHost: host)
175
+        }
176
+
177
+        if validateHost {
178
+            try trust.af.performValidation(forHost: host)
179
+        }
180
+
181
+        if #available(iOS 12, macOS 10.14, tvOS 12, watchOS 5, *) {
182
+            try trust.af.evaluate(afterApplying: SecPolicy.af.revocation(options: options))
183
+        } else {
184
+            try trust.af.validate(policy: SecPolicy.af.revocation(options: options)) { status, result in
185
+                AFError.serverTrustEvaluationFailed(reason: .revocationCheckFailed(output: .init(host, trust, status, result), options: options))
186
+            }
187
+        }
188
+    }
189
+}
190
+
191
+/// Uses the pinned certificates to validate the server trust. The server trust is considered valid if one of the pinned
192
+/// certificates match one of the server certificates. By validating both the certificate chain and host, certificate
193
+/// pinning provides a very secure form of server trust validation mitigating most, if not all, MITM attacks.
194
+/// Applications are encouraged to always validate the host and require a valid certificate chain in production
195
+/// environments.
196
+public final class PinnedCertificatesTrustEvaluator: ServerTrustEvaluating {
197
+    private let certificates: [SecCertificate]
198
+    private let acceptSelfSignedCertificates: Bool
199
+    private let performDefaultValidation: Bool
200
+    private let validateHost: Bool
201
+
202
+    /// Creates a `PinnedCertificatesTrustEvaluator`.
203
+    ///
204
+    /// - Parameters:
205
+    ///   - certificates:                 The certificates to use to evaluate the trust. All `cer`, `crt`, and `der`
206
+    ///                                   certificates in `Bundle.main` by default.
207
+    ///   - acceptSelfSignedCertificates: Adds the provided certificates as anchors for the trust evaluation, allowing
208
+    ///                                   self-signed certificates to pass. `false` by default. THIS SETTING SHOULD BE
209
+    ///                                   FALSE IN PRODUCTION!
210
+    ///   - performDefaultValidation:     Determines whether default validation should be performed in addition to
211
+    ///                                   evaluating the pinned certificates. `true` by default.
212
+    ///   - validateHost:                 Determines whether or not the evaluator should validate the host, in addition
213
+    ///                                   to performing the default evaluation, even if `performDefaultValidation` is
214
+    ///                                   `false`. `true` by default.
215
+    public init(certificates: [SecCertificate] = Bundle.main.af.certificates,
216
+                acceptSelfSignedCertificates: Bool = false,
217
+                performDefaultValidation: Bool = true,
218
+                validateHost: Bool = true) {
219
+        self.certificates = certificates
220
+        self.acceptSelfSignedCertificates = acceptSelfSignedCertificates
221
+        self.performDefaultValidation = performDefaultValidation
222
+        self.validateHost = validateHost
223
+    }
224
+
225
+    public func evaluate(_ trust: SecTrust, forHost host: String) throws {
226
+        guard !certificates.isEmpty else {
227
+            throw AFError.serverTrustEvaluationFailed(reason: .noCertificatesFound)
228
+        }
229
+
230
+        if acceptSelfSignedCertificates {
231
+            try trust.af.setAnchorCertificates(certificates)
232
+        }
233
+
234
+        if performDefaultValidation {
235
+            try trust.af.performDefaultValidation(forHost: host)
236
+        }
237
+
238
+        if validateHost {
239
+            try trust.af.performValidation(forHost: host)
240
+        }
241
+
242
+        let serverCertificatesData = Set(trust.af.certificateData)
243
+        let pinnedCertificatesData = Set(certificates.af.data)
244
+        let pinnedCertificatesInServerData = !serverCertificatesData.isDisjoint(with: pinnedCertificatesData)
245
+        if !pinnedCertificatesInServerData {
246
+            throw AFError.serverTrustEvaluationFailed(reason: .certificatePinningFailed(host: host,
247
+                                                                                        trust: trust,
248
+                                                                                        pinnedCertificates: certificates,
249
+                                                                                        serverCertificates: trust.af.certificates))
250
+        }
251
+    }
252
+}
253
+
254
+/// Uses the pinned public keys to validate the server trust. The server trust is considered valid if one of the pinned
255
+/// public keys match one of the server certificate public keys. By validating both the certificate chain and host,
256
+/// public key pinning provides a very secure form of server trust validation mitigating most, if not all, MITM attacks.
257
+/// Applications are encouraged to always validate the host and require a valid certificate chain in production
258
+/// environments.
259
+public final class PublicKeysTrustEvaluator: ServerTrustEvaluating {
260
+    private let keys: [SecKey]
261
+    private let performDefaultValidation: Bool
262
+    private let validateHost: Bool
263
+
264
+    /// Creates a `PublicKeysTrustEvaluator`.
265
+    ///
266
+    /// - Note: Default and host validation will fail when using this evaluator with self-signed certificates. Use
267
+    ///         `PinnedCertificatesTrustEvaluator` if you need to use self-signed certificates.
268
+    ///
269
+    /// - Parameters:
270
+    ///   - keys:                     The `SecKey`s to use to validate public keys. Defaults to the public keys of all
271
+    ///                               certificates included in the main bundle.
272
+    ///   - performDefaultValidation: Determines whether default validation should be performed in addition to
273
+    ///                               evaluating the pinned certificates. `true` by default.
274
+    ///   - validateHost:             Determines whether or not the evaluator should validate the host, in addition to
275
+    ///                               performing the default evaluation, even if `performDefaultValidation` is `false`.
276
+    ///                               `true` by default.
277
+    public init(keys: [SecKey] = Bundle.main.af.publicKeys,
278
+                performDefaultValidation: Bool = true,
279
+                validateHost: Bool = true) {
280
+        self.keys = keys
281
+        self.performDefaultValidation = performDefaultValidation
282
+        self.validateHost = validateHost
283
+    }
284
+
285
+    public func evaluate(_ trust: SecTrust, forHost host: String) throws {
286
+        guard !keys.isEmpty else {
287
+            throw AFError.serverTrustEvaluationFailed(reason: .noPublicKeysFound)
288
+        }
289
+
290
+        if performDefaultValidation {
291
+            try trust.af.performDefaultValidation(forHost: host)
292
+        }
293
+
294
+        if validateHost {
295
+            try trust.af.performValidation(forHost: host)
296
+        }
297
+
298
+        let pinnedKeysInServerKeys: Bool = {
299
+            for serverPublicKey in trust.af.publicKeys {
300
+                for pinnedPublicKey in keys {
301
+                    if serverPublicKey == pinnedPublicKey {
302
+                        return true
303
+                    }
304
+                }
305
+            }
306
+            return false
307
+        }()
308
+
309
+        if !pinnedKeysInServerKeys {
310
+            throw AFError.serverTrustEvaluationFailed(reason: .publicKeyPinningFailed(host: host,
311
+                                                                                      trust: trust,
312
+                                                                                      pinnedKeys: keys,
313
+                                                                                      serverKeys: trust.af.publicKeys))
314
+        }
315
+    }
316
+}
317
+
318
+/// Uses the provided evaluators to validate the server trust. The trust is only considered valid if all of the
319
+/// evaluators consider it valid.
320
+public final class CompositeTrustEvaluator: ServerTrustEvaluating {
321
+    private let evaluators: [ServerTrustEvaluating]
322
+
323
+    /// Creates a `CompositeTrustEvaluator`.
324
+    ///
325
+    /// - Parameter evaluators: The `ServerTrustEvaluating` values used to evaluate the server trust.
326
+    public init(evaluators: [ServerTrustEvaluating]) {
327
+        self.evaluators = evaluators
328
+    }
329
+
330
+    public func evaluate(_ trust: SecTrust, forHost host: String) throws {
331
+        try evaluators.evaluate(trust, forHost: host)
332
+    }
333
+}
334
+
335
+/// Disables all evaluation which in turn will always consider any server trust as valid.
336
+///
337
+/// **THIS EVALUATOR SHOULD NEVER BE USED IN PRODUCTION!**
338
+public final class DisabledEvaluator: ServerTrustEvaluating {
339
+    /// Creates an instance.
340
+    public init() {}
341
+
342
+    public func evaluate(_ trust: SecTrust, forHost host: String) throws {}
343
+}
344
+
345
+// MARK: - Extensions
346
+
347
+public extension Array where Element == ServerTrustEvaluating {
348
+#if os(Linux)
349
+// Add this same convenience method for Linux.
350
+#else
351
+    /// Evaluates the given `SecTrust` value for the given `host`.
352
+    ///
353
+    /// - Parameters:
354
+    ///   - trust: The `SecTrust` value to evaluate.
355
+    ///   - host:  The host for which to evaluate the `SecTrust` value.
356
+    ///
357
+    /// - Returns: Whether or not the evaluator considers the `SecTrust` value valid for `host`.
358
+    func evaluate(_ trust: SecTrust, forHost host: String) throws {
359
+        for evaluator in self {
360
+            try evaluator.evaluate(trust, forHost: host)
361
+        }
362
+    }
363
+#endif
364
+}
365
+
366
+extension Bundle: AlamofireExtended {}
367
+public extension AlamofireExtension where ExtendedType: Bundle {
368
+    /// Returns all valid `cer`, `crt`, and `der` certificates in the bundle.
369
+    var certificates: [SecCertificate] {
370
+        return paths(forResourcesOfTypes: [".cer", ".CER", ".crt", ".CRT", ".der", ".DER"]).compactMap { path in
371
+            guard
372
+                let certificateData = try? Data(contentsOf: URL(fileURLWithPath: path)) as CFData,
373
+                let certificate = SecCertificateCreateWithData(nil, certificateData) else { return nil }
374
+
375
+            return certificate
376
+        }
377
+    }
378
+
379
+    /// Returns all public keys for the valid certificates in the bundle.
380
+    var publicKeys: [SecKey] {
381
+        return certificates.af.publicKeys
382
+    }
383
+
384
+    /// Returns all pathnames for the resources identified by the provided file extensions.
385
+    ///
386
+    /// - Parameter types: The filename extensions locate.
387
+    ///
388
+    /// - Returns:         All pathnames for the given filename extensions.
389
+    func paths(forResourcesOfTypes types: [String]) -> [String] {
390
+        return Array(Set(types.flatMap { type.paths(forResourcesOfType: $0, inDirectory: nil) }))
391
+    }
392
+}
393
+
394
+extension SecTrust: AlamofireExtended {}
395
+public extension AlamofireExtension where ExtendedType == SecTrust {
396
+    /// Evaluates `self` after applying the `SecPolicy` value provided.
397
+    ///
398
+    /// - Parameter policy: The `SecPolicy` to apply to `self` before evaluation.
399
+    ///
400
+    /// - Throws:           Any `Error` from applying the `SecPolicy` or from evaluation.
401
+    @available(iOS 12, macOS 10.14, tvOS 12, watchOS 5, *)
402
+    func evaluate(afterApplying policy: SecPolicy) throws {
403
+        try apply(policy: policy).af.evaluate()
404
+    }
405
+
406
+    /// Attempts to validate `self` using the `SecPolicy` provided and transforming any error produced using the closure passed.
407
+    ///
408
+    /// - Parameters:
409
+    ///   - policy:        The `SecPolicy` used to evaluate `self`.
410
+    ///   - errorProducer: The closure used transform the failed `OSStatus` and `SecTrustResultType`.
411
+    /// - Throws:          Any `Error` from applying the `policy`, or the result of `errorProducer` if validation fails.
412
+    @available(iOS, introduced: 10, deprecated: 12, renamed: "evaluate(afterApplying:)")
413
+    @available(macOS, introduced: 10.12, deprecated: 10.14, renamed: "evaluate(afterApplying:)")
414
+    @available(tvOS, introduced: 10, deprecated: 12, renamed: "evaluate(afterApplying:)")
415
+    @available(watchOS, introduced: 3, deprecated: 5, renamed: "evaluate(afterApplying:)")
416
+    func validate(policy: SecPolicy, errorProducer: (_ status: OSStatus, _ result: SecTrustResultType) -> Error) throws {
417
+        try apply(policy: policy).af.validate(errorProducer: errorProducer)
418
+    }
419
+
420
+    /// Applies a `SecPolicy` to `self`, throwing if it fails.
421
+    ///
422
+    /// - Parameter policy: The `SecPolicy`.
423
+    ///
424
+    /// - Returns: `self`, with the policy applied.
425
+    /// - Throws: An `AFError.serverTrustEvaluationFailed` instance with a `.policyApplicationFailed` reason.
426
+    func apply(policy: SecPolicy) throws -> SecTrust {
427
+        let status = SecTrustSetPolicies(type, policy)
428
+
429
+        guard status.af.isSuccess else {
430
+            throw AFError.serverTrustEvaluationFailed(reason: .policyApplicationFailed(trust: type,
431
+                                                                                       policy: policy,
432
+                                                                                       status: status))
433
+        }
434
+
435
+        return type
436
+    }
437
+
438
+    /// Evaluate `self`, throwing an `Error` if evaluation fails.
439
+    ///
440
+    /// - Throws: `AFError.serverTrustEvaluationFailed` with reason `.trustValidationFailed` and associated error from
441
+    ///           the underlying evaluation.
442
+    @available(iOS 12, macOS 10.14, tvOS 12, watchOS 5, *)
443
+    func evaluate() throws {
444
+        var error: CFError?
445
+        let evaluationSucceeded = SecTrustEvaluateWithError(type, &error)
446
+
447
+        if !evaluationSucceeded {
448
+            throw AFError.serverTrustEvaluationFailed(reason: .trustEvaluationFailed(error: error))
449
+        }
450
+    }
451
+
452
+    /// Validate `self`, passing any failure values through `errorProducer`.
453
+    ///
454
+    /// - Parameter errorProducer: The closure used to transform the failed `OSStatus` and `SecTrustResultType` into an
455
+    ///                            `Error`.
456
+    /// - Throws:                  The `Error` produced by the `errorProducer` closure.
457
+    @available(iOS, introduced: 10, deprecated: 12, renamed: "evaluate()")
458
+    @available(macOS, introduced: 10.12, deprecated: 10.14, renamed: "evaluate()")
459
+    @available(tvOS, introduced: 10, deprecated: 12, renamed: "evaluate()")
460
+    @available(watchOS, introduced: 3, deprecated: 5, renamed: "evaluate()")
461
+    func validate(errorProducer: (_ status: OSStatus, _ result: SecTrustResultType) -> Error) throws {
462
+        var result = SecTrustResultType.invalid
463
+        let status = SecTrustEvaluate(type, &result)
464
+
465
+        guard status.af.isSuccess && result.af.isSuccess else {
466
+            throw errorProducer(status, result)
467
+        }
468
+    }
469
+
470
+    /// Sets a custom certificate chain on `self`, allowing full validation of a self-signed certificate and its chain.
471
+    ///
472
+    /// - Parameter certificates: The `SecCertificate`s to add to the chain.
473
+    /// - Throws:                 Any error produced when applying the new certificate chain.
474
+    func setAnchorCertificates(_ certificates: [SecCertificate]) throws {
475
+        // Add additional anchor certificates.
476
+        let status = SecTrustSetAnchorCertificates(type, certificates as CFArray)
477
+        guard status.af.isSuccess else {
478
+            throw AFError.serverTrustEvaluationFailed(reason: .settingAnchorCertificatesFailed(status: status,
479
+                                                                                               certificates: certificates))
480
+        }
481
+
482
+        // Reenable system anchor certificates.
483
+        let systemStatus = SecTrustSetAnchorCertificatesOnly(type, true)
484
+        guard systemStatus.af.isSuccess else {
485
+            throw AFError.serverTrustEvaluationFailed(reason: .settingAnchorCertificatesFailed(status: systemStatus,
486
+                                                                                               certificates: certificates))
487
+        }
488
+    }
489
+
490
+    /// The public keys contained in `self`.
491
+    var publicKeys: [SecKey] {
492
+        return certificates.af.publicKeys
493
+    }
494
+
495
+    /// The `SecCertificate`s contained i `self`.
496
+    var certificates: [SecCertificate] {
497
+        return (0..<SecTrustGetCertificateCount(type)).compactMap { index in
498
+            SecTrustGetCertificateAtIndex(type, index)
499
+        }
500
+    }
501
+
502
+    /// The `Data` values for all certificates contained in `self`.
503
+    var certificateData: [Data] {
504
+        return certificates.af.data
505
+    }
506
+
507
+    /// Validates `self` after applying `SecPolicy.af.default`. This evaluation does not validate the hostname.
508
+    ///
509
+    /// - Parameter host: The hostname, used only in the error output if validation fails.
510
+    /// - Throws: An `AFError.serverTrustEvaluationFailed` instance with a `.defaultEvaluationFailed` reason.
511
+    func performDefaultValidation(forHost host: String) throws {
512
+        if #available(iOS 12, macOS 10.14, tvOS 12, watchOS 5, *) {
513
+            try evaluate(afterApplying: SecPolicy.af.default)
514
+        } else {
515
+            try validate(policy: SecPolicy.af.default) { status, result in
516
+                AFError.serverTrustEvaluationFailed(reason: .defaultEvaluationFailed(output: .init(host, type, status, result)))
517
+            }
518
+        }
519
+    }
520
+
521
+    /// Validates `self` after applying `SecPolicy.af.hostname(host)`, which performs the default validation as well as
522
+    /// hostname validation.
523
+    ///
524
+    /// - Parameter host: The hostname to use in the validation.
525
+    /// - Throws:         An `AFError.serverTrustEvaluationFailed` instance with a `.defaultEvaluationFailed` reason.
526
+    func performValidation(forHost host: String) throws {
527
+        if #available(iOS 12, macOS 10.14, tvOS 12, watchOS 5, *) {
528
+            try evaluate(afterApplying: SecPolicy.af.hostname(host))
529
+        } else {
530
+            try validate(policy: SecPolicy.af.hostname(host)) { status, result in
531
+                AFError.serverTrustEvaluationFailed(reason: .hostValidationFailed(output: .init(host, type, status, result)))
532
+            }
533
+        }
534
+    }
535
+}
536
+
537
+extension SecPolicy: AlamofireExtended {}
538
+public extension AlamofireExtension where ExtendedType == SecPolicy {
539
+    /// Creates a `SecPolicy` instance which will validate server certificates but not require a host name match.
540
+    static let `default` = SecPolicyCreateSSL(true, nil)
541
+
542
+    /// Creates a `SecPolicy` instance which will validate server certificates and much match the provided hostname.
543
+    ///
544
+    /// - Parameter hostname: The hostname to validate against.
545
+    ///
546
+    /// - Returns:            The `SecPolicy`.
547
+    static func hostname(_ hostname: String) -> SecPolicy {
548
+        return SecPolicyCreateSSL(true, hostname as CFString)
549
+    }
550
+
551
+    /// Creates a `SecPolicy` which checks the revocation of certificates.
552
+    ///
553
+    /// - Parameter options: The `RevocationTrustEvaluator.Options` for evaluation.
554
+    ///
555
+    /// - Returns:           The `SecPolicy`.
556
+    /// - Throws:            An `AFError.serverTrustEvaluationFailed` error with reason `.revocationPolicyCreationFailed`
557
+    ///                      if the policy cannot be created.
558
+    static func revocation(options: RevocationTrustEvaluator.Options) throws -> SecPolicy {
559
+        guard let policy = SecPolicyCreateRevocation(options.rawValue) else {
560
+            throw AFError.serverTrustEvaluationFailed(reason: .revocationPolicyCreationFailed)
561
+        }
562
+
563
+        return policy
564
+    }
565
+}
566
+
567
+extension Array: AlamofireExtended {}
568
+public extension AlamofireExtension where ExtendedType == [SecCertificate] {
569
+    /// All `Data` values for the contained `SecCertificate`s.
570
+    var data: [Data] {
571
+        return type.map { SecCertificateCopyData($0) as Data }
572
+    }
573
+
574
+    /// All public `SecKey` values for the contained `SecCertificate`s.
575
+    var publicKeys: [SecKey] {
576
+        return type.compactMap { $0.af.publicKey }
577
+    }
578
+}
579
+
580
+extension SecCertificate: AlamofireExtended {}
581
+public extension AlamofireExtension where ExtendedType == SecCertificate {
582
+    /// The public key for `self`, if it can be extracted.
583
+    var publicKey: SecKey? {
584
+        let policy = SecPolicyCreateBasicX509()
585
+        var trust: SecTrust?
586
+        let trustCreationStatus = SecTrustCreateWithCertificates(type, policy, &trust)
587
+
588
+        guard let createdTrust = trust, trustCreationStatus == errSecSuccess else { return nil }
589
+
590
+        return SecTrustCopyPublicKey(createdTrust)
591
+    }
592
+}
593
+
594
+extension OSStatus: AlamofireExtended {}
595
+public extension AlamofireExtension where ExtendedType == OSStatus {
596
+    /// Returns whether `self` is `errSecSuccess`.
597
+    var isSuccess: Bool { return type == errSecSuccess }
598
+}
599
+
600
+extension SecTrustResultType: AlamofireExtended {}
601
+public extension AlamofireExtension where ExtendedType == SecTrustResultType {
602
+    /// Returns whether `self is `.unspecified` or `.proceed`.
603
+    var isSuccess: Bool {
604
+        return (type == .unspecified || type == .proceed)
605
+    }
606
+}

+ 1039
- 0
trolley/Pods/Alamofire/Source/Session.swift
文件差异内容过多而无法显示
查看文件


+ 305
- 0
trolley/Pods/Alamofire/Source/SessionDelegate.swift 查看文件

@@ -0,0 +1,305 @@
1
+//
2
+//  SessionDelegate.swift
3
+//
4
+//  Copyright (c) 2014-2018 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
+/// Class which implements the various `URLSessionDelegate` methods to connect various Alamofire features.
28
+open class SessionDelegate: NSObject {
29
+    private let fileManager: FileManager
30
+
31
+    weak var stateProvider: SessionStateProvider?
32
+    var eventMonitor: EventMonitor?
33
+
34
+    /// Creates an instance from the given `FileManager`.
35
+    ///
36
+    /// - Parameter fileManager: `FileManager` to use for underlying file management, such as moving downloaded files.
37
+    ///                          `.default` by default.
38
+    public init(fileManager: FileManager = .default) {
39
+        self.fileManager = fileManager
40
+    }
41
+}
42
+
43
+/// Type which provides various `Session` state values.
44
+protocol SessionStateProvider: AnyObject {
45
+    var serverTrustManager: ServerTrustManager? { get }
46
+    var redirectHandler: RedirectHandler? { get }
47
+    var cachedResponseHandler: CachedResponseHandler? { get }
48
+
49
+    func request(for task: URLSessionTask) -> Request?
50
+    func didGatherMetricsForTask(_ task: URLSessionTask)
51
+    func didCompleteTask(_ task: URLSessionTask)
52
+    func credential(for task: URLSessionTask, in protectionSpace: URLProtectionSpace) -> URLCredential?
53
+    func cancelRequestsForSessionInvalidation(with error: Error?)
54
+}
55
+
56
+// MARK: URLSessionDelegate
57
+
58
+extension SessionDelegate: URLSessionDelegate {
59
+    open func urlSession(_ session: URLSession, didBecomeInvalidWithError error: Error?) {
60
+        eventMonitor?.urlSession(session, didBecomeInvalidWithError: error)
61
+
62
+        stateProvider?.cancelRequestsForSessionInvalidation(with: error)
63
+    }
64
+}
65
+
66
+// MARK: URLSessionTaskDelegate
67
+
68
+extension SessionDelegate: URLSessionTaskDelegate {
69
+    /// Result of a `URLAuthenticationChallenge` evaluation.
70
+    typealias ChallengeEvaluation = (disposition: URLSession.AuthChallengeDisposition, credential: URLCredential?, error: AFError?)
71
+
72
+    open func urlSession(_ session: URLSession,
73
+                         task: URLSessionTask,
74
+                         didReceive challenge: URLAuthenticationChallenge,
75
+                         completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
76
+        eventMonitor?.urlSession(session, task: task, didReceive: challenge)
77
+
78
+        let evaluation: ChallengeEvaluation
79
+        switch challenge.protectionSpace.authenticationMethod {
80
+        case NSURLAuthenticationMethodServerTrust:
81
+            evaluation = attemptServerTrustAuthentication(with: challenge)
82
+        case NSURLAuthenticationMethodHTTPBasic, NSURLAuthenticationMethodHTTPDigest, NSURLAuthenticationMethodNTLM, NSURLAuthenticationMethodNegotiate:
83
+            evaluation = attemptCredentialAuthentication(for: challenge, belongingTo: task)
84
+        // case NSURLAuthenticationMethodClientCertificate:
85
+        // Alamofire doesn't currently support client certificate validation.
86
+        default:
87
+            evaluation = (.performDefaultHandling, nil, nil)
88
+        }
89
+
90
+        if let error = evaluation.error {
91
+            stateProvider?.request(for: task)?.didFailTask(task, earlyWithError: error)
92
+        }
93
+
94
+        completionHandler(evaluation.disposition, evaluation.credential)
95
+    }
96
+
97
+    /// Evaluates the server trust `URLAuthenticationChallenge` received.
98
+    ///
99
+    /// - Parameter challenge: The `URLAuthenticationChallenge`.
100
+    ///
101
+    /// - Returns:             The `ChallengeEvaluation`.
102
+    func attemptServerTrustAuthentication(with challenge: URLAuthenticationChallenge) -> ChallengeEvaluation {
103
+        let host = challenge.protectionSpace.host
104
+
105
+        guard challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust,
106
+            let trust = challenge.protectionSpace.serverTrust
107
+        else {
108
+            return (.performDefaultHandling, nil, nil)
109
+        }
110
+
111
+        do {
112
+            guard let evaluator = try stateProvider?.serverTrustManager?.serverTrustEvaluator(forHost: host) else {
113
+                return (.performDefaultHandling, nil, nil)
114
+            }
115
+
116
+            try evaluator.evaluate(trust, forHost: host)
117
+
118
+            return (.useCredential, URLCredential(trust: trust), nil)
119
+        } catch {
120
+            return (.cancelAuthenticationChallenge, nil, error.asAFError(or: .serverTrustEvaluationFailed(reason: .customEvaluationFailed(error: error))))
121
+        }
122
+    }
123
+
124
+    /// Evaluates the credential-based authentication `URLAuthenticationChallenge` received for `task`.
125
+    ///
126
+    /// - Parameters:
127
+    ///   - challenge: The `URLAuthenticationChallenge`.
128
+    ///   - task:      The `URLSessionTask` which received the challenge.
129
+    ///
130
+    /// - Returns:     The `ChallengeEvaluation`.
131
+    func attemptCredentialAuthentication(for challenge: URLAuthenticationChallenge,
132
+                                         belongingTo task: URLSessionTask) -> ChallengeEvaluation {
133
+        guard challenge.previousFailureCount == 0 else {
134
+            return (.rejectProtectionSpace, nil, nil)
135
+        }
136
+
137
+        guard let credential = stateProvider?.credential(for: task, in: challenge.protectionSpace) else {
138
+            return (.performDefaultHandling, nil, nil)
139
+        }
140
+
141
+        return (.useCredential, credential, nil)
142
+    }
143
+
144
+    open func urlSession(_ session: URLSession,
145
+                         task: URLSessionTask,
146
+                         didSendBodyData bytesSent: Int64,
147
+                         totalBytesSent: Int64,
148
+                         totalBytesExpectedToSend: Int64) {
149
+        eventMonitor?.urlSession(session,
150
+                                 task: task,
151
+                                 didSendBodyData: bytesSent,
152
+                                 totalBytesSent: totalBytesSent,
153
+                                 totalBytesExpectedToSend: totalBytesExpectedToSend)
154
+
155
+        stateProvider?.request(for: task)?.updateUploadProgress(totalBytesSent: totalBytesSent,
156
+                                                                totalBytesExpectedToSend: totalBytesExpectedToSend)
157
+    }
158
+
159
+    open func urlSession(_ session: URLSession,
160
+                         task: URLSessionTask,
161
+                         needNewBodyStream completionHandler: @escaping (InputStream?) -> Void) {
162
+        eventMonitor?.urlSession(session, taskNeedsNewBodyStream: task)
163
+
164
+        guard let request = stateProvider?.request(for: task) as? UploadRequest else {
165
+            fatalError("needNewBodyStream for request that isn't UploadRequest.")
166
+        }
167
+
168
+        completionHandler(request.inputStream())
169
+    }
170
+
171
+    open func urlSession(_ session: URLSession,
172
+                         task: URLSessionTask,
173
+                         willPerformHTTPRedirection response: HTTPURLResponse,
174
+                         newRequest request: URLRequest,
175
+                         completionHandler: @escaping (URLRequest?) -> Void) {
176
+        eventMonitor?.urlSession(session, task: task, willPerformHTTPRedirection: response, newRequest: request)
177
+
178
+        if let redirectHandler = stateProvider?.request(for: task)?.redirectHandler ?? stateProvider?.redirectHandler {
179
+            redirectHandler.task(task, willBeRedirectedTo: request, for: response, completion: completionHandler)
180
+        } else {
181
+            completionHandler(request)
182
+        }
183
+    }
184
+
185
+    open func urlSession(_ session: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics) {
186
+        eventMonitor?.urlSession(session, task: task, didFinishCollecting: metrics)
187
+
188
+        stateProvider?.request(for: task)?.didGatherMetrics(metrics)
189
+
190
+        stateProvider?.didGatherMetricsForTask(task)
191
+    }
192
+
193
+    open func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
194
+        eventMonitor?.urlSession(session, task: task, didCompleteWithError: error)
195
+
196
+        stateProvider?.request(for: task)?.didCompleteTask(task, with: error.map { $0.asAFError(or: .sessionTaskFailed(error: $0)) })
197
+
198
+        stateProvider?.didCompleteTask(task)
199
+    }
200
+
201
+    @available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
202
+    open func urlSession(_ session: URLSession, taskIsWaitingForConnectivity task: URLSessionTask) {
203
+        eventMonitor?.urlSession(session, taskIsWaitingForConnectivity: task)
204
+    }
205
+}
206
+
207
+// MARK: URLSessionDataDelegate
208
+
209
+extension SessionDelegate: URLSessionDataDelegate {
210
+    open func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
211
+        eventMonitor?.urlSession(session, dataTask: dataTask, didReceive: data)
212
+
213
+        guard let request = stateProvider?.request(for: dataTask) as? DataRequest else {
214
+            fatalError("dataTask received data for incorrect Request subclass: \(String(describing: stateProvider?.request(for: dataTask)))")
215
+        }
216
+
217
+        request.didReceive(data: data)
218
+    }
219
+
220
+    open func urlSession(_ session: URLSession,
221
+                         dataTask: URLSessionDataTask,
222
+                         willCacheResponse proposedResponse: CachedURLResponse,
223
+                         completionHandler: @escaping (CachedURLResponse?) -> Void) {
224
+        eventMonitor?.urlSession(session, dataTask: dataTask, willCacheResponse: proposedResponse)
225
+
226
+        if let handler = stateProvider?.request(for: dataTask)?.cachedResponseHandler ?? stateProvider?.cachedResponseHandler {
227
+            handler.dataTask(dataTask, willCacheResponse: proposedResponse, completion: completionHandler)
228
+        } else {
229
+            completionHandler(proposedResponse)
230
+        }
231
+    }
232
+}
233
+
234
+// MARK: URLSessionDownloadDelegate
235
+
236
+extension SessionDelegate: URLSessionDownloadDelegate {
237
+    open func urlSession(_ session: URLSession,
238
+                         downloadTask: URLSessionDownloadTask,
239
+                         didResumeAtOffset fileOffset: Int64,
240
+                         expectedTotalBytes: Int64) {
241
+        eventMonitor?.urlSession(session,
242
+                                 downloadTask: downloadTask,
243
+                                 didResumeAtOffset: fileOffset,
244
+                                 expectedTotalBytes: expectedTotalBytes)
245
+
246
+        guard let downloadRequest = stateProvider?.request(for: downloadTask) as? DownloadRequest else {
247
+            fatalError("No DownloadRequest found for downloadTask: \(downloadTask)")
248
+        }
249
+
250
+        downloadRequest.updateDownloadProgress(bytesWritten: fileOffset,
251
+                                               totalBytesExpectedToWrite: expectedTotalBytes)
252
+    }
253
+
254
+    open func urlSession(_ session: URLSession,
255
+                         downloadTask: URLSessionDownloadTask,
256
+                         didWriteData bytesWritten: Int64,
257
+                         totalBytesWritten: Int64,
258
+                         totalBytesExpectedToWrite: Int64) {
259
+        eventMonitor?.urlSession(session,
260
+                                 downloadTask: downloadTask,
261
+                                 didWriteData: bytesWritten,
262
+                                 totalBytesWritten: totalBytesWritten,
263
+                                 totalBytesExpectedToWrite: totalBytesExpectedToWrite)
264
+
265
+        guard let downloadRequest = stateProvider?.request(for: downloadTask) as? DownloadRequest else {
266
+            fatalError("No DownloadRequest found for downloadTask: \(downloadTask)")
267
+        }
268
+
269
+        downloadRequest.updateDownloadProgress(bytesWritten: bytesWritten,
270
+                                               totalBytesExpectedToWrite: totalBytesExpectedToWrite)
271
+    }
272
+
273
+    open func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
274
+        eventMonitor?.urlSession(session, downloadTask: downloadTask, didFinishDownloadingTo: location)
275
+
276
+        guard let request = stateProvider?.request(for: downloadTask) as? DownloadRequest else {
277
+            fatalError("Download finished but either no request found or request wasn't DownloadRequest")
278
+        }
279
+
280
+        guard let response = request.response else {
281
+            fatalError("URLSessionDownloadTask finished downloading with no response.")
282
+        }
283
+
284
+        let (destination, options) = (request.destination)(location, response)
285
+
286
+        eventMonitor?.request(request, didCreateDestinationURL: destination)
287
+
288
+        do {
289
+            if options.contains(.removePreviousFile), fileManager.fileExists(atPath: destination.path) {
290
+                try fileManager.removeItem(at: destination)
291
+            }
292
+
293
+            if options.contains(.createIntermediateDirectories) {
294
+                let directory = destination.deletingLastPathComponent()
295
+                try fileManager.createDirectory(at: directory, withIntermediateDirectories: true)
296
+            }
297
+
298
+            try fileManager.moveItem(at: location, to: destination)
299
+
300
+            request.didFinishDownloading(using: downloadTask, with: .success(destination))
301
+        } catch {
302
+            request.didFinishDownloading(using: downloadTask, with: .failure(.downloadedFileMoveFailed(error: error, source: location, destination: destination)))
303
+        }
304
+    }
305
+}

+ 105
- 0
trolley/Pods/Alamofire/Source/URLConvertible+URLRequestConvertible.swift 查看文件

@@ -0,0 +1,105 @@
1
+//
2
+//  URLConvertible+URLRequestConvertible.swift
3
+//
4
+//  Copyright (c) 2014-2018 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
+/// Types adopting the `URLConvertible` protocol can be used to construct `URL`s, which can then be used to construct
28
+/// `URLRequests`.
29
+public protocol URLConvertible {
30
+    /// Returns a `URL` from the conforming instance or throws.
31
+    ///
32
+    /// - Returns: The `URL` created from the instance.
33
+    /// - Throws:  Any error thrown while creating the `URL`.
34
+    func asURL() throws -> URL
35
+}
36
+
37
+extension String: URLConvertible {
38
+    /// Returns a `URL` if `self` can be used to initialize a `URL` instance, otherwise throws.
39
+    ///
40
+    /// - Returns: The `URL` initialized with `self`.
41
+    /// - Throws:  An `AFError.invalidURL` instance.
42
+    public func asURL() throws -> URL {
43
+        guard let url = URL(string: self) else { throw AFError.invalidURL(url: self) }
44
+
45
+        return url
46
+    }
47
+}
48
+
49
+extension URL: URLConvertible {
50
+    /// Returns `self`.
51
+    public func asURL() throws -> URL { return self }
52
+}
53
+
54
+extension URLComponents: URLConvertible {
55
+    /// Returns a `URL` if the `self`'s `url` is not nil, otherwise throws.
56
+    ///
57
+    /// - Returns: The `URL` from the `url` property.
58
+    /// - Throws:  An `AFError.invalidURL` instance.
59
+    public func asURL() throws -> URL {
60
+        guard let url = url else { throw AFError.invalidURL(url: self) }
61
+
62
+        return url
63
+    }
64
+}
65
+
66
+// MARK: -
67
+
68
+/// Types adopting the `URLRequestConvertible` protocol can be used to safely construct `URLRequest`s.
69
+public protocol URLRequestConvertible {
70
+    /// Returns a `URLRequest` or throws if an `Error` was encountered.
71
+    ///
72
+    /// - Returns: A `URLRequest`.
73
+    /// - Throws:  Any error thrown while constructing the `URLRequest`.
74
+    func asURLRequest() throws -> URLRequest
75
+}
76
+
77
+extension URLRequestConvertible {
78
+    /// The `URLRequest` returned by discarding any `Error` encountered.
79
+    public var urlRequest: URLRequest? { return try? asURLRequest() }
80
+}
81
+
82
+extension URLRequest: URLRequestConvertible {
83
+    /// Returns `self`.
84
+    public func asURLRequest() throws -> URLRequest { return self }
85
+}
86
+
87
+// MARK: -
88
+
89
+extension URLRequest {
90
+    /// Creates an instance with the specified `url`, `method`, and `headers`.
91
+    ///
92
+    /// - Parameters:
93
+    ///   - url:     The `URLConvertible` value.
94
+    ///   - method:  The `HTTPMethod`.
95
+    ///   - headers: The `HTTPHeaders`, `nil` by default.
96
+    /// - Throws:    Any error thrown while converting the `URLConvertible` to a `URL`.
97
+    public init(url: URLConvertible, method: HTTPMethod, headers: HTTPHeaders? = nil) throws {
98
+        let url = try url.asURL()
99
+
100
+        self.init(url: url)
101
+
102
+        httpMethod = method.rawValue
103
+        allHTTPHeaderFields = headers?.dictionary
104
+    }
105
+}

+ 973
- 0
trolley/Pods/Alamofire/Source/URLEncodedFormEncoder.swift 查看文件

@@ -0,0 +1,973 @@
1
+//
2
+//  URLEncodedFormEncoder.swift
3
+//
4
+//  Copyright (c) 2019 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
+/// An object that encodes instances into URL-encoded query strings.
28
+///
29
+/// There is no published specification for how to encode collection types. By default, the convention of appending
30
+/// `[]` to the key for array values (`foo[]=1&foo[]=2`), and appending the key surrounded by square brackets for
31
+/// nested dictionary values (`foo[bar]=baz`) is used. Optionally, `ArrayEncoding` can be used to omit the
32
+/// square brackets appended to array keys.
33
+///
34
+/// `BoolEncoding` can be used to configure how `Bool` values are encoded. The default behavior is to encode
35
+/// `true` as 1 and `false` as 0.
36
+///
37
+/// `DateEncoding` can be used to configure how `Date` values are encoded. By default, the `.deferredToDate`
38
+/// strategy is used, which formats dates from their structure.
39
+///
40
+/// `SpaceEncoding` can be used to configure how spaces are encoded. Modern encodings use percent replacement (`%20`),
41
+/// while older encodings may expect spaces to be replaced with `+`.
42
+///
43
+/// This type is largely based on Vapor's [`url-encoded-form`](https://github.com/vapor/url-encoded-form) project.
44
+public final class URLEncodedFormEncoder {
45
+    /// Encoding to use for `Array` values.
46
+    public enum ArrayEncoding {
47
+        /// An empty set of square brackets ("[]") are appended to the key for every value. This is the default encoding.
48
+        case brackets
49
+        /// No brackets are appended to the key and the key is encoded as is.
50
+        case noBrackets
51
+
52
+        /// Encodes the key according to the encoding.
53
+        ///
54
+        /// - Parameter key: The `key` to encode.
55
+        /// - Returns:       The encoded key.
56
+        func encode(_ key: String) -> String {
57
+            switch self {
58
+            case .brackets: return "\(key)[]"
59
+            case .noBrackets: return key
60
+            }
61
+        }
62
+    }
63
+
64
+    /// Encoding to use for `Bool` values.
65
+    public enum BoolEncoding {
66
+        /// Encodes `true` as `1`, `false` as `0`.
67
+        case numeric
68
+        /// Encodes `true` as "true", `false` as "false". This is the default encoding.
69
+        case literal
70
+
71
+        /// Encodes the given `Bool` as a `String`.
72
+        ///
73
+        /// - Parameter value: The `Bool` to encode.
74
+        ///
75
+        /// - Returns:         The encoded `String`.
76
+        func encode(_ value: Bool) -> String {
77
+            switch self {
78
+            case .numeric: return value ? "1" : "0"
79
+            case .literal: return value ? "true" : "false"
80
+            }
81
+        }
82
+    }
83
+
84
+    /// Encoding to use for `Data` values.
85
+    public enum DataEncoding {
86
+        /// Defers encoding to the `Data` type.
87
+        case deferredToData
88
+        /// Encodes `Data` as a Base64-encoded string. This is the default encoding.
89
+        case base64
90
+        /// Encode the `Data` as a custom value encoded by the given closure.
91
+        case custom((Data) throws -> String)
92
+
93
+        /// Encodes `Data` according to the encoding.
94
+        ///
95
+        /// - Parameter data: The `Data` to encode.
96
+        ///
97
+        /// - Returns:        The encoded `String`, or `nil` if the `Data` should be encoded according to its
98
+        ///                   `Encodable` implementation.
99
+        func encode(_ data: Data) throws -> String? {
100
+            switch self {
101
+            case .deferredToData: return nil
102
+            case .base64: return data.base64EncodedString()
103
+            case let .custom(encoding): return try encoding(data)
104
+            }
105
+        }
106
+    }
107
+
108
+    /// Encoding to use for `Date` values.
109
+    public enum DateEncoding {
110
+        /// ISO8601 and RFC3339 formatter.
111
+        private static let iso8601Formatter: ISO8601DateFormatter = {
112
+            let formatter = ISO8601DateFormatter()
113
+            formatter.formatOptions = .withInternetDateTime
114
+            return formatter
115
+        }()
116
+
117
+        /// Defers encoding to the `Date` type. This is the default encoding.
118
+        case deferredToDate
119
+        /// Encodes `Date`s as seconds since midnight UTC on January 1, 1970.
120
+        case secondsSince1970
121
+        /// Encodes `Date`s as milliseconds since midnight UTC on January 1, 1970.
122
+        case millisecondsSince1970
123
+        /// Encodes `Date`s according to the ISO8601 and RFC3339 standards.
124
+        case iso8601
125
+        /// Encodes `Date`s using the given `DateFormatter`.
126
+        case formatted(DateFormatter)
127
+        /// Encodes `Date`s using the given closure.
128
+        case custom((Date) throws -> String)
129
+
130
+        /// Encodes the date according to the encoding.
131
+        ///
132
+        /// - Parameter date: The `Date` to encode.
133
+        ///
134
+        /// - Returns:        The encoded `String`, or `nil` if the `Date` should be encoded according to its
135
+        ///                   `Encodable` implementation.
136
+        func encode(_ date: Date) throws -> String? {
137
+            switch self {
138
+            case .deferredToDate:
139
+                return nil
140
+            case .secondsSince1970:
141
+                return String(date.timeIntervalSince1970)
142
+            case .millisecondsSince1970:
143
+                return String(date.timeIntervalSince1970 * 1000.0)
144
+            case .iso8601:
145
+                return DateEncoding.iso8601Formatter.string(from: date)
146
+            case let .formatted(formatter):
147
+                return formatter.string(from: date)
148
+            case let .custom(closure):
149
+                return try closure(date)
150
+            }
151
+        }
152
+    }
153
+
154
+    /// Encoding to use for keys.
155
+    ///
156
+    /// This type is derived from [`JSONEncoder`'s `KeyEncodingStrategy`](https://github.com/apple/swift/blob/6aa313b8dd5f05135f7f878eccc1db6f9fbe34ff/stdlib/public/Darwin/Foundation/JSONEncoder.swift#L128)
157
+    /// and [`XMLEncoder`s `KeyEncodingStrategy`](https://github.com/MaxDesiatov/XMLCoder/blob/master/Sources/XMLCoder/Encoder/XMLEncoder.swift#L102).
158
+    public enum KeyEncoding {
159
+        /// Use the keys specified by each type. This is the default encoding.
160
+        case useDefaultKeys
161
+        /// Convert from "camelCaseKeys" to "snake_case_keys" before writing a key.
162
+        ///
163
+        /// Capital characters are determined by testing membership in
164
+        /// `CharacterSet.uppercaseLetters` and `CharacterSet.lowercaseLetters`
165
+        /// (Unicode General Categories Lu and Lt).
166
+        /// The conversion to lower case uses `Locale.system`, also known as
167
+        /// the ICU "root" locale. This means the result is consistent
168
+        /// regardless of the current user's locale and language preferences.
169
+        ///
170
+        /// Converting from camel case to snake case:
171
+        /// 1. Splits words at the boundary of lower-case to upper-case
172
+        /// 2. Inserts `_` between words
173
+        /// 3. Lowercases the entire string
174
+        /// 4. Preserves starting and ending `_`.
175
+        ///
176
+        /// For example, `oneTwoThree` becomes `one_two_three`. `_oneTwoThree_` becomes `_one_two_three_`.
177
+        ///
178
+        /// - Note: Using a key encoding strategy has a nominal performance cost, as each string key has to be converted.
179
+        case convertToSnakeCase
180
+        /// Same as convertToSnakeCase, but using `-` instead of `_`.
181
+        /// For example `oneTwoThree` becomes `one-two-three`.
182
+        case convertToKebabCase
183
+        /// Capitalize the first letter only.
184
+        /// For example `oneTwoThree` becomes  `OneTwoThree`.
185
+        case capitalized
186
+        /// Uppercase all letters.
187
+        /// For example `oneTwoThree` becomes  `ONETWOTHREE`.
188
+        case uppercased
189
+        /// Lowercase all letters.
190
+        /// For example `oneTwoThree` becomes  `onetwothree`.
191
+        case lowercased
192
+        /// A custom encoding using the provided closure.
193
+        case custom((String) -> String)
194
+
195
+        func encode(_ key: String) -> String {
196
+            switch self {
197
+            case .useDefaultKeys: return key
198
+            case .convertToSnakeCase: return convertToSnakeCase(key)
199
+            case .convertToKebabCase: return convertToKebabCase(key)
200
+            case .capitalized: return String(key.prefix(1).uppercased() + key.dropFirst())
201
+            case .uppercased: return key.uppercased()
202
+            case .lowercased: return key.lowercased()
203
+            case let .custom(encoding): return encoding(key)
204
+            }
205
+        }
206
+
207
+        private func convertToSnakeCase(_ key: String) -> String {
208
+            return convert(key, usingSeparator: "_")
209
+        }
210
+
211
+        private func convertToKebabCase(_ key: String) -> String {
212
+            return convert(key, usingSeparator: "-")
213
+        }
214
+
215
+        private func convert(_ key: String, usingSeparator separator: String) -> String {
216
+            guard !key.isEmpty else { return key }
217
+
218
+            var words: [Range<String.Index>] = []
219
+            // The general idea of this algorithm is to split words on
220
+            // transition from lower to upper case, then on transition of >1
221
+            // upper case characters to lowercase
222
+            //
223
+            // myProperty -> my_property
224
+            // myURLProperty -> my_url_property
225
+            //
226
+            // It is assumed, per Swift naming conventions, that the first character of the key is lowercase.
227
+            var wordStart = key.startIndex
228
+            var searchRange = key.index(after: wordStart)..<key.endIndex
229
+
230
+            // Find next uppercase character
231
+            while let upperCaseRange = key.rangeOfCharacter(from: CharacterSet.uppercaseLetters, options: [], range: searchRange) {
232
+                let untilUpperCase = wordStart..<upperCaseRange.lowerBound
233
+                words.append(untilUpperCase)
234
+
235
+                // Find next lowercase character
236
+                searchRange = upperCaseRange.lowerBound..<searchRange.upperBound
237
+                guard let lowerCaseRange = key.rangeOfCharacter(from: CharacterSet.lowercaseLetters, options: [], range: searchRange) else {
238
+                    // There are no more lower case letters. Just end here.
239
+                    wordStart = searchRange.lowerBound
240
+                    break
241
+                }
242
+
243
+                // Is the next lowercase letter more than 1 after the uppercase?
244
+                // If so, we encountered a group of uppercase letters that we
245
+                // should treat as its own word
246
+                let nextCharacterAfterCapital = key.index(after: upperCaseRange.lowerBound)
247
+                if lowerCaseRange.lowerBound == nextCharacterAfterCapital {
248
+                    // The next character after capital is a lower case character and therefore not a word boundary.
249
+                    // Continue searching for the next upper case for the boundary.
250
+                    wordStart = upperCaseRange.lowerBound
251
+                } else {
252
+                    // There was a range of >1 capital letters. Turn those into a word, stopping at the capital before the lower case character.
253
+                    let beforeLowerIndex = key.index(before: lowerCaseRange.lowerBound)
254
+                    words.append(upperCaseRange.lowerBound..<beforeLowerIndex)
255
+
256
+                    // Next word starts at the capital before the lowercase we just found
257
+                    wordStart = beforeLowerIndex
258
+                }
259
+                searchRange = lowerCaseRange.upperBound..<searchRange.upperBound
260
+            }
261
+            words.append(wordStart..<searchRange.upperBound)
262
+            let result = words.map { range in
263
+                key[range].lowercased()
264
+            }.joined(separator: separator)
265
+
266
+            return result
267
+        }
268
+    }
269
+
270
+    /// Encoding to use for spaces.
271
+    public enum SpaceEncoding {
272
+        /// Encodes spaces according to normal percent escaping rules (%20).
273
+        case percentEscaped
274
+        /// Encodes spaces as `+`,
275
+        case plusReplaced
276
+
277
+        /// Encodes the string according to the encoding.
278
+        ///
279
+        /// - Parameter string: The `String` to encode.
280
+        ///
281
+        /// - Returns:          The encoded `String`.
282
+        func encode(_ string: String) -> String {
283
+            switch self {
284
+            case .percentEscaped: return string.replacingOccurrences(of: " ", with: "%20")
285
+            case .plusReplaced: return string.replacingOccurrences(of: " ", with: "+")
286
+            }
287
+        }
288
+    }
289
+
290
+    /// `URLEncodedFormEncoder` error.
291
+    public enum Error: Swift.Error {
292
+        /// An invalid root object was created by the encoder. Only keyed values are valid.
293
+        case invalidRootObject(String)
294
+
295
+        var localizedDescription: String {
296
+            switch self {
297
+            case let .invalidRootObject(object):
298
+                return "URLEncodedFormEncoder requires keyed root object. Received \(object) instead."
299
+            }
300
+        }
301
+    }
302
+
303
+    /// Whether or not to sort the encoded key value pairs.
304
+    ///
305
+    /// - Note: This setting ensures a consistent ordering for all encodings of the same parameters. When set to `false`,
306
+    ///         encoded `Dictionary` values may have a different encoded order each time they're encoded due to
307
+    ///       ` Dictionary`'s random storage order, but `Encodable` types will maintain their encoded order.
308
+    public let alphabetizeKeyValuePairs: Bool
309
+    /// The `ArrayEncoding` to use.
310
+    public let arrayEncoding: ArrayEncoding
311
+    /// The `BoolEncoding` to use.
312
+    public let boolEncoding: BoolEncoding
313
+    /// THe `DataEncoding` to use.
314
+    public let dataEncoding: DataEncoding
315
+    /// The `DateEncoding` to use.
316
+    public let dateEncoding: DateEncoding
317
+    /// The `KeyEncoding` to use.
318
+    public let keyEncoding: KeyEncoding
319
+    /// The `SpaceEncoding` to use.
320
+    public let spaceEncoding: SpaceEncoding
321
+    /// The `CharacterSet` of allowed (non-escaped) characters.
322
+    public var allowedCharacters: CharacterSet
323
+
324
+    /// Creates an instance from the supplied parameters.
325
+    ///
326
+    /// - Parameters:
327
+    ///   - alphabetizeKeyValuePairs: Whether or not to sort the encoded key value pairs. `true` by default.
328
+    ///   - arrayEncoding:            The `ArrayEncoding` to use. `.brackets` by default.
329
+    ///   - boolEncoding:             The `BoolEncoding` to use. `.numeric` by default.
330
+    ///   - dataEncoding:             The `DataEncoding` to use. `.base64` by default.
331
+    ///   - dateEncoding:             The `DateEncoding` to use. `.deferredToDate` by default.
332
+    ///   - keyEncoding:              The `KeyEncoding` to use. `.useDefaultKeys` by default.
333
+    ///   - spaceEncoding:            The `SpaceEncoding` to use. `.percentEscaped` by default.
334
+    ///   - allowedCharacters:        The `CharacterSet` of allowed (non-escaped) characters. `.afURLQueryAllowed` by
335
+    ///                               default.
336
+    public init(alphabetizeKeyValuePairs: Bool = true,
337
+                arrayEncoding: ArrayEncoding = .brackets,
338
+                boolEncoding: BoolEncoding = .numeric,
339
+                dataEncoding: DataEncoding = .base64,
340
+                dateEncoding: DateEncoding = .deferredToDate,
341
+                keyEncoding: KeyEncoding = .useDefaultKeys,
342
+                spaceEncoding: SpaceEncoding = .percentEscaped,
343
+                allowedCharacters: CharacterSet = .afURLQueryAllowed) {
344
+        self.alphabetizeKeyValuePairs = alphabetizeKeyValuePairs
345
+        self.arrayEncoding = arrayEncoding
346
+        self.boolEncoding = boolEncoding
347
+        self.dataEncoding = dataEncoding
348
+        self.dateEncoding = dateEncoding
349
+        self.keyEncoding = keyEncoding
350
+        self.spaceEncoding = spaceEncoding
351
+        self.allowedCharacters = allowedCharacters
352
+    }
353
+
354
+    func encode(_ value: Encodable) throws -> URLEncodedFormComponent {
355
+        let context = URLEncodedFormContext(.object([]))
356
+        let encoder = _URLEncodedFormEncoder(context: context,
357
+                                             boolEncoding: boolEncoding,
358
+                                             dataEncoding: dataEncoding,
359
+                                             dateEncoding: dateEncoding)
360
+        try value.encode(to: encoder)
361
+
362
+        return context.component
363
+    }
364
+
365
+    /// Encodes the `value` as a URL form encoded `String`.
366
+    ///
367
+    /// - Parameter value: The `Encodable` value.`
368
+    ///
369
+    /// - Returns:         The encoded `String`.
370
+    /// - Throws:          An `Error` or `EncodingError` instance if encoding fails.
371
+    public func encode(_ value: Encodable) throws -> String {
372
+        let component: URLEncodedFormComponent = try encode(value)
373
+
374
+        guard case let .object(object) = component else {
375
+            throw Error.invalidRootObject("\(component)")
376
+        }
377
+
378
+        let serializer = URLEncodedFormSerializer(alphabetizeKeyValuePairs: alphabetizeKeyValuePairs,
379
+                                                  arrayEncoding: arrayEncoding,
380
+                                                  keyEncoding: keyEncoding,
381
+                                                  spaceEncoding: spaceEncoding,
382
+                                                  allowedCharacters: allowedCharacters)
383
+        let query = serializer.serialize(object)
384
+
385
+        return query
386
+    }
387
+
388
+    /// Encodes the value as `Data`. This is performed by first creating an encoded `String` and then returning the
389
+    /// `.utf8` data.
390
+    ///
391
+    /// - Parameter value: The `Encodable` value.
392
+    ///
393
+    /// - Returns:         The encoded `Data`.
394
+    ///
395
+    /// - Throws:          An `Error` or `EncodingError` instance if encoding fails.
396
+    public func encode(_ value: Encodable) throws -> Data {
397
+        let string: String = try encode(value)
398
+
399
+        return Data(string.utf8)
400
+    }
401
+}
402
+
403
+final class _URLEncodedFormEncoder {
404
+    var codingPath: [CodingKey]
405
+    // Returns an empty dictionary, as this encoder doesn't support userInfo.
406
+    var userInfo: [CodingUserInfoKey: Any] { return [:] }
407
+
408
+    let context: URLEncodedFormContext
409
+
410
+    private let boolEncoding: URLEncodedFormEncoder.BoolEncoding
411
+    private let dataEncoding: URLEncodedFormEncoder.DataEncoding
412
+    private let dateEncoding: URLEncodedFormEncoder.DateEncoding
413
+
414
+    public init(context: URLEncodedFormContext,
415
+                codingPath: [CodingKey] = [],
416
+                boolEncoding: URLEncodedFormEncoder.BoolEncoding,
417
+                dataEncoding: URLEncodedFormEncoder.DataEncoding,
418
+                dateEncoding: URLEncodedFormEncoder.DateEncoding) {
419
+        self.context = context
420
+        self.codingPath = codingPath
421
+        self.boolEncoding = boolEncoding
422
+        self.dataEncoding = dataEncoding
423
+        self.dateEncoding = dateEncoding
424
+    }
425
+}
426
+
427
+extension _URLEncodedFormEncoder: Encoder {
428
+    func container<Key>(keyedBy type: Key.Type) -> KeyedEncodingContainer<Key> where Key: CodingKey {
429
+        let container = _URLEncodedFormEncoder.KeyedContainer<Key>(context: context,
430
+                                                                   codingPath: codingPath,
431
+                                                                   boolEncoding: boolEncoding,
432
+                                                                   dataEncoding: dataEncoding,
433
+                                                                   dateEncoding: dateEncoding)
434
+        return KeyedEncodingContainer(container)
435
+    }
436
+
437
+    func unkeyedContainer() -> UnkeyedEncodingContainer {
438
+        return _URLEncodedFormEncoder.UnkeyedContainer(context: context,
439
+                                                       codingPath: codingPath,
440
+                                                       boolEncoding: boolEncoding,
441
+                                                       dataEncoding: dataEncoding,
442
+                                                       dateEncoding: dateEncoding)
443
+    }
444
+
445
+    func singleValueContainer() -> SingleValueEncodingContainer {
446
+        return _URLEncodedFormEncoder.SingleValueContainer(context: context,
447
+                                                           codingPath: codingPath,
448
+                                                           boolEncoding: boolEncoding,
449
+                                                           dataEncoding: dataEncoding,
450
+                                                           dateEncoding: dateEncoding)
451
+    }
452
+}
453
+
454
+final class URLEncodedFormContext {
455
+    var component: URLEncodedFormComponent
456
+
457
+    init(_ component: URLEncodedFormComponent) {
458
+        self.component = component
459
+    }
460
+}
461
+
462
+enum URLEncodedFormComponent {
463
+    typealias Object = [(key: String, value: URLEncodedFormComponent)]
464
+
465
+    case string(String)
466
+    case array([URLEncodedFormComponent])
467
+    case object(Object)
468
+
469
+    /// Converts self to an `[URLEncodedFormData]` or returns `nil` if not convertible.
470
+    var array: [URLEncodedFormComponent]? {
471
+        switch self {
472
+        case let .array(array): return array
473
+        default: return nil
474
+        }
475
+    }
476
+
477
+    /// Converts self to an `Object` or returns `nil` if not convertible.
478
+    var object: Object? {
479
+        switch self {
480
+        case let .object(object): return object
481
+        default: return nil
482
+        }
483
+    }
484
+
485
+    /// Sets self to the supplied value at a given path.
486
+    ///
487
+    ///     data.set(to: "hello", at: ["path", "to", "value"])
488
+    ///
489
+    /// - parameters:
490
+    ///     - value: Value of `Self` to set at the supplied path.
491
+    ///     - path: `CodingKey` path to update with the supplied value.
492
+    public mutating func set(to value: URLEncodedFormComponent, at path: [CodingKey]) {
493
+        set(&self, to: value, at: path)
494
+    }
495
+
496
+    /// Recursive backing method to `set(to:at:)`.
497
+    private func set(_ context: inout URLEncodedFormComponent, to value: URLEncodedFormComponent, at path: [CodingKey]) {
498
+        guard path.count >= 1 else {
499
+            context = value
500
+            return
501
+        }
502
+
503
+        let end = path[0]
504
+        var child: URLEncodedFormComponent
505
+        switch path.count {
506
+        case 1:
507
+            child = value
508
+        case 2...:
509
+            if let index = end.intValue {
510
+                let array = context.array ?? []
511
+                if array.count > index {
512
+                    child = array[index]
513
+                } else {
514
+                    child = .array([])
515
+                }
516
+                set(&child, to: value, at: Array(path[1...]))
517
+            } else {
518
+                child = context.object?.first { $0.key == end.stringValue }?.value ?? .object(.init())
519
+                set(&child, to: value, at: Array(path[1...]))
520
+            }
521
+        default: fatalError("Unreachable")
522
+        }
523
+
524
+        if let index = end.intValue {
525
+            if var array = context.array {
526
+                if array.count > index {
527
+                    array[index] = child
528
+                } else {
529
+                    array.append(child)
530
+                }
531
+                context = .array(array)
532
+            } else {
533
+                context = .array([child])
534
+            }
535
+        } else {
536
+            if var object = context.object {
537
+                if let index = object.firstIndex(where: { $0.key == end.stringValue }) {
538
+                    object[index] = (key: end.stringValue, value: child)
539
+                } else {
540
+                    object.append((key: end.stringValue, value: child))
541
+                }
542
+                context = .object(object)
543
+            } else {
544
+                context = .object([(key: end.stringValue, value: child)])
545
+            }
546
+        }
547
+    }
548
+}
549
+
550
+struct AnyCodingKey: CodingKey, Hashable {
551
+    let stringValue: String
552
+    let intValue: Int?
553
+
554
+    init?(stringValue: String) {
555
+        self.stringValue = stringValue
556
+        intValue = nil
557
+    }
558
+
559
+    init?(intValue: Int) {
560
+        stringValue = "\(intValue)"
561
+        self.intValue = intValue
562
+    }
563
+
564
+    init<Key>(_ base: Key) where Key: CodingKey {
565
+        if let intValue = base.intValue {
566
+            self.init(intValue: intValue)!
567
+        } else {
568
+            self.init(stringValue: base.stringValue)!
569
+        }
570
+    }
571
+}
572
+
573
+extension _URLEncodedFormEncoder {
574
+    final class KeyedContainer<Key> where Key: CodingKey {
575
+        var codingPath: [CodingKey]
576
+
577
+        private let context: URLEncodedFormContext
578
+        private let boolEncoding: URLEncodedFormEncoder.BoolEncoding
579
+        private let dataEncoding: URLEncodedFormEncoder.DataEncoding
580
+        private let dateEncoding: URLEncodedFormEncoder.DateEncoding
581
+
582
+        init(context: URLEncodedFormContext,
583
+             codingPath: [CodingKey],
584
+             boolEncoding: URLEncodedFormEncoder.BoolEncoding,
585
+             dataEncoding: URLEncodedFormEncoder.DataEncoding,
586
+             dateEncoding: URLEncodedFormEncoder.DateEncoding) {
587
+            self.context = context
588
+            self.codingPath = codingPath
589
+            self.boolEncoding = boolEncoding
590
+            self.dataEncoding = dataEncoding
591
+            self.dateEncoding = dateEncoding
592
+        }
593
+
594
+        private func nestedCodingPath(for key: CodingKey) -> [CodingKey] {
595
+            return codingPath + [key]
596
+        }
597
+    }
598
+}
599
+
600
+extension _URLEncodedFormEncoder.KeyedContainer: KeyedEncodingContainerProtocol {
601
+    func encodeNil(forKey key: Key) throws {
602
+        let context = EncodingError.Context(codingPath: codingPath,
603
+                                            debugDescription: "URLEncodedFormEncoder cannot encode nil values.")
604
+        throw EncodingError.invalidValue("\(key): nil", context)
605
+    }
606
+
607
+    func encode<T>(_ value: T, forKey key: Key) throws where T: Encodable {
608
+        var container = nestedSingleValueEncoder(for: key)
609
+        try container.encode(value)
610
+    }
611
+
612
+    func nestedSingleValueEncoder(for key: Key) -> SingleValueEncodingContainer {
613
+        let container = _URLEncodedFormEncoder.SingleValueContainer(context: context,
614
+                                                                    codingPath: nestedCodingPath(for: key),
615
+                                                                    boolEncoding: boolEncoding,
616
+                                                                    dataEncoding: dataEncoding,
617
+                                                                    dateEncoding: dateEncoding)
618
+
619
+        return container
620
+    }
621
+
622
+    func nestedUnkeyedContainer(forKey key: Key) -> UnkeyedEncodingContainer {
623
+        let container = _URLEncodedFormEncoder.UnkeyedContainer(context: context,
624
+                                                                codingPath: nestedCodingPath(for: key),
625
+                                                                boolEncoding: boolEncoding,
626
+                                                                dataEncoding: dataEncoding,
627
+                                                                dateEncoding: dateEncoding)
628
+
629
+        return container
630
+    }
631
+
632
+    func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type, forKey key: Key) -> KeyedEncodingContainer<NestedKey> where NestedKey: CodingKey {
633
+        let container = _URLEncodedFormEncoder.KeyedContainer<NestedKey>(context: context,
634
+                                                                         codingPath: nestedCodingPath(for: key),
635
+                                                                         boolEncoding: boolEncoding,
636
+                                                                         dataEncoding: dataEncoding,
637
+                                                                         dateEncoding: dateEncoding)
638
+
639
+        return KeyedEncodingContainer(container)
640
+    }
641
+
642
+    func superEncoder() -> Encoder {
643
+        return _URLEncodedFormEncoder(context: context,
644
+                                      codingPath: codingPath,
645
+                                      boolEncoding: boolEncoding,
646
+                                      dataEncoding: dataEncoding,
647
+                                      dateEncoding: dateEncoding)
648
+    }
649
+
650
+    func superEncoder(forKey key: Key) -> Encoder {
651
+        return _URLEncodedFormEncoder(context: context,
652
+                                      codingPath: nestedCodingPath(for: key),
653
+                                      boolEncoding: boolEncoding,
654
+                                      dataEncoding: dataEncoding,
655
+                                      dateEncoding: dateEncoding)
656
+    }
657
+}
658
+
659
+extension _URLEncodedFormEncoder {
660
+    final class SingleValueContainer {
661
+        var codingPath: [CodingKey]
662
+
663
+        private var canEncodeNewValue = true
664
+
665
+        private let context: URLEncodedFormContext
666
+        private let boolEncoding: URLEncodedFormEncoder.BoolEncoding
667
+        private let dataEncoding: URLEncodedFormEncoder.DataEncoding
668
+        private let dateEncoding: URLEncodedFormEncoder.DateEncoding
669
+
670
+        init(context: URLEncodedFormContext,
671
+             codingPath: [CodingKey],
672
+             boolEncoding: URLEncodedFormEncoder.BoolEncoding,
673
+             dataEncoding: URLEncodedFormEncoder.DataEncoding,
674
+             dateEncoding: URLEncodedFormEncoder.DateEncoding) {
675
+            self.context = context
676
+            self.codingPath = codingPath
677
+            self.boolEncoding = boolEncoding
678
+            self.dataEncoding = dataEncoding
679
+            self.dateEncoding = dateEncoding
680
+        }
681
+
682
+        private func checkCanEncode(value: Any?) throws {
683
+            guard canEncodeNewValue else {
684
+                let context = EncodingError.Context(codingPath: codingPath,
685
+                                                    debugDescription: "Attempt to encode value through single value container when previously value already encoded.")
686
+                throw EncodingError.invalidValue(value as Any, context)
687
+            }
688
+        }
689
+    }
690
+}
691
+
692
+extension _URLEncodedFormEncoder.SingleValueContainer: SingleValueEncodingContainer {
693
+    func encodeNil() throws {
694
+        try checkCanEncode(value: nil)
695
+        defer { canEncodeNewValue = false }
696
+
697
+        let context = EncodingError.Context(codingPath: codingPath,
698
+                                            debugDescription: "URLEncodedFormEncoder cannot encode nil values.")
699
+        throw EncodingError.invalidValue("nil", context)
700
+    }
701
+
702
+    func encode(_ value: Bool) throws {
703
+        try encode(value, as: String(boolEncoding.encode(value)))
704
+    }
705
+
706
+    func encode(_ value: String) throws {
707
+        try encode(value, as: value)
708
+    }
709
+
710
+    func encode(_ value: Double) throws {
711
+        try encode(value, as: String(value))
712
+    }
713
+
714
+    func encode(_ value: Float) throws {
715
+        try encode(value, as: String(value))
716
+    }
717
+
718
+    func encode(_ value: Int) throws {
719
+        try encode(value, as: String(value))
720
+    }
721
+
722
+    func encode(_ value: Int8) throws {
723
+        try encode(value, as: String(value))
724
+    }
725
+
726
+    func encode(_ value: Int16) throws {
727
+        try encode(value, as: String(value))
728
+    }
729
+
730
+    func encode(_ value: Int32) throws {
731
+        try encode(value, as: String(value))
732
+    }
733
+
734
+    func encode(_ value: Int64) throws {
735
+        try encode(value, as: String(value))
736
+    }
737
+
738
+    func encode(_ value: UInt) throws {
739
+        try encode(value, as: String(value))
740
+    }
741
+
742
+    func encode(_ value: UInt8) throws {
743
+        try encode(value, as: String(value))
744
+    }
745
+
746
+    func encode(_ value: UInt16) throws {
747
+        try encode(value, as: String(value))
748
+    }
749
+
750
+    func encode(_ value: UInt32) throws {
751
+        try encode(value, as: String(value))
752
+    }
753
+
754
+    func encode(_ value: UInt64) throws {
755
+        try encode(value, as: String(value))
756
+    }
757
+
758
+    private func encode<T>(_ value: T, as string: String) throws where T: Encodable {
759
+        try checkCanEncode(value: value)
760
+        defer { canEncodeNewValue = false }
761
+
762
+        context.component.set(to: .string(string), at: codingPath)
763
+    }
764
+
765
+    func encode<T>(_ value: T) throws where T: Encodable {
766
+        switch value {
767
+        case let date as Date:
768
+            guard let string = try dateEncoding.encode(date) else {
769
+                try attemptToEncode(value)
770
+                return
771
+            }
772
+
773
+            try encode(value, as: string)
774
+        case let data as Data:
775
+            guard let string = try dataEncoding.encode(data) else {
776
+                try attemptToEncode(value)
777
+                return
778
+            }
779
+
780
+            try encode(value, as: string)
781
+        default:
782
+            try attemptToEncode(value)
783
+        }
784
+    }
785
+
786
+    private func attemptToEncode<T>(_ value: T) throws where T: Encodable {
787
+        try checkCanEncode(value: value)
788
+        defer { canEncodeNewValue = false }
789
+
790
+        let encoder = _URLEncodedFormEncoder(context: context,
791
+                                             codingPath: codingPath,
792
+                                             boolEncoding: boolEncoding,
793
+                                             dataEncoding: dataEncoding,
794
+                                             dateEncoding: dateEncoding)
795
+        try value.encode(to: encoder)
796
+    }
797
+}
798
+
799
+extension _URLEncodedFormEncoder {
800
+    final class UnkeyedContainer {
801
+        var codingPath: [CodingKey]
802
+
803
+        var count = 0
804
+        var nestedCodingPath: [CodingKey] {
805
+            return codingPath + [AnyCodingKey(intValue: count)!]
806
+        }
807
+
808
+        private let context: URLEncodedFormContext
809
+        private let boolEncoding: URLEncodedFormEncoder.BoolEncoding
810
+        private let dataEncoding: URLEncodedFormEncoder.DataEncoding
811
+        private let dateEncoding: URLEncodedFormEncoder.DateEncoding
812
+
813
+        init(context: URLEncodedFormContext,
814
+             codingPath: [CodingKey],
815
+             boolEncoding: URLEncodedFormEncoder.BoolEncoding,
816
+             dataEncoding: URLEncodedFormEncoder.DataEncoding,
817
+             dateEncoding: URLEncodedFormEncoder.DateEncoding) {
818
+            self.context = context
819
+            self.codingPath = codingPath
820
+            self.boolEncoding = boolEncoding
821
+            self.dataEncoding = dataEncoding
822
+            self.dateEncoding = dateEncoding
823
+        }
824
+    }
825
+}
826
+
827
+extension _URLEncodedFormEncoder.UnkeyedContainer: UnkeyedEncodingContainer {
828
+    func encodeNil() throws {
829
+        let context = EncodingError.Context(codingPath: codingPath,
830
+                                            debugDescription: "URLEncodedFormEncoder cannot encode nil values.")
831
+        throw EncodingError.invalidValue("nil", context)
832
+    }
833
+
834
+    func encode<T>(_ value: T) throws where T: Encodable {
835
+        var container = nestedSingleValueContainer()
836
+        try container.encode(value)
837
+    }
838
+
839
+    func nestedSingleValueContainer() -> SingleValueEncodingContainer {
840
+        defer { count += 1 }
841
+
842
+        return _URLEncodedFormEncoder.SingleValueContainer(context: context,
843
+                                                           codingPath: nestedCodingPath,
844
+                                                           boolEncoding: boolEncoding,
845
+                                                           dataEncoding: dataEncoding,
846
+                                                           dateEncoding: dateEncoding)
847
+    }
848
+
849
+    func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type) -> KeyedEncodingContainer<NestedKey> where NestedKey: CodingKey {
850
+        defer { count += 1 }
851
+        let container = _URLEncodedFormEncoder.KeyedContainer<NestedKey>(context: context,
852
+                                                                         codingPath: nestedCodingPath,
853
+                                                                         boolEncoding: boolEncoding,
854
+                                                                         dataEncoding: dataEncoding,
855
+                                                                         dateEncoding: dateEncoding)
856
+
857
+        return KeyedEncodingContainer(container)
858
+    }
859
+
860
+    func nestedUnkeyedContainer() -> UnkeyedEncodingContainer {
861
+        defer { count += 1 }
862
+
863
+        return _URLEncodedFormEncoder.UnkeyedContainer(context: context,
864
+                                                       codingPath: nestedCodingPath,
865
+                                                       boolEncoding: boolEncoding,
866
+                                                       dataEncoding: dataEncoding,
867
+                                                       dateEncoding: dateEncoding)
868
+    }
869
+
870
+    func superEncoder() -> Encoder {
871
+        defer { count += 1 }
872
+
873
+        return _URLEncodedFormEncoder(context: context,
874
+                                      codingPath: codingPath,
875
+                                      boolEncoding: boolEncoding,
876
+                                      dataEncoding: dataEncoding,
877
+                                      dateEncoding: dateEncoding)
878
+    }
879
+}
880
+
881
+final class URLEncodedFormSerializer {
882
+    private let alphabetizeKeyValuePairs: Bool
883
+    private let arrayEncoding: URLEncodedFormEncoder.ArrayEncoding
884
+    private let keyEncoding: URLEncodedFormEncoder.KeyEncoding
885
+    private let spaceEncoding: URLEncodedFormEncoder.SpaceEncoding
886
+    private let allowedCharacters: CharacterSet
887
+
888
+    init(alphabetizeKeyValuePairs: Bool,
889
+         arrayEncoding: URLEncodedFormEncoder.ArrayEncoding,
890
+         keyEncoding: URLEncodedFormEncoder.KeyEncoding,
891
+         spaceEncoding: URLEncodedFormEncoder.SpaceEncoding,
892
+         allowedCharacters: CharacterSet) {
893
+        self.alphabetizeKeyValuePairs = alphabetizeKeyValuePairs
894
+        self.arrayEncoding = arrayEncoding
895
+        self.keyEncoding = keyEncoding
896
+        self.spaceEncoding = spaceEncoding
897
+        self.allowedCharacters = allowedCharacters
898
+    }
899
+
900
+    func serialize(_ object: URLEncodedFormComponent.Object) -> String {
901
+        var output: [String] = []
902
+        for (key, component) in object {
903
+            let value = serialize(component, forKey: key)
904
+            output.append(value)
905
+        }
906
+        output = alphabetizeKeyValuePairs ? output.sorted() : output
907
+
908
+        return output.joinedWithAmpersands()
909
+    }
910
+
911
+    func serialize(_ component: URLEncodedFormComponent, forKey key: String) -> String {
912
+        switch component {
913
+        case let .string(string): return "\(escape(keyEncoding.encode(key)))=\(escape(string))"
914
+        case let .array(array): return serialize(array, forKey: key)
915
+        case let .object(object): return serialize(object, forKey: key)
916
+        }
917
+    }
918
+
919
+    func serialize(_ object: URLEncodedFormComponent.Object, forKey key: String) -> String {
920
+        var segments: [String] = object.map { subKey, value in
921
+            let keyPath = "[\(subKey)]"
922
+            return serialize(value, forKey: key + keyPath)
923
+        }
924
+        segments = alphabetizeKeyValuePairs ? segments.sorted() : segments
925
+
926
+        return segments.joinedWithAmpersands()
927
+    }
928
+
929
+    func serialize(_ array: [URLEncodedFormComponent], forKey key: String) -> String {
930
+        var segments: [String] = array.map { component in
931
+            let keyPath = arrayEncoding.encode(key)
932
+            return serialize(component, forKey: keyPath)
933
+        }
934
+        segments = alphabetizeKeyValuePairs ? segments.sorted() : segments
935
+
936
+        return segments.joinedWithAmpersands()
937
+    }
938
+
939
+    func escape(_ query: String) -> String {
940
+        var allowedCharactersWithSpace = allowedCharacters
941
+        allowedCharactersWithSpace.insert(charactersIn: " ")
942
+        let escapedQuery = query.addingPercentEncoding(withAllowedCharacters: allowedCharactersWithSpace) ?? query
943
+        let spaceEncodedQuery = spaceEncoding.encode(escapedQuery)
944
+
945
+        return spaceEncodedQuery
946
+    }
947
+}
948
+
949
+extension Array where Element == String {
950
+    func joinedWithAmpersands() -> String {
951
+        return joined(separator: "&")
952
+    }
953
+}
954
+
955
+public extension CharacterSet {
956
+    /// Creates a CharacterSet from RFC 3986 allowed characters.
957
+    ///
958
+    /// RFC 3986 states that the following characters are "reserved" characters.
959
+    ///
960
+    /// - General Delimiters: ":", "#", "[", "]", "@", "?", "/"
961
+    /// - Sub-Delimiters: "!", "$", "&", "'", "(", ")", "*", "+", ",", ";", "="
962
+    ///
963
+    /// In RFC 3986 - Section 3.4, it states that the "?" and "/" characters should not be escaped to allow
964
+    /// query strings to include a URL. Therefore, all "reserved" characters with the exception of "?" and "/"
965
+    /// should be percent-escaped in the query string.
966
+    static let afURLQueryAllowed: CharacterSet = {
967
+        let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4
968
+        let subDelimitersToEncode = "!$&'()*+,;="
969
+        let encodableDelimiters = CharacterSet(charactersIn: "\(generalDelimitersToEncode)\(subDelimitersToEncode)")
970
+
971
+        return CharacterSet.urlQueryAllowed.subtracting(encodableDelimiters)
972
+    }()
973
+}

+ 39
- 0
trolley/Pods/Alamofire/Source/URLRequest+Alamofire.swift 查看文件

@@ -0,0 +1,39 @@
1
+//
2
+//  URLRequest+Alamofire.swift
3
+//
4
+//  Copyright (c) 2019 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
+public extension URLRequest {
28
+    /// Returns the `httpMethod` as Alamofire's `HTTPMethod` type.
29
+    var method: HTTPMethod? {
30
+        get { return httpMethod.flatMap(HTTPMethod.init) }
31
+        set { httpMethod = newValue?.rawValue }
32
+    }
33
+
34
+    func validate() throws {
35
+        if method == .get, let bodyData = httpBody {
36
+            throw AFError.urlRequestValidationFailed(reason: .bodyDataInGETRequest(bodyData))
37
+        }
38
+    }
39
+}

+ 37
- 0
trolley/Pods/Alamofire/Source/URLSessionConfiguration+Alamofire.swift 查看文件

@@ -0,0 +1,37 @@
1
+//
2
+//  URLSessionConfiguration+Alamofire.swift
3
+//
4
+//  Copyright (c) 2014-2018 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 URLSessionConfiguration: AlamofireExtended {}
28
+extension AlamofireExtension where ExtendedType: URLSessionConfiguration {
29
+    /// Alamofire's default configuration. Same as `URLSessionConfiguration.default` but adds Alamofire default
30
+    /// `Accept-Language`, `Accept-Encoding`, and `User-Agent` headers.
31
+    public static var `default`: URLSessionConfiguration {
32
+        let configuration = URLSessionConfiguration.default
33
+        configuration.headers = .default
34
+
35
+        return configuration
36
+    }
37
+}

+ 247
- 0
trolley/Pods/Alamofire/Source/Validation.swift 查看文件

@@ -0,0 +1,247 @@
1
+//
2
+//  Validation.swift
3
+//
4
+//  Copyright (c) 2014-2018 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
+    // MARK: Helper Types
29
+
30
+    fileprivate typealias ErrorReason = AFError.ResponseValidationFailureReason
31
+
32
+    /// Used to represent whether a validation succeeded or failed.
33
+    public typealias ValidationResult = Result<Void, Error>
34
+
35
+    fileprivate struct MIMEType {
36
+        let type: String
37
+        let subtype: String
38
+
39
+        var isWildcard: Bool { return type == "*" && subtype == "*" }
40
+
41
+        init?(_ string: String) {
42
+            let components: [String] = {
43
+                let stripped = string.trimmingCharacters(in: .whitespacesAndNewlines)
44
+                let split = stripped[..<(stripped.range(of: ";")?.lowerBound ?? stripped.endIndex)]
45
+
46
+                return split.components(separatedBy: "/")
47
+            }()
48
+
49
+            if let type = components.first, let subtype = components.last {
50
+                self.type = type
51
+                self.subtype = subtype
52
+            } else {
53
+                return nil
54
+            }
55
+        }
56
+
57
+        func matches(_ mime: MIMEType) -> Bool {
58
+            switch (type, subtype) {
59
+            case (mime.type, mime.subtype), (mime.type, "*"), ("*", mime.subtype), ("*", "*"):
60
+                return true
61
+            default:
62
+                return false
63
+            }
64
+        }
65
+    }
66
+
67
+    // MARK: Properties
68
+
69
+    fileprivate var acceptableStatusCodes: Range<Int> { return 200..<300 }
70
+
71
+    fileprivate var acceptableContentTypes: [String] {
72
+        if let accept = request?.value(forHTTPHeaderField: "Accept") {
73
+            return accept.components(separatedBy: ",")
74
+        }
75
+
76
+        return ["*/*"]
77
+    }
78
+
79
+    // MARK: Status Code
80
+
81
+    fileprivate func validate<S: Sequence>(statusCode acceptableStatusCodes: S,
82
+                                           response: HTTPURLResponse)
83
+        -> ValidationResult
84
+        where S.Iterator.Element == Int {
85
+        if acceptableStatusCodes.contains(response.statusCode) {
86
+            return .success(Void())
87
+        } else {
88
+            let reason: ErrorReason = .unacceptableStatusCode(code: response.statusCode)
89
+            return .failure(AFError.responseValidationFailed(reason: reason))
90
+        }
91
+    }
92
+
93
+    // MARK: Content Type
94
+
95
+    fileprivate func validate<S: Sequence>(contentType acceptableContentTypes: S,
96
+                                           response: HTTPURLResponse,
97
+                                           data: Data?)
98
+        -> ValidationResult
99
+        where S.Iterator.Element == String {
100
+        guard let data = data, data.count > 0 else { return .success(Void()) }
101
+
102
+        guard
103
+            let responseContentType = response.mimeType,
104
+            let responseMIMEType = MIMEType(responseContentType)
105
+        else {
106
+            for contentType in acceptableContentTypes {
107
+                if let mimeType = MIMEType(contentType), mimeType.isWildcard {
108
+                    return .success(Void())
109
+                }
110
+            }
111
+
112
+            let error: AFError = {
113
+                let reason: ErrorReason = .missingContentType(acceptableContentTypes: Array(acceptableContentTypes))
114
+                return AFError.responseValidationFailed(reason: reason)
115
+            }()
116
+
117
+            return .failure(error)
118
+        }
119
+
120
+        for contentType in acceptableContentTypes {
121
+            if let acceptableMIMEType = MIMEType(contentType), acceptableMIMEType.matches(responseMIMEType) {
122
+                return .success(Void())
123
+            }
124
+        }
125
+
126
+        let error: AFError = {
127
+            let reason: ErrorReason = .unacceptableContentType(acceptableContentTypes: Array(acceptableContentTypes),
128
+                                                               responseContentType: responseContentType)
129
+
130
+            return AFError.responseValidationFailed(reason: reason)
131
+        }()
132
+
133
+        return .failure(error)
134
+    }
135
+}
136
+
137
+// MARK: -
138
+
139
+extension DataRequest {
140
+    /// A closure used to validate a request that takes a URL request, a URL response and data, and returns whether the
141
+    /// request was valid.
142
+    public typealias Validation = (URLRequest?, HTTPURLResponse, Data?) -> ValidationResult
143
+
144
+    /// Validates that the response has a status code in the specified sequence.
145
+    ///
146
+    /// If validation fails, subsequent calls to response handlers will have an associated error.
147
+    ///
148
+    /// - parameter range: The range of acceptable status codes.
149
+    ///
150
+    /// - returns: The request.
151
+    @discardableResult
152
+    public func validate<S: Sequence>(statusCode acceptableStatusCodes: S) -> Self where S.Iterator.Element == Int {
153
+        return validate { [unowned self] _, response, _ in
154
+            self.validate(statusCode: acceptableStatusCodes, response: response)
155
+        }
156
+    }
157
+
158
+    /// Validates that the response has a content type in the specified sequence.
159
+    ///
160
+    /// If validation fails, subsequent calls to response handlers will have an associated error.
161
+    ///
162
+    /// - parameter contentType: The acceptable content types, which may specify wildcard types and/or subtypes.
163
+    ///
164
+    /// - returns: The request.
165
+    @discardableResult
166
+    public func validate<S: Sequence>(contentType acceptableContentTypes: @escaping @autoclosure () -> S) -> Self where S.Iterator.Element == String {
167
+        return validate { [unowned self] _, response, data in
168
+            self.validate(contentType: acceptableContentTypes(), response: response, data: data)
169
+        }
170
+    }
171
+
172
+    /// Validates that the response has a status code in the default acceptable range of 200...299, and that the content
173
+    /// type matches any specified in the Accept HTTP header field.
174
+    ///
175
+    /// If validation fails, subsequent calls to response handlers will have an associated error.
176
+    ///
177
+    /// - returns: The request.
178
+    @discardableResult
179
+    public func validate() -> Self {
180
+        let contentTypes: () -> [String] = { [unowned self] in
181
+            self.acceptableContentTypes
182
+        }
183
+        return validate(statusCode: acceptableStatusCodes).validate(contentType: contentTypes())
184
+    }
185
+}
186
+
187
+// MARK: -
188
+
189
+extension DownloadRequest {
190
+    /// A closure used to validate a request that takes a URL request, a URL response, a temporary URL and a
191
+    /// destination URL, and returns whether the request was valid.
192
+    public typealias Validation = (_ request: URLRequest?,
193
+                                   _ response: HTTPURLResponse,
194
+                                   _ fileURL: URL?)
195
+        -> ValidationResult
196
+
197
+    /// Validates that the response has a status code in the specified sequence.
198
+    ///
199
+    /// If validation fails, subsequent calls to response handlers will have an associated error.
200
+    ///
201
+    /// - parameter range: The range of acceptable status codes.
202
+    ///
203
+    /// - returns: The request.
204
+    @discardableResult
205
+    public func validate<S: Sequence>(statusCode acceptableStatusCodes: S) -> Self where S.Iterator.Element == Int {
206
+        return validate { [unowned self] _, response, _ in
207
+            self.validate(statusCode: acceptableStatusCodes, response: response)
208
+        }
209
+    }
210
+
211
+    /// Validates that the response has a content type in the specified sequence.
212
+    ///
213
+    /// If validation fails, subsequent calls to response handlers will have an associated error.
214
+    ///
215
+    /// - parameter contentType: The acceptable content types, which may specify wildcard types and/or subtypes.
216
+    ///
217
+    /// - returns: The request.
218
+    @discardableResult
219
+    public func validate<S: Sequence>(contentType acceptableContentTypes: @escaping @autoclosure () -> S) -> Self where S.Iterator.Element == String {
220
+        return validate { [unowned self] _, response, fileURL in
221
+            guard let validFileURL = fileURL else {
222
+                return .failure(AFError.responseValidationFailed(reason: .dataFileNil))
223
+            }
224
+
225
+            do {
226
+                let data = try Data(contentsOf: validFileURL)
227
+                return self.validate(contentType: acceptableContentTypes(), response: response, data: data)
228
+            } catch {
229
+                return .failure(AFError.responseValidationFailed(reason: .dataFileReadFailed(at: validFileURL)))
230
+            }
231
+        }
232
+    }
233
+
234
+    /// Validates that the response has a status code in the default acceptable range of 200...299, and that the content
235
+    /// type matches any specified in the Accept HTTP header field.
236
+    ///
237
+    /// If validation fails, subsequent calls to response handlers will have an associated error.
238
+    ///
239
+    /// - returns: The request.
240
+    @discardableResult
241
+    public func validate() -> Self {
242
+        let contentTypes = { [unowned self] in
243
+            self.acceptableContentTypes
244
+        }
245
+        return validate(statusCode: acceptableStatusCodes).validate(contentType: contentTypes())
246
+    }
247
+}

+ 20
- 0
trolley/Pods/Manifest.lock 查看文件

@@ -0,0 +1,20 @@
1
+PODS:
2
+  - Alamofire (5.0.0-rc.3)
3
+  - SwiftyJSON (4.3.0)
4
+
5
+DEPENDENCIES:
6
+  - Alamofire (~> 5.0.0-rc.3)
7
+  - SwiftyJSON (~> 4.0)
8
+
9
+SPEC REPOS:
10
+  trunk:
11
+    - Alamofire
12
+    - SwiftyJSON
13
+
14
+SPEC CHECKSUMS:
15
+  Alamofire: ca8c0de6906873be89d6deec5c8de279e00bf872
16
+  SwiftyJSON: 6faa0040f8b59dead0ee07436cbf76b73c08fd08
17
+
18
+PODFILE CHECKSUM: bbeb87e6f37761e96d8e2b35e3bf81e6aa0f8a7f
19
+
20
+COCOAPODS: 1.8.4

+ 917
- 0
trolley/Pods/Pods.xcodeproj/project.pbxproj 查看文件

@@ -0,0 +1,917 @@
1
+// !$*UTF8*$!
2
+{
3
+	archiveVersion = 1;
4
+	classes = {
5
+	};
6
+	objectVersion = 50;
7
+	objects = {
8
+
9
+/* Begin PBXBuildFile section */
10
+		00FA97D56201027AEB1C7692A2C3CF8B /* Alamofire-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = D476090870A4C1F270AF191144821EE0 /* Alamofire-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; };
11
+		0419772A87B16DB7DCF405A9E77D671F /* Protector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B7761460A78F6B568B3C9004F30AABD /* Protector.swift */; };
12
+		06507A26118BA5ACFBBC8C225776920E /* Validation.swift in Sources */ = {isa = PBXBuildFile; fileRef = C31254BAA3FFD33BA38224DA869BEB40 /* Validation.swift */; };
13
+		0A33AA753FE836DA0C9F480BF9B8EEBD /* Pods-Trolley App-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = C8DAE32FAF9DFD3DE02E5B036BAB4339 /* Pods-Trolley App-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; };
14
+		0AE06C3AEA6CA45342BA703230ABD2CB /* CachedResponseHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A5A040CBB1EA3620D59D4091F5C5482 /* CachedResponseHandler.swift */; };
15
+		0CC43FF0E31AA320ACFEB0FE6239DF34 /* ServerTrustEvaluation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71317563ECAB83A32994A1916063E464 /* ServerTrustEvaluation.swift */; };
16
+		13457FE4E607509A3B9527B0711033D5 /* ResponseSerialization.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61672F694C039966112741F5B337B03C /* ResponseSerialization.swift */; };
17
+		14AB7976E100075ADEA0AB1DB833E72D /* ParameterEncoding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35C1FDE797E96D791DBA888D7BB4A421 /* ParameterEncoding.swift */; };
18
+		17953A9CF2E354B3E69B9ABC2F367AD9 /* AFError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 699150D1DB93B31F739A86936B8E383A /* AFError.swift */; };
19
+		1942F7D3B7722A5637C3FC0BE44B1E6C /* SwiftyJSON-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 6D3D1A2B5FEAF863B6C8AB55F1F1B7F8 /* SwiftyJSON-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; };
20
+		2BF6FBC0A64BF107C5D64C61F1397770 /* SwiftyJSON-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = F5FFA3C231B6E838CFF29FB82CCF3062 /* SwiftyJSON-dummy.m */; };
21
+		4082513A35C682F2193D002C80F72B79 /* Result+Alamofire.swift in Sources */ = {isa = PBXBuildFile; fileRef = 736D46C38CD672081C214C316E6B174C /* Result+Alamofire.swift */; };
22
+		42CDB5C986C78BBC8E5C0185F746CABF /* SessionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B819B1F3D86B49E0C3D0121454EEBD5A /* SessionDelegate.swift */; };
23
+		44127C4B989C9CC6A90D78B66A929A5E /* AlamofireExtended.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03197070251E124BBEFE81BEDACED86 /* AlamofireExtended.swift */; };
24
+		464450D037D17ED5EE2322E180A6A9F5 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 222DAEF0D819F359AFCFF3D4F927E8A7 /* Foundation.framework */; };
25
+		48D97BE7D5CAED273BD2341C239CC934 /* RequestTaskMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D9B0C4A96EAF7FF69B4D3F492C21C3C /* RequestTaskMap.swift */; };
26
+		56EC8ED1535DAB987F3D2B71D4C05773 /* HTTPHeaders.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22572800EECDE9BE54B3114E111E783A /* HTTPHeaders.swift */; };
27
+		5C4A0685B5A201436AB52EF25829B333 /* MultipartFormData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 952EEAEDD1F3338F11AA71CA45536129 /* MultipartFormData.swift */; };
28
+		5D12235D061AEE7459279AAF8C348DFE /* URLEncodedFormEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49E7355310ABA0D6E01776B14529B5FB /* URLEncodedFormEncoder.swift */; };
29
+		5D61C8ED0DDCC9F8B576B6514B19EE50 /* ParameterEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD232CDF3E701759F5766978763D7A7D /* ParameterEncoder.swift */; };
30
+		68C881E948E0B324AD5C087A6824B2AA /* Pods-Trolley App-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = B20936CE73A899AFC85238AF25EADD92 /* Pods-Trolley App-dummy.m */; };
31
+		69ACE4EEE5A8C1C618B22CC1F7B8EF01 /* Session.swift in Sources */ = {isa = PBXBuildFile; fileRef = A417CC269792F28210F4137FE29C8D24 /* Session.swift */; };
32
+		6A22C46CB1EDE471794D9AB2AC10327F /* Request.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8765C17A537B69BF9983892D422235AF /* Request.swift */; };
33
+		70517C3BAC2D6614347DEAC15299EB84 /* URLConvertible+URLRequestConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 656640CD84846289906E483AB4EB1946 /* URLConvertible+URLRequestConvertible.swift */; };
34
+		7B4CE5C84161E2BFE477F42DFD634382 /* SwiftyJSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15274DB1E8A5D70031D5A91049B8985E /* SwiftyJSON.swift */; };
35
+		7CF8362BA31492053F5CB165637AE117 /* NetworkReachabilityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4D168E821AE5843A32F41BCFB1BA57A /* NetworkReachabilityManager.swift */; };
36
+		8E5CC56869172C38BEAD04CFCE5FA129 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 222DAEF0D819F359AFCFF3D4F927E8A7 /* Foundation.framework */; };
37
+		92811AC5CD9A5004116AE43C4E8FD955 /* OperationQueue+Alamofire.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08471AEB5D3ED0B8A0CEEE2B92B9A821 /* OperationQueue+Alamofire.swift */; };
38
+		97A168DFB6DB61770CE2DBF4FD39AA8D /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B079F294DA5D9A879E6D53A91F51A1E /* CFNetwork.framework */; };
39
+		AD9899986955B2EC1EC20818C860C971 /* RequestInterceptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EDA410CDB58171C455D6E3BC7B2467F /* RequestInterceptor.swift */; };
40
+		AF92602937CA016548022C600B8CDC16 /* URLSessionConfiguration+Alamofire.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DEB0436C28D555D73861B8E078AF506 /* URLSessionConfiguration+Alamofire.swift */; };
41
+		B1C58F6CED7B3E45170711D9ADF878AF /* Alamofire-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = A05320B6EA712CC4F247C1889D37099F /* Alamofire-dummy.m */; };
42
+		B23E9A5CDA31534491226F4C2EE8F8E6 /* HTTPMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D43FC460F9F0F23DF65AD795A8A5218 /* HTTPMethod.swift */; };
43
+		B788B3354CCEBE56DFDB963CAFD7F6C2 /* Alamofire.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63BE47921896DF3F95A49544FB23EB5C /* Alamofire.swift */; };
44
+		BE82AE980F8C7EE28A6448959194F93A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 222DAEF0D819F359AFCFF3D4F927E8A7 /* Foundation.framework */; };
45
+		C64AF152F7928CDB59385528DB65FE19 /* RedirectHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A39FC2200A0A670CB446B725FDFB90D /* RedirectHandler.swift */; };
46
+		C7369563F6946D8984124E1A546B6425 /* Notifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92682BBB26B0D3321F2531618197A1B0 /* Notifications.swift */; };
47
+		CACBD166E573774FB5613C34AA6DA7A7 /* EventMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E39775963B99EAB8EC5F206ABE847741 /* EventMonitor.swift */; };
48
+		D6B2983389480F48F27A0704EEB5DC81 /* RetryPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9316125B5AB01426BC779E90B017C763 /* RetryPolicy.swift */; };
49
+		E07BD425C4EA9ADF15DDFCDB10D0B2FB /* MultipartUpload.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55ABC4A2F46D9406DC7056485011FD99 /* MultipartUpload.swift */; };
50
+		E4E12208D5246E64B7E6CCAE987ADB03 /* URLRequest+Alamofire.swift in Sources */ = {isa = PBXBuildFile; fileRef = D052E9F52FDE47ABAD398907DBCFF724 /* URLRequest+Alamofire.swift */; };
51
+		E9A5AC2F471699CCA516952A5FEB990B /* DispatchQueue+Alamofire.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BBA3825D95DF8E6E25A408274CF00A /* DispatchQueue+Alamofire.swift */; };
52
+		F71789DC91A75033EFB79DB828676451 /* Response.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54E9EC8B935FF3CFDF353D79C45EADAA /* Response.swift */; };
53
+/* End PBXBuildFile section */
54
+
55
+/* Begin PBXContainerItemProxy section */
56
+		1DB6BD47CAF1ECF6E02B36A1EEAD3587 /* PBXContainerItemProxy */ = {
57
+			isa = PBXContainerItemProxy;
58
+			containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */;
59
+			proxyType = 1;
60
+			remoteGlobalIDString = D118A6A04828FD3CDA8640CD2B6796D2;
61
+			remoteInfo = SwiftyJSON;
62
+		};
63
+		36A01FA1C62B729E3DA5A9638A3FC288 /* PBXContainerItemProxy */ = {
64
+			isa = PBXContainerItemProxy;
65
+			containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */;
66
+			proxyType = 1;
67
+			remoteGlobalIDString = EAAA1AD3A8A1B59AB91319EE40752C6D;
68
+			remoteInfo = Alamofire;
69
+		};
70
+/* End PBXContainerItemProxy section */
71
+
72
+/* Begin PBXFileReference section */
73
+		08471AEB5D3ED0B8A0CEEE2B92B9A821 /* OperationQueue+Alamofire.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "OperationQueue+Alamofire.swift"; path = "Source/OperationQueue+Alamofire.swift"; sourceTree = "<group>"; };
74
+		0D9B0C4A96EAF7FF69B4D3F492C21C3C /* RequestTaskMap.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = RequestTaskMap.swift; path = Source/RequestTaskMap.swift; sourceTree = "<group>"; };
75
+		0F04AFD3B2F75EC4D94DCAAAE6F65E3E /* Pods-Trolley App.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Trolley App.debug.xcconfig"; sourceTree = "<group>"; };
76
+		15274DB1E8A5D70031D5A91049B8985E /* SwiftyJSON.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SwiftyJSON.swift; path = Source/SwiftyJSON/SwiftyJSON.swift; sourceTree = "<group>"; };
77
+		1B1D8193211F4CF8190DD98D24AA5A3C /* Pods-Trolley App-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-Trolley App-acknowledgements.markdown"; sourceTree = "<group>"; };
78
+		1DEB0436C28D555D73861B8E078AF506 /* URLSessionConfiguration+Alamofire.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "URLSessionConfiguration+Alamofire.swift"; path = "Source/URLSessionConfiguration+Alamofire.swift"; sourceTree = "<group>"; };
79
+		222DAEF0D819F359AFCFF3D4F927E8A7 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; };
80
+		22572800EECDE9BE54B3114E111E783A /* HTTPHeaders.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = HTTPHeaders.swift; path = Source/HTTPHeaders.swift; sourceTree = "<group>"; };
81
+		2A5A040CBB1EA3620D59D4091F5C5482 /* CachedResponseHandler.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CachedResponseHandler.swift; path = Source/CachedResponseHandler.swift; sourceTree = "<group>"; };
82
+		2F8C726BF7AEBB3DF201B63EE8AC4EDC /* SwiftyJSON.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SwiftyJSON.xcconfig; sourceTree = "<group>"; };
83
+		35C1FDE797E96D791DBA888D7BB4A421 /* ParameterEncoding.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ParameterEncoding.swift; path = Source/ParameterEncoding.swift; sourceTree = "<group>"; };
84
+		393516C6BFFFAB6FC49599474E05B17B /* Pods-Trolley App-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-Trolley App-Info.plist"; sourceTree = "<group>"; };
85
+		3A01C48AC23CA9AAC7E0EEF917F07DA5 /* Pods-Trolley App-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-Trolley App-acknowledgements.plist"; sourceTree = "<group>"; };
86
+		3A39FC2200A0A670CB446B725FDFB90D /* RedirectHandler.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = RedirectHandler.swift; path = Source/RedirectHandler.swift; sourceTree = "<group>"; };
87
+		3CAA211143B95E27EBC3BCF6C0981653 /* Pods-Trolley App.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-Trolley App.modulemap"; sourceTree = "<group>"; };
88
+		3F88FEA61E1ABE7D1BDC7BB673C3CD2C /* Alamofire.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = Alamofire.modulemap; sourceTree = "<group>"; };
89
+		44309CF1369CA316F5571975E49CC682 /* Pods_Trolley_App.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_Trolley_App.framework; path = "Pods-Trolley App.framework"; sourceTree = BUILT_PRODUCTS_DIR; };
90
+		49E7355310ABA0D6E01776B14529B5FB /* URLEncodedFormEncoder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = URLEncodedFormEncoder.swift; path = Source/URLEncodedFormEncoder.swift; sourceTree = "<group>"; };
91
+		51475D6BC60AF470F09828783BFB7D09 /* Alamofire-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Alamofire-prefix.pch"; sourceTree = "<group>"; };
92
+		54E9EC8B935FF3CFDF353D79C45EADAA /* Response.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Response.swift; path = Source/Response.swift; sourceTree = "<group>"; };
93
+		55ABC4A2F46D9406DC7056485011FD99 /* MultipartUpload.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MultipartUpload.swift; path = Source/MultipartUpload.swift; sourceTree = "<group>"; };
94
+		5D797E9A5C5782CE845840781FA1CC81 /* Alamofire.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Alamofire.framework; path = Alamofire.framework; sourceTree = BUILT_PRODUCTS_DIR; };
95
+		61672F694C039966112741F5B337B03C /* ResponseSerialization.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ResponseSerialization.swift; path = Source/ResponseSerialization.swift; sourceTree = "<group>"; };
96
+		63BE47921896DF3F95A49544FB23EB5C /* Alamofire.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Alamofire.swift; path = Source/Alamofire.swift; sourceTree = "<group>"; };
97
+		652DC10C3B779819FFADFE0B8DF9BFDB /* SwiftyJSON-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "SwiftyJSON-Info.plist"; sourceTree = "<group>"; };
98
+		656640CD84846289906E483AB4EB1946 /* URLConvertible+URLRequestConvertible.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "URLConvertible+URLRequestConvertible.swift"; path = "Source/URLConvertible+URLRequestConvertible.swift"; sourceTree = "<group>"; };
99
+		65D7566B596BE9048CE78915E9003BBD /* SwiftyJSON.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = SwiftyJSON.modulemap; sourceTree = "<group>"; };
100
+		699150D1DB93B31F739A86936B8E383A /* AFError.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AFError.swift; path = Source/AFError.swift; sourceTree = "<group>"; };
101
+		6AE015C857E33610B42A675FA9476516 /* Alamofire-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Alamofire-Info.plist"; sourceTree = "<group>"; };
102
+		6BFF6AB28CCA0394147F7105063B2C86 /* Alamofire.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Alamofire.xcconfig; sourceTree = "<group>"; };
103
+		6D3D1A2B5FEAF863B6C8AB55F1F1B7F8 /* SwiftyJSON-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SwiftyJSON-umbrella.h"; sourceTree = "<group>"; };
104
+		6EDA410CDB58171C455D6E3BC7B2467F /* RequestInterceptor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = RequestInterceptor.swift; path = Source/RequestInterceptor.swift; sourceTree = "<group>"; };
105
+		71317563ECAB83A32994A1916063E464 /* ServerTrustEvaluation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ServerTrustEvaluation.swift; path = Source/ServerTrustEvaluation.swift; sourceTree = "<group>"; };
106
+		736D46C38CD672081C214C316E6B174C /* Result+Alamofire.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Result+Alamofire.swift"; path = "Source/Result+Alamofire.swift"; sourceTree = "<group>"; };
107
+		7A9E60B1A018CCFB58106BB429914737 /* Pods-Trolley App.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Trolley App.release.xcconfig"; sourceTree = "<group>"; };
108
+		7B7761460A78F6B568B3C9004F30AABD /* Protector.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Protector.swift; path = Source/Protector.swift; sourceTree = "<group>"; };
109
+		7C72DCE12ABEC9F1617F8CDB4661EE72 /* SwiftyJSON-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SwiftyJSON-prefix.pch"; sourceTree = "<group>"; };
110
+		865132122B5496B9D5D345110ECA8088 /* Pods-Trolley App-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-Trolley App-frameworks.sh"; sourceTree = "<group>"; };
111
+		8765C17A537B69BF9983892D422235AF /* Request.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Request.swift; path = Source/Request.swift; sourceTree = "<group>"; };
112
+		8B079F294DA5D9A879E6D53A91F51A1E /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/CFNetwork.framework; sourceTree = DEVELOPER_DIR; };
113
+		8D43FC460F9F0F23DF65AD795A8A5218 /* HTTPMethod.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = HTTPMethod.swift; path = Source/HTTPMethod.swift; sourceTree = "<group>"; };
114
+		92682BBB26B0D3321F2531618197A1B0 /* Notifications.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Notifications.swift; path = Source/Notifications.swift; sourceTree = "<group>"; };
115
+		9316125B5AB01426BC779E90B017C763 /* RetryPolicy.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = RetryPolicy.swift; path = Source/RetryPolicy.swift; sourceTree = "<group>"; };
116
+		952EEAEDD1F3338F11AA71CA45536129 /* MultipartFormData.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MultipartFormData.swift; path = Source/MultipartFormData.swift; sourceTree = "<group>"; };
117
+		9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; };
118
+		A05320B6EA712CC4F247C1889D37099F /* Alamofire-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Alamofire-dummy.m"; sourceTree = "<group>"; };
119
+		A417CC269792F28210F4137FE29C8D24 /* Session.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Session.swift; path = Source/Session.swift; sourceTree = "<group>"; };
120
+		AD232CDF3E701759F5766978763D7A7D /* ParameterEncoder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ParameterEncoder.swift; path = Source/ParameterEncoder.swift; sourceTree = "<group>"; };
121
+		B20936CE73A899AFC85238AF25EADD92 /* Pods-Trolley App-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-Trolley App-dummy.m"; sourceTree = "<group>"; };
122
+		B5BBA3825D95DF8E6E25A408274CF00A /* DispatchQueue+Alamofire.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "DispatchQueue+Alamofire.swift"; path = "Source/DispatchQueue+Alamofire.swift"; sourceTree = "<group>"; };
123
+		B819B1F3D86B49E0C3D0121454EEBD5A /* SessionDelegate.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SessionDelegate.swift; path = Source/SessionDelegate.swift; sourceTree = "<group>"; };
124
+		C31254BAA3FFD33BA38224DA869BEB40 /* Validation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Validation.swift; path = Source/Validation.swift; sourceTree = "<group>"; };
125
+		C8DAE32FAF9DFD3DE02E5B036BAB4339 /* Pods-Trolley App-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-Trolley App-umbrella.h"; sourceTree = "<group>"; };
126
+		D03197070251E124BBEFE81BEDACED86 /* AlamofireExtended.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AlamofireExtended.swift; path = Source/AlamofireExtended.swift; sourceTree = "<group>"; };
127
+		D052E9F52FDE47ABAD398907DBCFF724 /* URLRequest+Alamofire.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "URLRequest+Alamofire.swift"; path = "Source/URLRequest+Alamofire.swift"; sourceTree = "<group>"; };
128
+		D476090870A4C1F270AF191144821EE0 /* Alamofire-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Alamofire-umbrella.h"; sourceTree = "<group>"; };
129
+		E23C076BA70925415F490FEDB215DA92 /* SwiftyJSON.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = SwiftyJSON.framework; path = SwiftyJSON.framework; sourceTree = BUILT_PRODUCTS_DIR; };
130
+		E39775963B99EAB8EC5F206ABE847741 /* EventMonitor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EventMonitor.swift; path = Source/EventMonitor.swift; sourceTree = "<group>"; };
131
+		F4D168E821AE5843A32F41BCFB1BA57A /* NetworkReachabilityManager.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = NetworkReachabilityManager.swift; path = Source/NetworkReachabilityManager.swift; sourceTree = "<group>"; };
132
+		F5FFA3C231B6E838CFF29FB82CCF3062 /* SwiftyJSON-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "SwiftyJSON-dummy.m"; sourceTree = "<group>"; };
133
+/* End PBXFileReference section */
134
+
135
+/* Begin PBXFrameworksBuildPhase section */
136
+		22DB9C644F770B18D936E2B304CFF534 /* Frameworks */ = {
137
+			isa = PBXFrameworksBuildPhase;
138
+			buildActionMask = 2147483647;
139
+			files = (
140
+				8E5CC56869172C38BEAD04CFCE5FA129 /* Foundation.framework in Frameworks */,
141
+			);
142
+			runOnlyForDeploymentPostprocessing = 0;
143
+		};
144
+		8B0D8633F410345F93419B8C3D7B6916 /* Frameworks */ = {
145
+			isa = PBXFrameworksBuildPhase;
146
+			buildActionMask = 2147483647;
147
+			files = (
148
+				97A168DFB6DB61770CE2DBF4FD39AA8D /* CFNetwork.framework in Frameworks */,
149
+				BE82AE980F8C7EE28A6448959194F93A /* Foundation.framework in Frameworks */,
150
+			);
151
+			runOnlyForDeploymentPostprocessing = 0;
152
+		};
153
+		AD9C5A8DAF4334B670E91B2EC08DBE2C /* Frameworks */ = {
154
+			isa = PBXFrameworksBuildPhase;
155
+			buildActionMask = 2147483647;
156
+			files = (
157
+				464450D037D17ED5EE2322E180A6A9F5 /* Foundation.framework in Frameworks */,
158
+			);
159
+			runOnlyForDeploymentPostprocessing = 0;
160
+		};
161
+/* End PBXFrameworksBuildPhase section */
162
+
163
+/* Begin PBXGroup section */
164
+		1628BF05B4CAFDCC3549A101F5A10A17 /* Frameworks */ = {
165
+			isa = PBXGroup;
166
+			children = (
167
+				E34DCC8E2CF86B8D72232914781A840D /* iOS */,
168
+			);
169
+			name = Frameworks;
170
+			sourceTree = "<group>";
171
+		};
172
+		1713D5D26513A71876A7F5676C179011 /* Targets Support Files */ = {
173
+			isa = PBXGroup;
174
+			children = (
175
+				652971AEECA6C4C8D08F6C665FA2E63F /* Pods-Trolley App */,
176
+			);
177
+			name = "Targets Support Files";
178
+			sourceTree = "<group>";
179
+		};
180
+		652971AEECA6C4C8D08F6C665FA2E63F /* Pods-Trolley App */ = {
181
+			isa = PBXGroup;
182
+			children = (
183
+				3CAA211143B95E27EBC3BCF6C0981653 /* Pods-Trolley App.modulemap */,
184
+				1B1D8193211F4CF8190DD98D24AA5A3C /* Pods-Trolley App-acknowledgements.markdown */,
185
+				3A01C48AC23CA9AAC7E0EEF917F07DA5 /* Pods-Trolley App-acknowledgements.plist */,
186
+				B20936CE73A899AFC85238AF25EADD92 /* Pods-Trolley App-dummy.m */,
187
+				865132122B5496B9D5D345110ECA8088 /* Pods-Trolley App-frameworks.sh */,
188
+				393516C6BFFFAB6FC49599474E05B17B /* Pods-Trolley App-Info.plist */,
189
+				C8DAE32FAF9DFD3DE02E5B036BAB4339 /* Pods-Trolley App-umbrella.h */,
190
+				0F04AFD3B2F75EC4D94DCAAAE6F65E3E /* Pods-Trolley App.debug.xcconfig */,
191
+				7A9E60B1A018CCFB58106BB429914737 /* Pods-Trolley App.release.xcconfig */,
192
+			);
193
+			name = "Pods-Trolley App";
194
+			path = "Target Support Files/Pods-Trolley App";
195
+			sourceTree = "<group>";
196
+		};
197
+		69453FA0DBCD35291F69BE8D6C0BB0EE /* Support Files */ = {
198
+			isa = PBXGroup;
199
+			children = (
200
+				3F88FEA61E1ABE7D1BDC7BB673C3CD2C /* Alamofire.modulemap */,
201
+				6BFF6AB28CCA0394147F7105063B2C86 /* Alamofire.xcconfig */,
202
+				A05320B6EA712CC4F247C1889D37099F /* Alamofire-dummy.m */,
203
+				6AE015C857E33610B42A675FA9476516 /* Alamofire-Info.plist */,
204
+				51475D6BC60AF470F09828783BFB7D09 /* Alamofire-prefix.pch */,
205
+				D476090870A4C1F270AF191144821EE0 /* Alamofire-umbrella.h */,
206
+			);
207
+			name = "Support Files";
208
+			path = "../Target Support Files/Alamofire";
209
+			sourceTree = "<group>";
210
+		};
211
+		71C529FB98A95FF2E1EAA264DBC1CA99 /* Pods */ = {
212
+			isa = PBXGroup;
213
+			children = (
214
+				C17F53E6334F882F25262B133407C66C /* Alamofire */,
215
+				CEA89809072D23C31E6348C93E430AB9 /* SwiftyJSON */,
216
+			);
217
+			name = Pods;
218
+			sourceTree = "<group>";
219
+		};
220
+		A590EE22770CB3ACFFCF44B1B8CFBBD9 /* Support Files */ = {
221
+			isa = PBXGroup;
222
+			children = (
223
+				65D7566B596BE9048CE78915E9003BBD /* SwiftyJSON.modulemap */,
224
+				2F8C726BF7AEBB3DF201B63EE8AC4EDC /* SwiftyJSON.xcconfig */,
225
+				F5FFA3C231B6E838CFF29FB82CCF3062 /* SwiftyJSON-dummy.m */,
226
+				652DC10C3B779819FFADFE0B8DF9BFDB /* SwiftyJSON-Info.plist */,
227
+				7C72DCE12ABEC9F1617F8CDB4661EE72 /* SwiftyJSON-prefix.pch */,
228
+				6D3D1A2B5FEAF863B6C8AB55F1F1B7F8 /* SwiftyJSON-umbrella.h */,
229
+			);
230
+			name = "Support Files";
231
+			path = "../Target Support Files/SwiftyJSON";
232
+			sourceTree = "<group>";
233
+		};
234
+		AA892F70254758B4E668FF3B0A8FC86F /* Products */ = {
235
+			isa = PBXGroup;
236
+			children = (
237
+				5D797E9A5C5782CE845840781FA1CC81 /* Alamofire.framework */,
238
+				44309CF1369CA316F5571975E49CC682 /* Pods_Trolley_App.framework */,
239
+				E23C076BA70925415F490FEDB215DA92 /* SwiftyJSON.framework */,
240
+			);
241
+			name = Products;
242
+			sourceTree = "<group>";
243
+		};
244
+		C17F53E6334F882F25262B133407C66C /* Alamofire */ = {
245
+			isa = PBXGroup;
246
+			children = (
247
+				699150D1DB93B31F739A86936B8E383A /* AFError.swift */,
248
+				63BE47921896DF3F95A49544FB23EB5C /* Alamofire.swift */,
249
+				D03197070251E124BBEFE81BEDACED86 /* AlamofireExtended.swift */,
250
+				2A5A040CBB1EA3620D59D4091F5C5482 /* CachedResponseHandler.swift */,
251
+				B5BBA3825D95DF8E6E25A408274CF00A /* DispatchQueue+Alamofire.swift */,
252
+				E39775963B99EAB8EC5F206ABE847741 /* EventMonitor.swift */,
253
+				22572800EECDE9BE54B3114E111E783A /* HTTPHeaders.swift */,
254
+				8D43FC460F9F0F23DF65AD795A8A5218 /* HTTPMethod.swift */,
255
+				952EEAEDD1F3338F11AA71CA45536129 /* MultipartFormData.swift */,
256
+				55ABC4A2F46D9406DC7056485011FD99 /* MultipartUpload.swift */,
257
+				F4D168E821AE5843A32F41BCFB1BA57A /* NetworkReachabilityManager.swift */,
258
+				92682BBB26B0D3321F2531618197A1B0 /* Notifications.swift */,
259
+				08471AEB5D3ED0B8A0CEEE2B92B9A821 /* OperationQueue+Alamofire.swift */,
260
+				AD232CDF3E701759F5766978763D7A7D /* ParameterEncoder.swift */,
261
+				35C1FDE797E96D791DBA888D7BB4A421 /* ParameterEncoding.swift */,
262
+				7B7761460A78F6B568B3C9004F30AABD /* Protector.swift */,
263
+				3A39FC2200A0A670CB446B725FDFB90D /* RedirectHandler.swift */,
264
+				8765C17A537B69BF9983892D422235AF /* Request.swift */,
265
+				6EDA410CDB58171C455D6E3BC7B2467F /* RequestInterceptor.swift */,
266
+				0D9B0C4A96EAF7FF69B4D3F492C21C3C /* RequestTaskMap.swift */,
267
+				54E9EC8B935FF3CFDF353D79C45EADAA /* Response.swift */,
268
+				61672F694C039966112741F5B337B03C /* ResponseSerialization.swift */,
269
+				736D46C38CD672081C214C316E6B174C /* Result+Alamofire.swift */,
270
+				9316125B5AB01426BC779E90B017C763 /* RetryPolicy.swift */,
271
+				71317563ECAB83A32994A1916063E464 /* ServerTrustEvaluation.swift */,
272
+				A417CC269792F28210F4137FE29C8D24 /* Session.swift */,
273
+				B819B1F3D86B49E0C3D0121454EEBD5A /* SessionDelegate.swift */,
274
+				656640CD84846289906E483AB4EB1946 /* URLConvertible+URLRequestConvertible.swift */,
275
+				49E7355310ABA0D6E01776B14529B5FB /* URLEncodedFormEncoder.swift */,
276
+				D052E9F52FDE47ABAD398907DBCFF724 /* URLRequest+Alamofire.swift */,
277
+				1DEB0436C28D555D73861B8E078AF506 /* URLSessionConfiguration+Alamofire.swift */,
278
+				C31254BAA3FFD33BA38224DA869BEB40 /* Validation.swift */,
279
+				69453FA0DBCD35291F69BE8D6C0BB0EE /* Support Files */,
280
+			);
281
+			name = Alamofire;
282
+			path = Alamofire;
283
+			sourceTree = "<group>";
284
+		};
285
+		CEA89809072D23C31E6348C93E430AB9 /* SwiftyJSON */ = {
286
+			isa = PBXGroup;
287
+			children = (
288
+				15274DB1E8A5D70031D5A91049B8985E /* SwiftyJSON.swift */,
289
+				A590EE22770CB3ACFFCF44B1B8CFBBD9 /* Support Files */,
290
+			);
291
+			name = SwiftyJSON;
292
+			path = SwiftyJSON;
293
+			sourceTree = "<group>";
294
+		};
295
+		CF1408CF629C7361332E53B88F7BD30C = {
296
+			isa = PBXGroup;
297
+			children = (
298
+				9D940727FF8FB9C785EB98E56350EF41 /* Podfile */,
299
+				1628BF05B4CAFDCC3549A101F5A10A17 /* Frameworks */,
300
+				71C529FB98A95FF2E1EAA264DBC1CA99 /* Pods */,
301
+				AA892F70254758B4E668FF3B0A8FC86F /* Products */,
302
+				1713D5D26513A71876A7F5676C179011 /* Targets Support Files */,
303
+			);
304
+			sourceTree = "<group>";
305
+		};
306
+		E34DCC8E2CF86B8D72232914781A840D /* iOS */ = {
307
+			isa = PBXGroup;
308
+			children = (
309
+				8B079F294DA5D9A879E6D53A91F51A1E /* CFNetwork.framework */,
310
+				222DAEF0D819F359AFCFF3D4F927E8A7 /* Foundation.framework */,
311
+			);
312
+			name = iOS;
313
+			sourceTree = "<group>";
314
+		};
315
+/* End PBXGroup section */
316
+
317
+/* Begin PBXHeadersBuildPhase section */
318
+		3D7DD627DB5C5AD636646E57B685AFB2 /* Headers */ = {
319
+			isa = PBXHeadersBuildPhase;
320
+			buildActionMask = 2147483647;
321
+			files = (
322
+				1942F7D3B7722A5637C3FC0BE44B1E6C /* SwiftyJSON-umbrella.h in Headers */,
323
+			);
324
+			runOnlyForDeploymentPostprocessing = 0;
325
+		};
326
+		A2DFC093A47C742BC695AB0F27228B71 /* Headers */ = {
327
+			isa = PBXHeadersBuildPhase;
328
+			buildActionMask = 2147483647;
329
+			files = (
330
+				0A33AA753FE836DA0C9F480BF9B8EEBD /* Pods-Trolley App-umbrella.h in Headers */,
331
+			);
332
+			runOnlyForDeploymentPostprocessing = 0;
333
+		};
334
+		ADDF288DD930A46B5F0F198C225895C9 /* Headers */ = {
335
+			isa = PBXHeadersBuildPhase;
336
+			buildActionMask = 2147483647;
337
+			files = (
338
+				00FA97D56201027AEB1C7692A2C3CF8B /* Alamofire-umbrella.h in Headers */,
339
+			);
340
+			runOnlyForDeploymentPostprocessing = 0;
341
+		};
342
+/* End PBXHeadersBuildPhase section */
343
+
344
+/* Begin PBXNativeTarget section */
345
+		171A0B9EEB8AE346EB29A7957BE4577E /* Pods-Trolley App */ = {
346
+			isa = PBXNativeTarget;
347
+			buildConfigurationList = 510CECFBE569732973A1CF992AB0AC87 /* Build configuration list for PBXNativeTarget "Pods-Trolley App" */;
348
+			buildPhases = (
349
+				A2DFC093A47C742BC695AB0F27228B71 /* Headers */,
350
+				97E712F54AECB1BF4A10C9AF1F9601EC /* Sources */,
351
+				22DB9C644F770B18D936E2B304CFF534 /* Frameworks */,
352
+				8143C3A9828098CC7CE000480F9730F0 /* Resources */,
353
+			);
354
+			buildRules = (
355
+			);
356
+			dependencies = (
357
+				3319C124D3EBBD92EDEC76A250B2AADA /* PBXTargetDependency */,
358
+				DB3FBC6E48CA4511B2E99FCB86948EAA /* PBXTargetDependency */,
359
+			);
360
+			name = "Pods-Trolley App";
361
+			productName = "Pods-Trolley App";
362
+			productReference = 44309CF1369CA316F5571975E49CC682 /* Pods_Trolley_App.framework */;
363
+			productType = "com.apple.product-type.framework";
364
+		};
365
+		D118A6A04828FD3CDA8640CD2B6796D2 /* SwiftyJSON */ = {
366
+			isa = PBXNativeTarget;
367
+			buildConfigurationList = 62468BF9C7EDA172E951A24083C3ECA7 /* Build configuration list for PBXNativeTarget "SwiftyJSON" */;
368
+			buildPhases = (
369
+				3D7DD627DB5C5AD636646E57B685AFB2 /* Headers */,
370
+				1700C451C98D9DCECBEDFC5E351C5A9E /* Sources */,
371
+				AD9C5A8DAF4334B670E91B2EC08DBE2C /* Frameworks */,
372
+				D098F7F0080A87A1F472C81FC2F85528 /* Resources */,
373
+			);
374
+			buildRules = (
375
+			);
376
+			dependencies = (
377
+			);
378
+			name = SwiftyJSON;
379
+			productName = SwiftyJSON;
380
+			productReference = E23C076BA70925415F490FEDB215DA92 /* SwiftyJSON.framework */;
381
+			productType = "com.apple.product-type.framework";
382
+		};
383
+		EAAA1AD3A8A1B59AB91319EE40752C6D /* Alamofire */ = {
384
+			isa = PBXNativeTarget;
385
+			buildConfigurationList = 6B2B8EC7E21CDBFF2BDA26B1B4AC4C0D /* Build configuration list for PBXNativeTarget "Alamofire" */;
386
+			buildPhases = (
387
+				ADDF288DD930A46B5F0F198C225895C9 /* Headers */,
388
+				7349DB0E9BEBE664696F1DCC25226F26 /* Sources */,
389
+				8B0D8633F410345F93419B8C3D7B6916 /* Frameworks */,
390
+				28FC0024B79C28A420D7C4FEBB9E3AEB /* Resources */,
391
+			);
392
+			buildRules = (
393
+			);
394
+			dependencies = (
395
+			);
396
+			name = Alamofire;
397
+			productName = Alamofire;
398
+			productReference = 5D797E9A5C5782CE845840781FA1CC81 /* Alamofire.framework */;
399
+			productType = "com.apple.product-type.framework";
400
+		};
401
+/* End PBXNativeTarget section */
402
+
403
+/* Begin PBXProject section */
404
+		BFDFE7DC352907FC980B868725387E98 /* Project object */ = {
405
+			isa = PBXProject;
406
+			attributes = {
407
+				LastSwiftUpdateCheck = 1100;
408
+				LastUpgradeCheck = 1100;
409
+			};
410
+			buildConfigurationList = 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */;
411
+			compatibilityVersion = "Xcode 9.3";
412
+			developmentRegion = en;
413
+			hasScannedForEncodings = 0;
414
+			knownRegions = (
415
+				en,
416
+				Base,
417
+			);
418
+			mainGroup = CF1408CF629C7361332E53B88F7BD30C;
419
+			productRefGroup = AA892F70254758B4E668FF3B0A8FC86F /* Products */;
420
+			projectDirPath = "";
421
+			projectRoot = "";
422
+			targets = (
423
+				EAAA1AD3A8A1B59AB91319EE40752C6D /* Alamofire */,
424
+				171A0B9EEB8AE346EB29A7957BE4577E /* Pods-Trolley App */,
425
+				D118A6A04828FD3CDA8640CD2B6796D2 /* SwiftyJSON */,
426
+			);
427
+		};
428
+/* End PBXProject section */
429
+
430
+/* Begin PBXResourcesBuildPhase section */
431
+		28FC0024B79C28A420D7C4FEBB9E3AEB /* Resources */ = {
432
+			isa = PBXResourcesBuildPhase;
433
+			buildActionMask = 2147483647;
434
+			files = (
435
+			);
436
+			runOnlyForDeploymentPostprocessing = 0;
437
+		};
438
+		8143C3A9828098CC7CE000480F9730F0 /* Resources */ = {
439
+			isa = PBXResourcesBuildPhase;
440
+			buildActionMask = 2147483647;
441
+			files = (
442
+			);
443
+			runOnlyForDeploymentPostprocessing = 0;
444
+		};
445
+		D098F7F0080A87A1F472C81FC2F85528 /* Resources */ = {
446
+			isa = PBXResourcesBuildPhase;
447
+			buildActionMask = 2147483647;
448
+			files = (
449
+			);
450
+			runOnlyForDeploymentPostprocessing = 0;
451
+		};
452
+/* End PBXResourcesBuildPhase section */
453
+
454
+/* Begin PBXSourcesBuildPhase section */
455
+		1700C451C98D9DCECBEDFC5E351C5A9E /* Sources */ = {
456
+			isa = PBXSourcesBuildPhase;
457
+			buildActionMask = 2147483647;
458
+			files = (
459
+				2BF6FBC0A64BF107C5D64C61F1397770 /* SwiftyJSON-dummy.m in Sources */,
460
+				7B4CE5C84161E2BFE477F42DFD634382 /* SwiftyJSON.swift in Sources */,
461
+			);
462
+			runOnlyForDeploymentPostprocessing = 0;
463
+		};
464
+		7349DB0E9BEBE664696F1DCC25226F26 /* Sources */ = {
465
+			isa = PBXSourcesBuildPhase;
466
+			buildActionMask = 2147483647;
467
+			files = (
468
+				17953A9CF2E354B3E69B9ABC2F367AD9 /* AFError.swift in Sources */,
469
+				B1C58F6CED7B3E45170711D9ADF878AF /* Alamofire-dummy.m in Sources */,
470
+				B788B3354CCEBE56DFDB963CAFD7F6C2 /* Alamofire.swift in Sources */,
471
+				44127C4B989C9CC6A90D78B66A929A5E /* AlamofireExtended.swift in Sources */,
472
+				0AE06C3AEA6CA45342BA703230ABD2CB /* CachedResponseHandler.swift in Sources */,
473
+				E9A5AC2F471699CCA516952A5FEB990B /* DispatchQueue+Alamofire.swift in Sources */,
474
+				CACBD166E573774FB5613C34AA6DA7A7 /* EventMonitor.swift in Sources */,
475
+				56EC8ED1535DAB987F3D2B71D4C05773 /* HTTPHeaders.swift in Sources */,
476
+				B23E9A5CDA31534491226F4C2EE8F8E6 /* HTTPMethod.swift in Sources */,
477
+				5C4A0685B5A201436AB52EF25829B333 /* MultipartFormData.swift in Sources */,
478
+				E07BD425C4EA9ADF15DDFCDB10D0B2FB /* MultipartUpload.swift in Sources */,
479
+				7CF8362BA31492053F5CB165637AE117 /* NetworkReachabilityManager.swift in Sources */,
480
+				C7369563F6946D8984124E1A546B6425 /* Notifications.swift in Sources */,
481
+				92811AC5CD9A5004116AE43C4E8FD955 /* OperationQueue+Alamofire.swift in Sources */,
482
+				5D61C8ED0DDCC9F8B576B6514B19EE50 /* ParameterEncoder.swift in Sources */,
483
+				14AB7976E100075ADEA0AB1DB833E72D /* ParameterEncoding.swift in Sources */,
484
+				0419772A87B16DB7DCF405A9E77D671F /* Protector.swift in Sources */,
485
+				C64AF152F7928CDB59385528DB65FE19 /* RedirectHandler.swift in Sources */,
486
+				6A22C46CB1EDE471794D9AB2AC10327F /* Request.swift in Sources */,
487
+				AD9899986955B2EC1EC20818C860C971 /* RequestInterceptor.swift in Sources */,
488
+				48D97BE7D5CAED273BD2341C239CC934 /* RequestTaskMap.swift in Sources */,
489
+				F71789DC91A75033EFB79DB828676451 /* Response.swift in Sources */,
490
+				13457FE4E607509A3B9527B0711033D5 /* ResponseSerialization.swift in Sources */,
491
+				4082513A35C682F2193D002C80F72B79 /* Result+Alamofire.swift in Sources */,
492
+				D6B2983389480F48F27A0704EEB5DC81 /* RetryPolicy.swift in Sources */,
493
+				0CC43FF0E31AA320ACFEB0FE6239DF34 /* ServerTrustEvaluation.swift in Sources */,
494
+				69ACE4EEE5A8C1C618B22CC1F7B8EF01 /* Session.swift in Sources */,
495
+				42CDB5C986C78BBC8E5C0185F746CABF /* SessionDelegate.swift in Sources */,
496
+				70517C3BAC2D6614347DEAC15299EB84 /* URLConvertible+URLRequestConvertible.swift in Sources */,
497
+				5D12235D061AEE7459279AAF8C348DFE /* URLEncodedFormEncoder.swift in Sources */,
498
+				E4E12208D5246E64B7E6CCAE987ADB03 /* URLRequest+Alamofire.swift in Sources */,
499
+				AF92602937CA016548022C600B8CDC16 /* URLSessionConfiguration+Alamofire.swift in Sources */,
500
+				06507A26118BA5ACFBBC8C225776920E /* Validation.swift in Sources */,
501
+			);
502
+			runOnlyForDeploymentPostprocessing = 0;
503
+		};
504
+		97E712F54AECB1BF4A10C9AF1F9601EC /* Sources */ = {
505
+			isa = PBXSourcesBuildPhase;
506
+			buildActionMask = 2147483647;
507
+			files = (
508
+				68C881E948E0B324AD5C087A6824B2AA /* Pods-Trolley App-dummy.m in Sources */,
509
+			);
510
+			runOnlyForDeploymentPostprocessing = 0;
511
+		};
512
+/* End PBXSourcesBuildPhase section */
513
+
514
+/* Begin PBXTargetDependency section */
515
+		3319C124D3EBBD92EDEC76A250B2AADA /* PBXTargetDependency */ = {
516
+			isa = PBXTargetDependency;
517
+			name = Alamofire;
518
+			target = EAAA1AD3A8A1B59AB91319EE40752C6D /* Alamofire */;
519
+			targetProxy = 36A01FA1C62B729E3DA5A9638A3FC288 /* PBXContainerItemProxy */;
520
+		};
521
+		DB3FBC6E48CA4511B2E99FCB86948EAA /* PBXTargetDependency */ = {
522
+			isa = PBXTargetDependency;
523
+			name = SwiftyJSON;
524
+			target = D118A6A04828FD3CDA8640CD2B6796D2 /* SwiftyJSON */;
525
+			targetProxy = 1DB6BD47CAF1ECF6E02B36A1EEAD3587 /* PBXContainerItemProxy */;
526
+		};
527
+/* End PBXTargetDependency section */
528
+
529
+/* Begin XCBuildConfiguration section */
530
+		00319A2330DC739FCBFBB6CFB0C5F58D /* Debug */ = {
531
+			isa = XCBuildConfiguration;
532
+			baseConfigurationReference = 6BFF6AB28CCA0394147F7105063B2C86 /* Alamofire.xcconfig */;
533
+			buildSettings = {
534
+				CLANG_ENABLE_OBJC_WEAK = NO;
535
+				CODE_SIGN_IDENTITY = "";
536
+				"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
537
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
538
+				"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
539
+				CURRENT_PROJECT_VERSION = 1;
540
+				DEFINES_MODULE = YES;
541
+				DYLIB_COMPATIBILITY_VERSION = 1;
542
+				DYLIB_CURRENT_VERSION = 1;
543
+				DYLIB_INSTALL_NAME_BASE = "@rpath";
544
+				GCC_PREFIX_HEADER = "Target Support Files/Alamofire/Alamofire-prefix.pch";
545
+				INFOPLIST_FILE = "Target Support Files/Alamofire/Alamofire-Info.plist";
546
+				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
547
+				IPHONEOS_DEPLOYMENT_TARGET = 10.0;
548
+				LD_RUNPATH_SEARCH_PATHS = (
549
+					"$(inherited)",
550
+					"@executable_path/Frameworks",
551
+					"@loader_path/Frameworks",
552
+				);
553
+				MODULEMAP_FILE = "Target Support Files/Alamofire/Alamofire.modulemap";
554
+				PRODUCT_MODULE_NAME = Alamofire;
555
+				PRODUCT_NAME = Alamofire;
556
+				SDKROOT = iphoneos;
557
+				SKIP_INSTALL = YES;
558
+				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) ";
559
+				SWIFT_VERSION = 5.1;
560
+				TARGETED_DEVICE_FAMILY = "1,2";
561
+				VERSIONING_SYSTEM = "apple-generic";
562
+				VERSION_INFO_PREFIX = "";
563
+			};
564
+			name = Debug;
565
+		};
566
+		09880EE5F49A6DD73DCE928894E03E82 /* Debug */ = {
567
+			isa = XCBuildConfiguration;
568
+			baseConfigurationReference = 0F04AFD3B2F75EC4D94DCAAAE6F65E3E /* Pods-Trolley App.debug.xcconfig */;
569
+			buildSettings = {
570
+				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO;
571
+				CLANG_ENABLE_OBJC_WEAK = NO;
572
+				CODE_SIGN_IDENTITY = "";
573
+				"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
574
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
575
+				"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
576
+				CURRENT_PROJECT_VERSION = 1;
577
+				DEFINES_MODULE = YES;
578
+				DYLIB_COMPATIBILITY_VERSION = 1;
579
+				DYLIB_CURRENT_VERSION = 1;
580
+				DYLIB_INSTALL_NAME_BASE = "@rpath";
581
+				INFOPLIST_FILE = "Target Support Files/Pods-Trolley App/Pods-Trolley App-Info.plist";
582
+				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
583
+				IPHONEOS_DEPLOYMENT_TARGET = 10.0;
584
+				LD_RUNPATH_SEARCH_PATHS = (
585
+					"$(inherited)",
586
+					"@executable_path/Frameworks",
587
+					"@loader_path/Frameworks",
588
+				);
589
+				MACH_O_TYPE = staticlib;
590
+				MODULEMAP_FILE = "Target Support Files/Pods-Trolley App/Pods-Trolley App.modulemap";
591
+				OTHER_LDFLAGS = "";
592
+				OTHER_LIBTOOLFLAGS = "";
593
+				PODS_ROOT = "$(SRCROOT)";
594
+				PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}";
595
+				PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
596
+				SDKROOT = iphoneos;
597
+				SKIP_INSTALL = YES;
598
+				TARGETED_DEVICE_FAMILY = "1,2";
599
+				VERSIONING_SYSTEM = "apple-generic";
600
+				VERSION_INFO_PREFIX = "";
601
+			};
602
+			name = Debug;
603
+		};
604
+		196DFA3E4A09A28224918543529A1885 /* Debug */ = {
605
+			isa = XCBuildConfiguration;
606
+			buildSettings = {
607
+				ALWAYS_SEARCH_USER_PATHS = NO;
608
+				CLANG_ANALYZER_NONNULL = YES;
609
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
610
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
611
+				CLANG_CXX_LIBRARY = "libc++";
612
+				CLANG_ENABLE_MODULES = YES;
613
+				CLANG_ENABLE_OBJC_ARC = YES;
614
+				CLANG_ENABLE_OBJC_WEAK = YES;
615
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
616
+				CLANG_WARN_BOOL_CONVERSION = YES;
617
+				CLANG_WARN_COMMA = YES;
618
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
619
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
620
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
621
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
622
+				CLANG_WARN_EMPTY_BODY = YES;
623
+				CLANG_WARN_ENUM_CONVERSION = YES;
624
+				CLANG_WARN_INFINITE_RECURSION = YES;
625
+				CLANG_WARN_INT_CONVERSION = YES;
626
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
627
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
628
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
629
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
630
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
631
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
632
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
633
+				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
634
+				CLANG_WARN_UNREACHABLE_CODE = YES;
635
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
636
+				COPY_PHASE_STRIP = NO;
637
+				DEBUG_INFORMATION_FORMAT = dwarf;
638
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
639
+				ENABLE_TESTABILITY = YES;
640
+				GCC_C_LANGUAGE_STANDARD = gnu11;
641
+				GCC_DYNAMIC_NO_PIC = NO;
642
+				GCC_NO_COMMON_BLOCKS = YES;
643
+				GCC_OPTIMIZATION_LEVEL = 0;
644
+				GCC_PREPROCESSOR_DEFINITIONS = (
645
+					"POD_CONFIGURATION_DEBUG=1",
646
+					"DEBUG=1",
647
+					"$(inherited)",
648
+				);
649
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
650
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
651
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
652
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
653
+				GCC_WARN_UNUSED_FUNCTION = YES;
654
+				GCC_WARN_UNUSED_VARIABLE = YES;
655
+				IPHONEOS_DEPLOYMENT_TARGET = 10.0;
656
+				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
657
+				MTL_FAST_MATH = YES;
658
+				ONLY_ACTIVE_ARCH = YES;
659
+				PRODUCT_NAME = "$(TARGET_NAME)";
660
+				STRIP_INSTALLED_PRODUCT = NO;
661
+				SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
662
+				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
663
+				SWIFT_VERSION = 5.0;
664
+				SYMROOT = "${SRCROOT}/../build";
665
+			};
666
+			name = Debug;
667
+		};
668
+		699B60D7404DE827B94037923F577203 /* Release */ = {
669
+			isa = XCBuildConfiguration;
670
+			baseConfigurationReference = 7A9E60B1A018CCFB58106BB429914737 /* Pods-Trolley App.release.xcconfig */;
671
+			buildSettings = {
672
+				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO;
673
+				CLANG_ENABLE_OBJC_WEAK = NO;
674
+				CODE_SIGN_IDENTITY = "";
675
+				"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
676
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
677
+				"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
678
+				CURRENT_PROJECT_VERSION = 1;
679
+				DEFINES_MODULE = YES;
680
+				DYLIB_COMPATIBILITY_VERSION = 1;
681
+				DYLIB_CURRENT_VERSION = 1;
682
+				DYLIB_INSTALL_NAME_BASE = "@rpath";
683
+				INFOPLIST_FILE = "Target Support Files/Pods-Trolley App/Pods-Trolley App-Info.plist";
684
+				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
685
+				IPHONEOS_DEPLOYMENT_TARGET = 10.0;
686
+				LD_RUNPATH_SEARCH_PATHS = (
687
+					"$(inherited)",
688
+					"@executable_path/Frameworks",
689
+					"@loader_path/Frameworks",
690
+				);
691
+				MACH_O_TYPE = staticlib;
692
+				MODULEMAP_FILE = "Target Support Files/Pods-Trolley App/Pods-Trolley App.modulemap";
693
+				OTHER_LDFLAGS = "";
694
+				OTHER_LIBTOOLFLAGS = "";
695
+				PODS_ROOT = "$(SRCROOT)";
696
+				PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}";
697
+				PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
698
+				SDKROOT = iphoneos;
699
+				SKIP_INSTALL = YES;
700
+				TARGETED_DEVICE_FAMILY = "1,2";
701
+				VALIDATE_PRODUCT = YES;
702
+				VERSIONING_SYSTEM = "apple-generic";
703
+				VERSION_INFO_PREFIX = "";
704
+			};
705
+			name = Release;
706
+		};
707
+		6E2226BAF771B9AEEA8FE646C18E7879 /* Release */ = {
708
+			isa = XCBuildConfiguration;
709
+			baseConfigurationReference = 2F8C726BF7AEBB3DF201B63EE8AC4EDC /* SwiftyJSON.xcconfig */;
710
+			buildSettings = {
711
+				CODE_SIGN_IDENTITY = "";
712
+				"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
713
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
714
+				"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
715
+				CURRENT_PROJECT_VERSION = 1;
716
+				DEFINES_MODULE = YES;
717
+				DYLIB_COMPATIBILITY_VERSION = 1;
718
+				DYLIB_CURRENT_VERSION = 1;
719
+				DYLIB_INSTALL_NAME_BASE = "@rpath";
720
+				GCC_PREFIX_HEADER = "Target Support Files/SwiftyJSON/SwiftyJSON-prefix.pch";
721
+				INFOPLIST_FILE = "Target Support Files/SwiftyJSON/SwiftyJSON-Info.plist";
722
+				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
723
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
724
+				LD_RUNPATH_SEARCH_PATHS = (
725
+					"$(inherited)",
726
+					"@executable_path/Frameworks",
727
+					"@loader_path/Frameworks",
728
+				);
729
+				MODULEMAP_FILE = "Target Support Files/SwiftyJSON/SwiftyJSON.modulemap";
730
+				PRODUCT_MODULE_NAME = SwiftyJSON;
731
+				PRODUCT_NAME = SwiftyJSON;
732
+				SDKROOT = iphoneos;
733
+				SKIP_INSTALL = YES;
734
+				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) ";
735
+				SWIFT_VERSION = 5.0;
736
+				TARGETED_DEVICE_FAMILY = "1,2";
737
+				VALIDATE_PRODUCT = YES;
738
+				VERSIONING_SYSTEM = "apple-generic";
739
+				VERSION_INFO_PREFIX = "";
740
+			};
741
+			name = Release;
742
+		};
743
+		B01D14FDC83DCF9D4BE53066BEA96D05 /* Release */ = {
744
+			isa = XCBuildConfiguration;
745
+			buildSettings = {
746
+				ALWAYS_SEARCH_USER_PATHS = NO;
747
+				CLANG_ANALYZER_NONNULL = YES;
748
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
749
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
750
+				CLANG_CXX_LIBRARY = "libc++";
751
+				CLANG_ENABLE_MODULES = YES;
752
+				CLANG_ENABLE_OBJC_ARC = YES;
753
+				CLANG_ENABLE_OBJC_WEAK = YES;
754
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
755
+				CLANG_WARN_BOOL_CONVERSION = YES;
756
+				CLANG_WARN_COMMA = YES;
757
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
758
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
759
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
760
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
761
+				CLANG_WARN_EMPTY_BODY = YES;
762
+				CLANG_WARN_ENUM_CONVERSION = YES;
763
+				CLANG_WARN_INFINITE_RECURSION = YES;
764
+				CLANG_WARN_INT_CONVERSION = YES;
765
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
766
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
767
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
768
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
769
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
770
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
771
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
772
+				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
773
+				CLANG_WARN_UNREACHABLE_CODE = YES;
774
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
775
+				COPY_PHASE_STRIP = NO;
776
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
777
+				ENABLE_NS_ASSERTIONS = NO;
778
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
779
+				GCC_C_LANGUAGE_STANDARD = gnu11;
780
+				GCC_NO_COMMON_BLOCKS = YES;
781
+				GCC_PREPROCESSOR_DEFINITIONS = (
782
+					"POD_CONFIGURATION_RELEASE=1",
783
+					"$(inherited)",
784
+				);
785
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
786
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
787
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
788
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
789
+				GCC_WARN_UNUSED_FUNCTION = YES;
790
+				GCC_WARN_UNUSED_VARIABLE = YES;
791
+				IPHONEOS_DEPLOYMENT_TARGET = 10.0;
792
+				MTL_ENABLE_DEBUG_INFO = NO;
793
+				MTL_FAST_MATH = YES;
794
+				PRODUCT_NAME = "$(TARGET_NAME)";
795
+				STRIP_INSTALLED_PRODUCT = NO;
796
+				SWIFT_COMPILATION_MODE = wholemodule;
797
+				SWIFT_OPTIMIZATION_LEVEL = "-O";
798
+				SWIFT_VERSION = 5.0;
799
+				SYMROOT = "${SRCROOT}/../build";
800
+			};
801
+			name = Release;
802
+		};
803
+		E8F35927ECB754A46E0AC8C2BACAF32D /* Debug */ = {
804
+			isa = XCBuildConfiguration;
805
+			baseConfigurationReference = 2F8C726BF7AEBB3DF201B63EE8AC4EDC /* SwiftyJSON.xcconfig */;
806
+			buildSettings = {
807
+				CODE_SIGN_IDENTITY = "";
808
+				"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
809
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
810
+				"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
811
+				CURRENT_PROJECT_VERSION = 1;
812
+				DEFINES_MODULE = YES;
813
+				DYLIB_COMPATIBILITY_VERSION = 1;
814
+				DYLIB_CURRENT_VERSION = 1;
815
+				DYLIB_INSTALL_NAME_BASE = "@rpath";
816
+				GCC_PREFIX_HEADER = "Target Support Files/SwiftyJSON/SwiftyJSON-prefix.pch";
817
+				INFOPLIST_FILE = "Target Support Files/SwiftyJSON/SwiftyJSON-Info.plist";
818
+				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
819
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
820
+				LD_RUNPATH_SEARCH_PATHS = (
821
+					"$(inherited)",
822
+					"@executable_path/Frameworks",
823
+					"@loader_path/Frameworks",
824
+				);
825
+				MODULEMAP_FILE = "Target Support Files/SwiftyJSON/SwiftyJSON.modulemap";
826
+				PRODUCT_MODULE_NAME = SwiftyJSON;
827
+				PRODUCT_NAME = SwiftyJSON;
828
+				SDKROOT = iphoneos;
829
+				SKIP_INSTALL = YES;
830
+				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) ";
831
+				SWIFT_VERSION = 5.0;
832
+				TARGETED_DEVICE_FAMILY = "1,2";
833
+				VERSIONING_SYSTEM = "apple-generic";
834
+				VERSION_INFO_PREFIX = "";
835
+			};
836
+			name = Debug;
837
+		};
838
+		F659822BFF3B3C20B29B76B89800A5E9 /* Release */ = {
839
+			isa = XCBuildConfiguration;
840
+			baseConfigurationReference = 6BFF6AB28CCA0394147F7105063B2C86 /* Alamofire.xcconfig */;
841
+			buildSettings = {
842
+				CLANG_ENABLE_OBJC_WEAK = NO;
843
+				CODE_SIGN_IDENTITY = "";
844
+				"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
845
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
846
+				"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
847
+				CURRENT_PROJECT_VERSION = 1;
848
+				DEFINES_MODULE = YES;
849
+				DYLIB_COMPATIBILITY_VERSION = 1;
850
+				DYLIB_CURRENT_VERSION = 1;
851
+				DYLIB_INSTALL_NAME_BASE = "@rpath";
852
+				GCC_PREFIX_HEADER = "Target Support Files/Alamofire/Alamofire-prefix.pch";
853
+				INFOPLIST_FILE = "Target Support Files/Alamofire/Alamofire-Info.plist";
854
+				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
855
+				IPHONEOS_DEPLOYMENT_TARGET = 10.0;
856
+				LD_RUNPATH_SEARCH_PATHS = (
857
+					"$(inherited)",
858
+					"@executable_path/Frameworks",
859
+					"@loader_path/Frameworks",
860
+				);
861
+				MODULEMAP_FILE = "Target Support Files/Alamofire/Alamofire.modulemap";
862
+				PRODUCT_MODULE_NAME = Alamofire;
863
+				PRODUCT_NAME = Alamofire;
864
+				SDKROOT = iphoneos;
865
+				SKIP_INSTALL = YES;
866
+				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) ";
867
+				SWIFT_VERSION = 5.1;
868
+				TARGETED_DEVICE_FAMILY = "1,2";
869
+				VALIDATE_PRODUCT = YES;
870
+				VERSIONING_SYSTEM = "apple-generic";
871
+				VERSION_INFO_PREFIX = "";
872
+			};
873
+			name = Release;
874
+		};
875
+/* End XCBuildConfiguration section */
876
+
877
+/* Begin XCConfigurationList section */
878
+		4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = {
879
+			isa = XCConfigurationList;
880
+			buildConfigurations = (
881
+				196DFA3E4A09A28224918543529A1885 /* Debug */,
882
+				B01D14FDC83DCF9D4BE53066BEA96D05 /* Release */,
883
+			);
884
+			defaultConfigurationIsVisible = 0;
885
+			defaultConfigurationName = Release;
886
+		};
887
+		510CECFBE569732973A1CF992AB0AC87 /* Build configuration list for PBXNativeTarget "Pods-Trolley App" */ = {
888
+			isa = XCConfigurationList;
889
+			buildConfigurations = (
890
+				09880EE5F49A6DD73DCE928894E03E82 /* Debug */,
891
+				699B60D7404DE827B94037923F577203 /* Release */,
892
+			);
893
+			defaultConfigurationIsVisible = 0;
894
+			defaultConfigurationName = Release;
895
+		};
896
+		62468BF9C7EDA172E951A24083C3ECA7 /* Build configuration list for PBXNativeTarget "SwiftyJSON" */ = {
897
+			isa = XCConfigurationList;
898
+			buildConfigurations = (
899
+				E8F35927ECB754A46E0AC8C2BACAF32D /* Debug */,
900
+				6E2226BAF771B9AEEA8FE646C18E7879 /* Release */,
901
+			);
902
+			defaultConfigurationIsVisible = 0;
903
+			defaultConfigurationName = Release;
904
+		};
905
+		6B2B8EC7E21CDBFF2BDA26B1B4AC4C0D /* Build configuration list for PBXNativeTarget "Alamofire" */ = {
906
+			isa = XCConfigurationList;
907
+			buildConfigurations = (
908
+				00319A2330DC739FCBFBB6CFB0C5F58D /* Debug */,
909
+				F659822BFF3B3C20B29B76B89800A5E9 /* Release */,
910
+			);
911
+			defaultConfigurationIsVisible = 0;
912
+			defaultConfigurationName = Release;
913
+		};
914
+/* End XCConfigurationList section */
915
+	};
916
+	rootObject = BFDFE7DC352907FC980B868725387E98 /* Project object */;
917
+}

+ 60
- 0
trolley/Pods/Pods.xcodeproj/xcuserdata/stephanie.marie.xcuserdatad/xcschemes/Alamofire.xcscheme 查看文件

@@ -0,0 +1,60 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<Scheme
3
+   LastUpgradeVersion = "1100"
4
+   version = "1.3">
5
+   <BuildAction
6
+      parallelizeBuildables = "YES"
7
+      buildImplicitDependencies = "YES">
8
+      <BuildActionEntries>
9
+         <BuildActionEntry
10
+            buildForAnalyzing = "YES"
11
+            buildForTesting = "YES"
12
+            buildForRunning = "YES"
13
+            buildForProfiling = "YES"
14
+            buildForArchiving = "YES">
15
+            <BuildableReference
16
+               BuildableIdentifier = "primary"
17
+               BlueprintIdentifier = "EAAA1AD3A8A1B59AB91319EE40752C6D"
18
+               BuildableName = "Alamofire.framework"
19
+               BlueprintName = "Alamofire"
20
+               ReferencedContainer = "container:Pods.xcodeproj">
21
+            </BuildableReference>
22
+         </BuildActionEntry>
23
+      </BuildActionEntries>
24
+   </BuildAction>
25
+   <TestAction
26
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
27
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
28
+      shouldUseLaunchSchemeArgsEnv = "YES"
29
+      buildConfiguration = "Debug">
30
+      <AdditionalOptions>
31
+      </AdditionalOptions>
32
+   </TestAction>
33
+   <LaunchAction
34
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
35
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
36
+      launchStyle = "0"
37
+      useCustomWorkingDirectory = "NO"
38
+      ignoresPersistentStateOnLaunch = "NO"
39
+      debugDocumentVersioning = "YES"
40
+      debugServiceExtension = "internal"
41
+      buildConfiguration = "Debug"
42
+      allowLocationSimulation = "YES">
43
+      <AdditionalOptions>
44
+      </AdditionalOptions>
45
+   </LaunchAction>
46
+   <ProfileAction
47
+      savedToolIdentifier = ""
48
+      useCustomWorkingDirectory = "NO"
49
+      debugDocumentVersioning = "YES"
50
+      buildConfiguration = "Release"
51
+      shouldUseLaunchSchemeArgsEnv = "YES">
52
+   </ProfileAction>
53
+   <AnalyzeAction
54
+      buildConfiguration = "Debug">
55
+   </AnalyzeAction>
56
+   <ArchiveAction
57
+      buildConfiguration = "Release"
58
+      revealArchiveInOrganizer = "YES">
59
+   </ArchiveAction>
60
+</Scheme>

+ 58
- 0
trolley/Pods/Pods.xcodeproj/xcuserdata/stephanie.marie.xcuserdatad/xcschemes/Pods-Trolley App.xcscheme 查看文件

@@ -0,0 +1,58 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<Scheme
3
+   LastUpgradeVersion = "1100"
4
+   version = "1.3">
5
+   <BuildAction
6
+      parallelizeBuildables = "YES"
7
+      buildImplicitDependencies = "YES">
8
+      <BuildActionEntries>
9
+         <BuildActionEntry
10
+            buildForTesting = "YES"
11
+            buildForRunning = "YES"
12
+            buildForProfiling = "YES"
13
+            buildForArchiving = "YES"
14
+            buildForAnalyzing = "YES">
15
+            <BuildableReference
16
+               BuildableIdentifier = "primary"
17
+               BlueprintIdentifier = "171A0B9EEB8AE346EB29A7957BE4577E"
18
+               BuildableName = "Pods_Trolley_App.framework"
19
+               BlueprintName = "Pods-Trolley App"
20
+               ReferencedContainer = "container:Pods.xcodeproj">
21
+            </BuildableReference>
22
+         </BuildActionEntry>
23
+      </BuildActionEntries>
24
+   </BuildAction>
25
+   <TestAction
26
+      buildConfiguration = "Debug"
27
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
28
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
29
+      shouldUseLaunchSchemeArgsEnv = "YES">
30
+      <Testables>
31
+      </Testables>
32
+   </TestAction>
33
+   <LaunchAction
34
+      buildConfiguration = "Debug"
35
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
36
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
37
+      launchStyle = "0"
38
+      useCustomWorkingDirectory = "NO"
39
+      ignoresPersistentStateOnLaunch = "NO"
40
+      debugDocumentVersioning = "YES"
41
+      debugServiceExtension = "internal"
42
+      allowLocationSimulation = "YES">
43
+   </LaunchAction>
44
+   <ProfileAction
45
+      buildConfiguration = "Release"
46
+      shouldUseLaunchSchemeArgsEnv = "YES"
47
+      savedToolIdentifier = ""
48
+      useCustomWorkingDirectory = "NO"
49
+      debugDocumentVersioning = "YES">
50
+   </ProfileAction>
51
+   <AnalyzeAction
52
+      buildConfiguration = "Debug">
53
+   </AnalyzeAction>
54
+   <ArchiveAction
55
+      buildConfiguration = "Release"
56
+      revealArchiveInOrganizer = "YES">
57
+   </ArchiveAction>
58
+</Scheme>

+ 60
- 0
trolley/Pods/Pods.xcodeproj/xcuserdata/stephanie.marie.xcuserdatad/xcschemes/SwiftyJSON.xcscheme 查看文件

@@ -0,0 +1,60 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<Scheme
3
+   LastUpgradeVersion = "1100"
4
+   version = "1.3">
5
+   <BuildAction
6
+      parallelizeBuildables = "YES"
7
+      buildImplicitDependencies = "YES">
8
+      <BuildActionEntries>
9
+         <BuildActionEntry
10
+            buildForAnalyzing = "YES"
11
+            buildForTesting = "YES"
12
+            buildForRunning = "YES"
13
+            buildForProfiling = "YES"
14
+            buildForArchiving = "YES">
15
+            <BuildableReference
16
+               BuildableIdentifier = "primary"
17
+               BlueprintIdentifier = "D118A6A04828FD3CDA8640CD2B6796D2"
18
+               BuildableName = "SwiftyJSON.framework"
19
+               BlueprintName = "SwiftyJSON"
20
+               ReferencedContainer = "container:Pods.xcodeproj">
21
+            </BuildableReference>
22
+         </BuildActionEntry>
23
+      </BuildActionEntries>
24
+   </BuildAction>
25
+   <TestAction
26
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
27
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
28
+      shouldUseLaunchSchemeArgsEnv = "YES"
29
+      buildConfiguration = "Debug">
30
+      <AdditionalOptions>
31
+      </AdditionalOptions>
32
+   </TestAction>
33
+   <LaunchAction
34
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
35
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
36
+      launchStyle = "0"
37
+      useCustomWorkingDirectory = "NO"
38
+      ignoresPersistentStateOnLaunch = "NO"
39
+      debugDocumentVersioning = "YES"
40
+      debugServiceExtension = "internal"
41
+      buildConfiguration = "Debug"
42
+      allowLocationSimulation = "YES">
43
+      <AdditionalOptions>
44
+      </AdditionalOptions>
45
+   </LaunchAction>
46
+   <ProfileAction
47
+      savedToolIdentifier = ""
48
+      useCustomWorkingDirectory = "NO"
49
+      debugDocumentVersioning = "YES"
50
+      buildConfiguration = "Release"
51
+      shouldUseLaunchSchemeArgsEnv = "YES">
52
+   </ProfileAction>
53
+   <AnalyzeAction
54
+      buildConfiguration = "Debug">
55
+   </AnalyzeAction>
56
+   <ArchiveAction
57
+      buildConfiguration = "Release"
58
+      revealArchiveInOrganizer = "YES">
59
+   </ArchiveAction>
60
+</Scheme>

+ 32
- 0
trolley/Pods/Pods.xcodeproj/xcuserdata/stephanie.marie.xcuserdatad/xcschemes/xcschememanagement.plist 查看文件

@@ -0,0 +1,32 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+<plist version="1.0">
4
+<dict>
5
+	<key>SchemeUserState</key>
6
+	<dict>
7
+		<key>Alamofire.xcscheme</key>
8
+		<dict>
9
+			<key>isShown</key>
10
+			<false/>
11
+			<key>orderHint</key>
12
+			<integer>0</integer>
13
+		</dict>
14
+		<key>Pods-Trolley App.xcscheme</key>
15
+		<dict>
16
+			<key>isShown</key>
17
+			<false/>
18
+			<key>orderHint</key>
19
+			<integer>1</integer>
20
+		</dict>
21
+		<key>SwiftyJSON.xcscheme</key>
22
+		<dict>
23
+			<key>isShown</key>
24
+			<false/>
25
+			<key>orderHint</key>
26
+			<integer>2</integer>
27
+		</dict>
28
+	</dict>
29
+	<key>SuppressBuildableAutocreation</key>
30
+	<dict/>
31
+</dict>
32
+</plist>

+ 60
- 0
trolley/Pods/Pods.xcodeproj/xcuserdata/stephaniem.ramos.xcuserdatad/xcschemes/Alamofire.xcscheme 查看文件

@@ -0,0 +1,60 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<Scheme
3
+   LastUpgradeVersion = "1100"
4
+   version = "1.3">
5
+   <BuildAction
6
+      parallelizeBuildables = "YES"
7
+      buildImplicitDependencies = "YES">
8
+      <BuildActionEntries>
9
+         <BuildActionEntry
10
+            buildForAnalyzing = "YES"
11
+            buildForTesting = "YES"
12
+            buildForRunning = "YES"
13
+            buildForProfiling = "YES"
14
+            buildForArchiving = "YES">
15
+            <BuildableReference
16
+               BuildableIdentifier = "primary"
17
+               BlueprintIdentifier = "EAAA1AD3A8A1B59AB91319EE40752C6D"
18
+               BuildableName = "Alamofire.framework"
19
+               BlueprintName = "Alamofire"
20
+               ReferencedContainer = "container:Pods.xcodeproj">
21
+            </BuildableReference>
22
+         </BuildActionEntry>
23
+      </BuildActionEntries>
24
+   </BuildAction>
25
+   <TestAction
26
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
27
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
28
+      shouldUseLaunchSchemeArgsEnv = "YES"
29
+      buildConfiguration = "Debug">
30
+      <AdditionalOptions>
31
+      </AdditionalOptions>
32
+   </TestAction>
33
+   <LaunchAction
34
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
35
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
36
+      launchStyle = "0"
37
+      useCustomWorkingDirectory = "NO"
38
+      ignoresPersistentStateOnLaunch = "NO"
39
+      debugDocumentVersioning = "YES"
40
+      debugServiceExtension = "internal"
41
+      buildConfiguration = "Debug"
42
+      allowLocationSimulation = "YES">
43
+      <AdditionalOptions>
44
+      </AdditionalOptions>
45
+   </LaunchAction>
46
+   <ProfileAction
47
+      savedToolIdentifier = ""
48
+      useCustomWorkingDirectory = "NO"
49
+      debugDocumentVersioning = "YES"
50
+      buildConfiguration = "Release"
51
+      shouldUseLaunchSchemeArgsEnv = "YES">
52
+   </ProfileAction>
53
+   <AnalyzeAction
54
+      buildConfiguration = "Debug">
55
+   </AnalyzeAction>
56
+   <ArchiveAction
57
+      buildConfiguration = "Release"
58
+      revealArchiveInOrganizer = "YES">
59
+   </ArchiveAction>
60
+</Scheme>

+ 58
- 0
trolley/Pods/Pods.xcodeproj/xcuserdata/stephaniem.ramos.xcuserdatad/xcschemes/Pods-Trolley App.xcscheme 查看文件

@@ -0,0 +1,58 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<Scheme
3
+   LastUpgradeVersion = "1100"
4
+   version = "1.3">
5
+   <BuildAction
6
+      parallelizeBuildables = "YES"
7
+      buildImplicitDependencies = "YES">
8
+      <BuildActionEntries>
9
+         <BuildActionEntry
10
+            buildForTesting = "YES"
11
+            buildForRunning = "YES"
12
+            buildForProfiling = "YES"
13
+            buildForArchiving = "YES"
14
+            buildForAnalyzing = "YES">
15
+            <BuildableReference
16
+               BuildableIdentifier = "primary"
17
+               BlueprintIdentifier = "171A0B9EEB8AE346EB29A7957BE4577E"
18
+               BuildableName = "Pods_Trolley_App.framework"
19
+               BlueprintName = "Pods-Trolley App"
20
+               ReferencedContainer = "container:Pods.xcodeproj">
21
+            </BuildableReference>
22
+         </BuildActionEntry>
23
+      </BuildActionEntries>
24
+   </BuildAction>
25
+   <TestAction
26
+      buildConfiguration = "Debug"
27
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
28
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
29
+      shouldUseLaunchSchemeArgsEnv = "YES">
30
+      <Testables>
31
+      </Testables>
32
+   </TestAction>
33
+   <LaunchAction
34
+      buildConfiguration = "Debug"
35
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
36
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
37
+      launchStyle = "0"
38
+      useCustomWorkingDirectory = "NO"
39
+      ignoresPersistentStateOnLaunch = "NO"
40
+      debugDocumentVersioning = "YES"
41
+      debugServiceExtension = "internal"
42
+      allowLocationSimulation = "YES">
43
+   </LaunchAction>
44
+   <ProfileAction
45
+      buildConfiguration = "Release"
46
+      shouldUseLaunchSchemeArgsEnv = "YES"
47
+      savedToolIdentifier = ""
48
+      useCustomWorkingDirectory = "NO"
49
+      debugDocumentVersioning = "YES">
50
+   </ProfileAction>
51
+   <AnalyzeAction
52
+      buildConfiguration = "Debug">
53
+   </AnalyzeAction>
54
+   <ArchiveAction
55
+      buildConfiguration = "Release"
56
+      revealArchiveInOrganizer = "YES">
57
+   </ArchiveAction>
58
+</Scheme>

+ 25
- 0
trolley/Pods/Pods.xcodeproj/xcuserdata/stephaniem.ramos.xcuserdatad/xcschemes/xcschememanagement.plist 查看文件

@@ -0,0 +1,25 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+<plist version="1.0">
4
+<dict>
5
+	<key>SchemeUserState</key>
6
+	<dict>
7
+		<key>Alamofire.xcscheme</key>
8
+		<dict>
9
+			<key>isShown</key>
10
+			<false/>
11
+			<key>orderHint</key>
12
+			<integer>0</integer>
13
+		</dict>
14
+		<key>Pods-Trolley App.xcscheme</key>
15
+		<dict>
16
+			<key>isShown</key>
17
+			<false/>
18
+			<key>orderHint</key>
19
+			<integer>1</integer>
20
+		</dict>
21
+	</dict>
22
+	<key>SuppressBuildableAutocreation</key>
23
+	<dict/>
24
+</dict>
25
+</plist>

+ 21
- 0
trolley/Pods/SwiftyJSON/LICENSE 查看文件

@@ -0,0 +1,21 @@
1
+The MIT License (MIT)
2
+
3
+Copyright (c) 2017 Ruoyu Fu
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.

+ 562
- 0
trolley/Pods/SwiftyJSON/README.md 查看文件

@@ -0,0 +1,562 @@
1
+# SwiftyJSON
2
+
3
+[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) ![CocoaPods](https://img.shields.io/cocoapods/v/SwiftyJSON.svg) ![Platform](https://img.shields.io/badge/platforms-iOS%208.0%20%7C%20macOS%2010.10%20%7C%20tvOS%209.0%20%7C%20watchOS%203.0-F28D00.svg) [![Reviewed by Hound](https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg)](https://houndci.com)
4
+
5
+SwiftyJSON makes it easy to deal with JSON data in Swift.
6
+
7
+Platform | Build Status
8
+---------| --------------| 
9
+*OS      | [![Travis CI](https://travis-ci.org/SwiftyJSON/SwiftyJSON.svg?branch=master)](https://travis-ci.org/SwiftyJSON/SwiftyJSON)    | 
10
+[Linux](https://github.com/IBM-Swift/SwiftyJSON)      | [![Build Status](https://travis-ci.org/IBM-Swift/SwiftyJSON.svg?branch=master)](https://travis-ci.org/IBM-Swift/SwiftyJSON)     | 
11
+
12
+
13
+1. [Why is the typical JSON handling in Swift NOT good](#why-is-the-typical-json-handling-in-swift-not-good)
14
+2. [Requirements](#requirements)
15
+3. [Integration](#integration)
16
+4. [Usage](#usage)
17
+   - [Initialization](#initialization)
18
+   - [Subscript](#subscript)
19
+   - [Loop](#loop)
20
+   - [Error](#error)
21
+   - [Optional getter](#optional-getter)
22
+   - [Non-optional getter](#non-optional-getter)
23
+   - [Setter](#setter)
24
+   - [Raw object](#raw-object)
25
+   - [Literal convertibles](#literal-convertibles)
26
+   - [Merging](#merging)
27
+5. [Work with Alamofire](#work-with-alamofire)
28
+6. [Work with Moya](#work-with-moya)
29
+7. [SwiftyJSON Model Generator](#swiftyjson-model-generator)
30
+
31
+> [中文介绍](http://tangplin.github.io/swiftyjson/)
32
+
33
+
34
+## Why is the typical JSON handling in Swift NOT good?
35
+
36
+Swift is very strict about types. But although explicit typing is good for saving us from mistakes, it becomes painful when dealing with JSON and other areas that are, by nature, implicit about types.
37
+
38
+Take the Twitter API for example. Say we want to retrieve a user's "name" value of some tweet in Swift (according to [Twitter's API](https://developer.twitter.com/en/docs/tweets/timelines/api-reference/get-statuses-home_timeline)).
39
+
40
+The code would look like this:
41
+
42
+```swift
43
+if let statusesArray = try? JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [[String: Any]],
44
+    let user = statusesArray[0]["user"] as? [String: Any],
45
+    let username = user["name"] as? String {
46
+    // Finally we got the username
47
+}
48
+```
49
+
50
+It's not good.
51
+
52
+Even if we use optional chaining, it would be messy:
53
+
54
+```swift
55
+if let JSONObject = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [[String: Any]],
56
+    let username = (JSONObject[0]["user"] as? [String: Any])?["name"] as? String {
57
+        // There's our username
58
+}
59
+```
60
+
61
+An unreadable mess--for something that should really be simple!
62
+
63
+With SwiftyJSON all you have to do is:
64
+
65
+```swift
66
+let json = JSON(data: dataFromNetworking)
67
+if let userName = json[0]["user"]["name"].string {
68
+  //Now you got your value
69
+}
70
+```
71
+
72
+And don't worry about the Optional Wrapping thing. It's done for you automatically.
73
+
74
+```swift
75
+let json = JSON(data: dataFromNetworking)
76
+let result = json[999999]["wrong_key"]["wrong_name"]
77
+if let userName = result.string {
78
+    //Calm down, take it easy, the ".string" property still produces the correct Optional String type with safety
79
+} else {
80
+    //Print the error
81
+    print(result.error)
82
+}
83
+```
84
+
85
+## Requirements
86
+
87
+- iOS 8.0+ | macOS 10.10+ | tvOS 9.0+ | watchOS 2.0+
88
+- Xcode 8
89
+
90
+## Integration
91
+
92
+#### CocoaPods (iOS 8+, OS X 10.9+)
93
+
94
+You can use [CocoaPods](http://cocoapods.org/) to install `SwiftyJSON` by adding it to your `Podfile`:
95
+
96
+```ruby
97
+platform :ios, '8.0'
98
+use_frameworks!
99
+
100
+target 'MyApp' do
101
+    pod 'SwiftyJSON', '~> 4.0'
102
+end
103
+```
104
+
105
+#### Carthage (iOS 8+, OS X 10.9+)
106
+
107
+You can use [Carthage](https://github.com/Carthage/Carthage) to install `SwiftyJSON` by adding it to your `Cartfile`:
108
+
109
+```
110
+github "SwiftyJSON/SwiftyJSON" ~> 4.0
111
+```
112
+
113
+If you use Carthage to build your dependencies, make sure you have added `SwiftyJSON.framework` to the "Linked Frameworks and Libraries" section of your target, and have included them in your Carthage framework copying build phase.
114
+
115
+#### Swift Package Manager
116
+
117
+You can use [The Swift Package Manager](https://swift.org/package-manager) to install `SwiftyJSON` by adding the proper description to your `Package.swift` file:
118
+
119
+```swift
120
+// swift-tools-version:4.0
121
+import PackageDescription
122
+
123
+let package = Package(
124
+    name: "YOUR_PROJECT_NAME",
125
+    dependencies: [
126
+        .package(url: "https://github.com/SwiftyJSON/SwiftyJSON.git", from: "4.0.0"),
127
+    ]
128
+)
129
+```
130
+Then run `swift build` whenever you get prepared.
131
+
132
+#### Manually (iOS 7+, OS X 10.9+)
133
+
134
+To use this library in your project manually you may:  
135
+
136
+1. for Projects, just drag SwiftyJSON.swift to the project tree
137
+2. for Workspaces, include the whole SwiftyJSON.xcodeproj
138
+
139
+## Usage
140
+
141
+#### Initialization
142
+
143
+```swift
144
+import SwiftyJSON
145
+```
146
+
147
+```swift
148
+let json = JSON(data: dataFromNetworking)
149
+```
150
+Or
151
+
152
+```swift
153
+let json = JSON(jsonObject)
154
+```
155
+Or
156
+
157
+```swift
158
+if let dataFromString = jsonString.data(using: .utf8, allowLossyConversion: false) {
159
+    let json = JSON(data: dataFromString)
160
+}
161
+```
162
+
163
+#### Subscript
164
+
165
+```swift
166
+// Getting a double from a JSON Array
167
+let name = json[0].double
168
+```
169
+
170
+```swift
171
+// Getting an array of string from a JSON Array
172
+let arrayNames =  json["users"].arrayValue.map {$0["name"].stringValue}
173
+```
174
+
175
+```swift
176
+// Getting a string from a JSON Dictionary
177
+let name = json["name"].stringValue
178
+```
179
+
180
+```swift
181
+// Getting a string using a path to the element
182
+let path: [JSONSubscriptType] = [1,"list",2,"name"]
183
+let name = json[path].string
184
+// Just the same
185
+let name = json[1]["list"][2]["name"].string
186
+// Alternatively
187
+let name = json[1,"list",2,"name"].string
188
+```
189
+
190
+```swift
191
+// With a hard way
192
+let name = json[].string
193
+```
194
+
195
+```swift
196
+// With a custom way
197
+let keys:[JSONSubscriptType] = [1,"list",2,"name"]
198
+let name = json[keys].string
199
+```
200
+
201
+#### Loop
202
+
203
+```swift
204
+// If json is .Dictionary
205
+for (key,subJson):(String, JSON) in json {
206
+   // Do something you want
207
+}
208
+```
209
+
210
+*The first element is always a String, even if the JSON is an Array*
211
+
212
+```swift
213
+// If json is .Array
214
+// The `index` is 0..<json.count's string value
215
+for (index,subJson):(String, JSON) in json {
216
+    // Do something you want
217
+}
218
+```
219
+
220
+#### Error
221
+
222
+##### SwiftyJSON 4.x
223
+
224
+SwiftyJSON 4.x introduces an enum type called `SwiftyJSONError`, which includes `unsupportedType`, `indexOutOfBounds`, `elementTooDeep`, `wrongType`, `notExist` and `invalidJSON`, at the same time, `ErrorDomain` are being replaced by `SwiftyJSONError.errorDomain`.
225
+Note: Those old error types are deprecated in SwiftyJSON 4.x and will be removed in the future release.
226
+
227
+##### SwiftyJSON 3.x
228
+
229
+Use a subscript to get/set a value in an Array or Dictionary
230
+
231
+If the JSON is:
232
+*  an array, the app may crash with "index out-of-bounds."
233
+*  a dictionary, it will be assigned to `nil` without a reason.
234
+*  not an array or a dictionary, the app may crash with an "unrecognised selector" exception.
235
+
236
+This will never happen in SwiftyJSON.
237
+
238
+```swift
239
+let json = JSON(["name", "age"])
240
+if let name = json[999].string {
241
+    // Do something you want
242
+} else {
243
+    print(json[999].error!) // "Array[999] is out of bounds"
244
+}
245
+```
246
+
247
+```swift
248
+let json = JSON(["name":"Jack", "age": 25])
249
+if let name = json["address"].string {
250
+    // Do something you want
251
+} else {
252
+    print(json["address"].error!) // "Dictionary["address"] does not exist"
253
+}
254
+```
255
+
256
+```swift
257
+let json = JSON(12345)
258
+if let age = json[0].string {
259
+    // Do something you want
260
+} else {
261
+    print(json[0])       // "Array[0] failure, It is not an array"
262
+    print(json[0].error!) // "Array[0] failure, It is not an array"
263
+}
264
+
265
+if let name = json["name"].string {
266
+    // Do something you want
267
+} else {
268
+    print(json["name"])       // "Dictionary[\"name"] failure, It is not an dictionary"
269
+    print(json["name"].error!) // "Dictionary[\"name"] failure, It is not an dictionary"
270
+}
271
+```
272
+
273
+#### Optional getter
274
+
275
+```swift
276
+// NSNumber
277
+if let id = json["user"]["favourites_count"].number {
278
+   // Do something you want
279
+} else {
280
+   // Print the error
281
+   print(json["user"]["favourites_count"].error!)
282
+}
283
+```
284
+
285
+```swift
286
+// String
287
+if let id = json["user"]["name"].string {
288
+   // Do something you want
289
+} else {
290
+   // Print the error
291
+   print(json["user"]["name"].error!)
292
+}
293
+```
294
+
295
+```swift
296
+// Bool
297
+if let id = json["user"]["is_translator"].bool {
298
+   // Do something you want
299
+} else {
300
+   // Print the error
301
+   print(json["user"]["is_translator"].error!)
302
+}
303
+```
304
+
305
+```swift
306
+// Int
307
+if let id = json["user"]["id"].int {
308
+   // Do something you want
309
+} else {
310
+   // Print the error
311
+   print(json["user"]["id"].error!)
312
+}
313
+...
314
+```
315
+
316
+#### Non-optional getter
317
+
318
+Non-optional getter is named `xxxValue`
319
+
320
+```swift
321
+// If not a Number or nil, return 0
322
+let id: Int = json["id"].intValue
323
+```
324
+
325
+```swift
326
+// If not a String or nil, return ""
327
+let name: String = json["name"].stringValue
328
+```
329
+
330
+```swift
331
+// If not an Array or nil, return []
332
+let list: Array<JSON> = json["list"].arrayValue
333
+```
334
+
335
+```swift
336
+// If not a Dictionary or nil, return [:]
337
+let user: Dictionary<String, JSON> = json["user"].dictionaryValue
338
+```
339
+
340
+#### Setter
341
+
342
+```swift
343
+json["name"] = JSON("new-name")
344
+json[0] = JSON(1)
345
+```
346
+
347
+```swift
348
+json["id"].int =  1234567890
349
+json["coordinate"].double =  8766.766
350
+json["name"].string =  "Jack"
351
+json.arrayObject = [1,2,3,4]
352
+json.dictionaryObject = ["name":"Jack", "age":25]
353
+```
354
+
355
+#### Raw object
356
+
357
+```swift
358
+let rawObject: Any = json.object
359
+```
360
+
361
+```swift
362
+let rawValue: Any = json.rawValue
363
+```
364
+
365
+```swift
366
+//convert the JSON to raw NSData
367
+do {
368
+	let rawData = try json.rawData()
369
+  //Do something you want
370
+} catch {
371
+	print("Error \(error)")
372
+}
373
+```
374
+
375
+```swift
376
+//convert the JSON to a raw String
377
+if let rawString = json.rawString() {
378
+  //Do something you want
379
+} else {
380
+	print("json.rawString is nil")
381
+}
382
+```
383
+
384
+#### Existence
385
+
386
+```swift
387
+// shows you whether value specified in JSON or not
388
+if json["name"].exists()
389
+```
390
+
391
+#### Literal convertibles
392
+
393
+For more info about literal convertibles: [Swift Literal Convertibles](http://nshipster.com/swift-literal-convertible/)
394
+
395
+```swift
396
+// StringLiteralConvertible
397
+let json: JSON = "I'm a json"
398
+```
399
+
400
+```swift
401
+/ /IntegerLiteralConvertible
402
+let json: JSON =  12345
403
+```
404
+
405
+```swift
406
+// BooleanLiteralConvertible
407
+let json: JSON =  true
408
+```
409
+
410
+```swift
411
+// FloatLiteralConvertible
412
+let json: JSON =  2.8765
413
+```
414
+
415
+```swift
416
+// DictionaryLiteralConvertible
417
+let json: JSON =  ["I":"am", "a":"json"]
418
+```
419
+
420
+```swift
421
+// ArrayLiteralConvertible
422
+let json: JSON =  ["I", "am", "a", "json"]
423
+```
424
+
425
+```swift
426
+// With subscript in array
427
+var json: JSON =  [1,2,3]
428
+json[0] = 100
429
+json[1] = 200
430
+json[2] = 300
431
+json[999] = 300 // Don't worry, nothing will happen
432
+```
433
+
434
+```swift
435
+// With subscript in dictionary
436
+var json: JSON =  ["name": "Jack", "age": 25]
437
+json["name"] = "Mike"
438
+json["age"] = "25" // It's OK to set String
439
+json["address"] = "L.A." // Add the "address": "L.A." in json
440
+```
441
+
442
+```swift
443
+// Array & Dictionary
444
+var json: JSON =  ["name": "Jack", "age": 25, "list": ["a", "b", "c", ["what": "this"]]]
445
+json["list"][3]["what"] = "that"
446
+json["list",3,"what"] = "that"
447
+let path: [JSONSubscriptType] = ["list",3,"what"]
448
+json[path] = "that"
449
+```
450
+
451
+```swift
452
+// With other JSON objects
453
+let user: JSON = ["username" : "Steve", "password": "supersecurepassword"]
454
+let auth: JSON = [
455
+  "user": user.object, // use user.object instead of just user
456
+  "apikey": "supersecretapitoken"
457
+]
458
+```
459
+
460
+#### Merging
461
+
462
+It is possible to merge one JSON into another JSON. Merging a JSON into another JSON adds all non existing values to the original JSON which are only present in the `other` JSON.
463
+
464
+If both JSONs contain a value for the same key, _mostly_ this value gets overwritten in the original JSON, but there are two cases where it provides some special treatment:
465
+
466
+- In case of both values being a `JSON.Type.array` the values form the array found in the `other` JSON getting appended to the original JSON's array value.
467
+- In case of both values being a `JSON.Type.dictionary` both JSON-values are getting merged the same way the encapsulating JSON is merged.
468
+
469
+In case, where two fields in a JSON have a different types, the value will get always overwritten.
470
+
471
+There are two different fashions for merging: `merge` modifies the original JSON, whereas `merged` works non-destructively on a copy.
472
+
473
+```swift
474
+let original: JSON = [
475
+    "first_name": "John",
476
+    "age": 20,
477
+    "skills": ["Coding", "Reading"],
478
+    "address": [
479
+        "street": "Front St",
480
+        "zip": "12345",
481
+    ]
482
+]
483
+
484
+let update: JSON = [
485
+    "last_name": "Doe",
486
+    "age": 21,
487
+    "skills": ["Writing"],
488
+    "address": [
489
+        "zip": "12342",
490
+        "city": "New York City"
491
+    ]
492
+]
493
+
494
+let updated = original.merge(with: update)
495
+// [
496
+//     "first_name": "John",
497
+//     "last_name": "Doe",
498
+//     "age": 21,
499
+//     "skills": ["Coding", "Reading", "Writing"],
500
+//     "address": [
501
+//         "street": "Front St",
502
+//         "zip": "12342",
503
+//         "city": "New York City"
504
+//     ]
505
+// ]
506
+```
507
+
508
+## String representation
509
+There are two options available:
510
+- use the default Swift one
511
+- use a custom one that will handle optionals well and represent `nil` as `"null"`:
512
+```swift
513
+let dict = ["1":2, "2":"two", "3": nil] as [String: Any?]
514
+let json = JSON(dict)
515
+let representation = json.rawString(options: [.castNilToNSNull: true])
516
+// representation is "{\"1\":2,\"2\":\"two\",\"3\":null}", which represents {"1":2,"2":"two","3":null}
517
+```
518
+
519
+## Work with [Alamofire](https://github.com/Alamofire/Alamofire)
520
+
521
+SwiftyJSON nicely wraps the result of the Alamofire JSON response handler:
522
+
523
+```swift
524
+Alamofire.request(url, method: .get).validate().responseJSON { response in
525
+    switch response.result {
526
+    case .success(let value):
527
+        let json = JSON(value)
528
+        print("JSON: \(json)")
529
+    case .failure(let error):
530
+        print(error)
531
+    }
532
+}
533
+```
534
+
535
+We also provide an extension of Alamofire for serializing NSData to SwiftyJSON's JSON.
536
+
537
+See: [Alamofire-SwiftyJSON](https://github.com/SwiftyJSON/Alamofire-SwiftyJSON)
538
+
539
+
540
+## Work with [Moya](https://github.com/Moya/Moya)
541
+
542
+SwiftyJSON parse data to JSON:
543
+
544
+```swift
545
+let provider = MoyaProvider<Backend>()
546
+provider.request(.showProducts) { result in
547
+    switch result {
548
+    case let .success(moyaResponse):
549
+        let data = moyaResponse.data
550
+        let json = JSON(data: data) // convert network data to json
551
+        print(json)
552
+    case let .failure(error):
553
+        print("error: \(error)")
554
+    }
555
+}
556
+
557
+```
558
+
559
+## SwiftyJSON Model Generator
560
+Tools to generate SwiftyJSON Models
561
+* [JSON Cafe](http://www.jsoncafe.com/)
562
+* [JSON Export](https://github.com/Ahmed-Ali/JSONExport)

+ 1401
- 0
trolley/Pods/SwiftyJSON/Source/SwiftyJSON/SwiftyJSON.swift
文件差异内容过多而无法显示
查看文件


+ 26
- 0
trolley/Pods/Target Support Files/Alamofire/Alamofire-Info.plist 查看文件

@@ -0,0 +1,26 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+<plist version="1.0">
4
+<dict>
5
+  <key>CFBundleDevelopmentRegion</key>
6
+  <string>en</string>
7
+  <key>CFBundleExecutable</key>
8
+  <string>${EXECUTABLE_NAME}</string>
9
+  <key>CFBundleIdentifier</key>
10
+  <string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
11
+  <key>CFBundleInfoDictionaryVersion</key>
12
+  <string>6.0</string>
13
+  <key>CFBundleName</key>
14
+  <string>${PRODUCT_NAME}</string>
15
+  <key>CFBundlePackageType</key>
16
+  <string>FMWK</string>
17
+  <key>CFBundleShortVersionString</key>
18
+  <string>5.0.0</string>
19
+  <key>CFBundleSignature</key>
20
+  <string>????</string>
21
+  <key>CFBundleVersion</key>
22
+  <string>${CURRENT_PROJECT_VERSION}</string>
23
+  <key>NSPrincipalClass</key>
24
+  <string></string>
25
+</dict>
26
+</plist>

+ 5
- 0
trolley/Pods/Target Support Files/Alamofire/Alamofire-dummy.m 查看文件

@@ -0,0 +1,5 @@
1
+#import <Foundation/Foundation.h>
2
+@interface PodsDummy_Alamofire : NSObject
3
+@end
4
+@implementation PodsDummy_Alamofire
5
+@end

+ 12
- 0
trolley/Pods/Target Support Files/Alamofire/Alamofire-prefix.pch 查看文件

@@ -0,0 +1,12 @@
1
+#ifdef __OBJC__
2
+#import <UIKit/UIKit.h>
3
+#else
4
+#ifndef FOUNDATION_EXPORT
5
+#if defined(__cplusplus)
6
+#define FOUNDATION_EXPORT extern "C"
7
+#else
8
+#define FOUNDATION_EXPORT extern
9
+#endif
10
+#endif
11
+#endif
12
+

+ 16
- 0
trolley/Pods/Target Support Files/Alamofire/Alamofire-umbrella.h 查看文件

@@ -0,0 +1,16 @@
1
+#ifdef __OBJC__
2
+#import <UIKit/UIKit.h>
3
+#else
4
+#ifndef FOUNDATION_EXPORT
5
+#if defined(__cplusplus)
6
+#define FOUNDATION_EXPORT extern "C"
7
+#else
8
+#define FOUNDATION_EXPORT extern
9
+#endif
10
+#endif
11
+#endif
12
+
13
+
14
+FOUNDATION_EXPORT double AlamofireVersionNumber;
15
+FOUNDATION_EXPORT const unsigned char AlamofireVersionString[];
16
+

+ 6
- 0
trolley/Pods/Target Support Files/Alamofire/Alamofire.modulemap 查看文件

@@ -0,0 +1,6 @@
1
+framework module Alamofire {
2
+  umbrella header "Alamofire-umbrella.h"
3
+
4
+  export *
5
+  module * { export * }
6
+}

+ 11
- 0
trolley/Pods/Target Support Files/Alamofire/Alamofire.xcconfig 查看文件

@@ -0,0 +1,11 @@
1
+CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Alamofire
2
+GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
3
+OTHER_LDFLAGS = $(inherited) -framework "CFNetwork"
4
+OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
5
+PODS_BUILD_DIR = ${BUILD_DIR}
6
+PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
7
+PODS_ROOT = ${SRCROOT}
8
+PODS_TARGET_SRCROOT = ${PODS_ROOT}/Alamofire
9
+PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
10
+SKIP_INSTALL = YES
11
+USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

+ 26
- 0
trolley/Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App-Info.plist 查看文件

@@ -0,0 +1,26 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+<plist version="1.0">
4
+<dict>
5
+  <key>CFBundleDevelopmentRegion</key>
6
+  <string>en</string>
7
+  <key>CFBundleExecutable</key>
8
+  <string>${EXECUTABLE_NAME}</string>
9
+  <key>CFBundleIdentifier</key>
10
+  <string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
11
+  <key>CFBundleInfoDictionaryVersion</key>
12
+  <string>6.0</string>
13
+  <key>CFBundleName</key>
14
+  <string>${PRODUCT_NAME}</string>
15
+  <key>CFBundlePackageType</key>
16
+  <string>FMWK</string>
17
+  <key>CFBundleShortVersionString</key>
18
+  <string>1.0.0</string>
19
+  <key>CFBundleSignature</key>
20
+  <string>????</string>
21
+  <key>CFBundleVersion</key>
22
+  <string>${CURRENT_PROJECT_VERSION}</string>
23
+  <key>NSPrincipalClass</key>
24
+  <string></string>
25
+</dict>
26
+</plist>

+ 51
- 0
trolley/Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App-acknowledgements.markdown 查看文件

@@ -0,0 +1,51 @@
1
+# Acknowledgements
2
+This application makes use of the following third party libraries:
3
+
4
+## Alamofire
5
+
6
+Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
7
+
8
+Permission is hereby granted, free of charge, to any person obtaining a copy
9
+of this software and associated documentation files (the "Software"), to deal
10
+in the Software without restriction, including without limitation the rights
11
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+copies of the Software, and to permit persons to whom the Software is
13
+furnished to do so, subject to the following conditions:
14
+
15
+The above copyright notice and this permission notice shall be included in
16
+all copies or substantial portions of the Software.
17
+
18
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+THE SOFTWARE.
25
+
26
+
27
+## SwiftyJSON
28
+
29
+The MIT License (MIT)
30
+
31
+Copyright (c) 2017 Ruoyu Fu
32
+
33
+Permission is hereby granted, free of charge, to any person obtaining a copy
34
+of this software and associated documentation files (the "Software"), to deal
35
+in the Software without restriction, including without limitation the rights
36
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
37
+copies of the Software, and to permit persons to whom the Software is
38
+furnished to do so, subject to the following conditions:
39
+
40
+The above copyright notice and this permission notice shall be included in
41
+all copies or substantial portions of the Software.
42
+
43
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
44
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
45
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
46
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
47
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
48
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
49
+THE SOFTWARE.
50
+
51
+Generated by CocoaPods - https://cocoapods.org

+ 89
- 0
trolley/Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App-acknowledgements.plist 查看文件

@@ -0,0 +1,89 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+<plist version="1.0">
4
+<dict>
5
+	<key>PreferenceSpecifiers</key>
6
+	<array>
7
+		<dict>
8
+			<key>FooterText</key>
9
+			<string>This application makes use of the following third party libraries:</string>
10
+			<key>Title</key>
11
+			<string>Acknowledgements</string>
12
+			<key>Type</key>
13
+			<string>PSGroupSpecifier</string>
14
+		</dict>
15
+		<dict>
16
+			<key>FooterText</key>
17
+			<string>Copyright (c) 2014-2018 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
+</string>
37
+			<key>License</key>
38
+			<string>MIT</string>
39
+			<key>Title</key>
40
+			<string>Alamofire</string>
41
+			<key>Type</key>
42
+			<string>PSGroupSpecifier</string>
43
+		</dict>
44
+		<dict>
45
+			<key>FooterText</key>
46
+			<string>The MIT License (MIT)
47
+
48
+Copyright (c) 2017 Ruoyu Fu
49
+
50
+Permission is hereby granted, free of charge, to any person obtaining a copy
51
+of this software and associated documentation files (the "Software"), to deal
52
+in the Software without restriction, including without limitation the rights
53
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
54
+copies of the Software, and to permit persons to whom the Software is
55
+furnished to do so, subject to the following conditions:
56
+
57
+The above copyright notice and this permission notice shall be included in
58
+all copies or substantial portions of the Software.
59
+
60
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
61
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
62
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
63
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
64
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
65
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
66
+THE SOFTWARE.
67
+</string>
68
+			<key>License</key>
69
+			<string>MIT</string>
70
+			<key>Title</key>
71
+			<string>SwiftyJSON</string>
72
+			<key>Type</key>
73
+			<string>PSGroupSpecifier</string>
74
+		</dict>
75
+		<dict>
76
+			<key>FooterText</key>
77
+			<string>Generated by CocoaPods - https://cocoapods.org</string>
78
+			<key>Title</key>
79
+			<string></string>
80
+			<key>Type</key>
81
+			<string>PSGroupSpecifier</string>
82
+		</dict>
83
+	</array>
84
+	<key>StringsTable</key>
85
+	<string>Acknowledgements</string>
86
+	<key>Title</key>
87
+	<string>Acknowledgements</string>
88
+</dict>
89
+</plist>

+ 5
- 0
trolley/Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App-dummy.m 查看文件

@@ -0,0 +1,5 @@
1
+#import <Foundation/Foundation.h>
2
+@interface PodsDummy_Pods_Trolley_App : NSObject
3
+@end
4
+@implementation PodsDummy_Pods_Trolley_App
5
+@end

+ 3
- 0
trolley/Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App-frameworks-Debug-input-files.xcfilelist 查看文件

@@ -0,0 +1,3 @@
1
+${PODS_ROOT}/Target Support Files/Pods-Trolley App/Pods-Trolley App-frameworks.sh
2
+${BUILT_PRODUCTS_DIR}/Alamofire/Alamofire.framework
3
+${BUILT_PRODUCTS_DIR}/SwiftyJSON/SwiftyJSON.framework

+ 2
- 0
trolley/Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App-frameworks-Debug-output-files.xcfilelist 查看文件

@@ -0,0 +1,2 @@
1
+${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Alamofire.framework
2
+${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftyJSON.framework

+ 3
- 0
trolley/Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App-frameworks-Release-input-files.xcfilelist 查看文件

@@ -0,0 +1,3 @@
1
+${PODS_ROOT}/Target Support Files/Pods-Trolley App/Pods-Trolley App-frameworks.sh
2
+${BUILT_PRODUCTS_DIR}/Alamofire/Alamofire.framework
3
+${BUILT_PRODUCTS_DIR}/SwiftyJSON/SwiftyJSON.framework

+ 2
- 0
trolley/Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App-frameworks-Release-output-files.xcfilelist 查看文件

@@ -0,0 +1,2 @@
1
+${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Alamofire.framework
2
+${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftyJSON.framework

+ 173
- 0
trolley/Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App-frameworks.sh 查看文件

@@ -0,0 +1,173 @@
1
+#!/bin/sh
2
+set -e
3
+set -u
4
+set -o pipefail
5
+
6
+function on_error {
7
+  echo "$(realpath -mq "${0}"):$1: error: Unexpected failure"
8
+}
9
+trap 'on_error $LINENO' ERR
10
+
11
+if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then
12
+  # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy
13
+  # frameworks to, so exit 0 (signalling the script phase was successful).
14
+  exit 0
15
+fi
16
+
17
+echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
18
+mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
19
+
20
+COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}"
21
+SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}"
22
+
23
+# Used as a return value for each invocation of `strip_invalid_archs` function.
24
+STRIP_BINARY_RETVAL=0
25
+
26
+# This protects against multiple targets copying the same framework dependency at the same time. The solution
27
+# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html
28
+RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????")
29
+
30
+# Copies and strips a vendored framework
31
+install_framework()
32
+{
33
+  if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then
34
+    local source="${BUILT_PRODUCTS_DIR}/$1"
35
+  elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then
36
+    local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")"
37
+  elif [ -r "$1" ]; then
38
+    local source="$1"
39
+  fi
40
+
41
+  local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
42
+
43
+  if [ -L "${source}" ]; then
44
+    echo "Symlinked..."
45
+    source="$(readlink "${source}")"
46
+  fi
47
+
48
+  # Use filter instead of exclude so missing patterns don't throw errors.
49
+  echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\""
50
+  rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}"
51
+
52
+  local basename
53
+  basename="$(basename -s .framework "$1")"
54
+  binary="${destination}/${basename}.framework/${basename}"
55
+
56
+  if ! [ -r "$binary" ]; then
57
+    binary="${destination}/${basename}"
58
+  elif [ -L "${binary}" ]; then
59
+    echo "Destination binary is symlinked..."
60
+    dirname="$(dirname "${binary}")"
61
+    binary="${dirname}/$(readlink "${binary}")"
62
+  fi
63
+
64
+  # Strip invalid architectures so "fat" simulator / device frameworks work on device
65
+  if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then
66
+    strip_invalid_archs "$binary"
67
+  fi
68
+
69
+  # Resign the code if required by the build settings to avoid unstable apps
70
+  code_sign_if_enabled "${destination}/$(basename "$1")"
71
+
72
+  # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7.
73
+  if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then
74
+    local swift_runtime_libs
75
+    swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u)
76
+    for lib in $swift_runtime_libs; do
77
+      echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\""
78
+      rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}"
79
+      code_sign_if_enabled "${destination}/${lib}"
80
+    done
81
+  fi
82
+}
83
+
84
+# Copies and strips a vendored dSYM
85
+install_dsym() {
86
+  local source="$1"
87
+  if [ -r "$source" ]; then
88
+    # Copy the dSYM into a the targets temp dir.
89
+    echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\""
90
+    rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}"
91
+
92
+    local basename
93
+    basename="$(basename -s .framework.dSYM "$source")"
94
+    binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}"
95
+
96
+    # Strip invalid architectures so "fat" simulator / device frameworks work on device
97
+    if [[ "$(file "$binary")" == *"Mach-O "*"dSYM companion"* ]]; then
98
+      strip_invalid_archs "$binary"
99
+    fi
100
+
101
+    if [[ $STRIP_BINARY_RETVAL == 1 ]]; then
102
+      # Move the stripped file into its final destination.
103
+      echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\""
104
+      rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.framework.dSYM" "${DWARF_DSYM_FOLDER_PATH}"
105
+    else
106
+      # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing.
107
+      touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.framework.dSYM"
108
+    fi
109
+  fi
110
+}
111
+
112
+# Copies the bcsymbolmap files of a vendored framework
113
+install_bcsymbolmap() {
114
+    local bcsymbolmap_path="$1"
115
+    local destination="${BUILT_PRODUCTS_DIR}"
116
+    echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}""
117
+    rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}"
118
+}
119
+
120
+# Signs a framework with the provided identity
121
+code_sign_if_enabled() {
122
+  if [ -n "${EXPANDED_CODE_SIGN_IDENTITY:-}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then
123
+    # Use the current code_sign_identity
124
+    echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}"
125
+    local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'"
126
+
127
+    if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then
128
+      code_sign_cmd="$code_sign_cmd &"
129
+    fi
130
+    echo "$code_sign_cmd"
131
+    eval "$code_sign_cmd"
132
+  fi
133
+}
134
+
135
+# Strip invalid architectures
136
+strip_invalid_archs() {
137
+  binary="$1"
138
+  # Get architectures for current target binary
139
+  binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)"
140
+  # Intersect them with the architectures we are building for
141
+  intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)"
142
+  # If there are no archs supported by this binary then warn the user
143
+  if [[ -z "$intersected_archs" ]]; then
144
+    echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)."
145
+    STRIP_BINARY_RETVAL=0
146
+    return
147
+  fi
148
+  stripped=""
149
+  for arch in $binary_archs; do
150
+    if ! [[ "${ARCHS}" == *"$arch"* ]]; then
151
+      # Strip non-valid architectures in-place
152
+      lipo -remove "$arch" -output "$binary" "$binary"
153
+      stripped="$stripped $arch"
154
+    fi
155
+  done
156
+  if [[ "$stripped" ]]; then
157
+    echo "Stripped $binary of architectures:$stripped"
158
+  fi
159
+  STRIP_BINARY_RETVAL=1
160
+}
161
+
162
+
163
+if [[ "$CONFIGURATION" == "Debug" ]]; then
164
+  install_framework "${BUILT_PRODUCTS_DIR}/Alamofire/Alamofire.framework"
165
+  install_framework "${BUILT_PRODUCTS_DIR}/SwiftyJSON/SwiftyJSON.framework"
166
+fi
167
+if [[ "$CONFIGURATION" == "Release" ]]; then
168
+  install_framework "${BUILT_PRODUCTS_DIR}/Alamofire/Alamofire.framework"
169
+  install_framework "${BUILT_PRODUCTS_DIR}/SwiftyJSON/SwiftyJSON.framework"
170
+fi
171
+if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then
172
+  wait
173
+fi

+ 16
- 0
trolley/Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App-umbrella.h 查看文件

@@ -0,0 +1,16 @@
1
+#ifdef __OBJC__
2
+#import <UIKit/UIKit.h>
3
+#else
4
+#ifndef FOUNDATION_EXPORT
5
+#if defined(__cplusplus)
6
+#define FOUNDATION_EXPORT extern "C"
7
+#else
8
+#define FOUNDATION_EXPORT extern
9
+#endif
10
+#endif
11
+#endif
12
+
13
+
14
+FOUNDATION_EXPORT double Pods_Trolley_AppVersionNumber;
15
+FOUNDATION_EXPORT const unsigned char Pods_Trolley_AppVersionString[];
16
+

+ 12
- 0
trolley/Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App.debug.xcconfig 查看文件

@@ -0,0 +1,12 @@
1
+ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
2
+FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyJSON"
3
+GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
4
+HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyJSON/SwiftyJSON.framework/Headers"
5
+LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
6
+OTHER_LDFLAGS = $(inherited) -framework "Alamofire" -framework "CFNetwork" -framework "SwiftyJSON"
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_PODFILE_DIR_PATH = ${SRCROOT}/.
11
+PODS_ROOT = ${SRCROOT}/Pods
12
+USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

+ 6
- 0
trolley/Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App.modulemap 查看文件

@@ -0,0 +1,6 @@
1
+framework module Pods_Trolley_App {
2
+  umbrella header "Pods-Trolley App-umbrella.h"
3
+
4
+  export *
5
+  module * { export * }
6
+}

+ 12
- 0
trolley/Pods/Target Support Files/Pods-Trolley App/Pods-Trolley App.release.xcconfig 查看文件

@@ -0,0 +1,12 @@
1
+ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
2
+FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyJSON"
3
+GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
4
+HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyJSON/SwiftyJSON.framework/Headers"
5
+LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
6
+OTHER_LDFLAGS = $(inherited) -framework "Alamofire" -framework "CFNetwork" -framework "SwiftyJSON"
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_PODFILE_DIR_PATH = ${SRCROOT}/.
11
+PODS_ROOT = ${SRCROOT}/Pods
12
+USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

+ 26
- 0
trolley/Pods/Target Support Files/SwiftyJSON/SwiftyJSON-Info.plist 查看文件

@@ -0,0 +1,26 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+<plist version="1.0">
4
+<dict>
5
+  <key>CFBundleDevelopmentRegion</key>
6
+  <string>en</string>
7
+  <key>CFBundleExecutable</key>
8
+  <string>${EXECUTABLE_NAME}</string>
9
+  <key>CFBundleIdentifier</key>
10
+  <string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
11
+  <key>CFBundleInfoDictionaryVersion</key>
12
+  <string>6.0</string>
13
+  <key>CFBundleName</key>
14
+  <string>${PRODUCT_NAME}</string>
15
+  <key>CFBundlePackageType</key>
16
+  <string>FMWK</string>
17
+  <key>CFBundleShortVersionString</key>
18
+  <string>4.3.0</string>
19
+  <key>CFBundleSignature</key>
20
+  <string>????</string>
21
+  <key>CFBundleVersion</key>
22
+  <string>${CURRENT_PROJECT_VERSION}</string>
23
+  <key>NSPrincipalClass</key>
24
+  <string></string>
25
+</dict>
26
+</plist>

+ 5
- 0
trolley/Pods/Target Support Files/SwiftyJSON/SwiftyJSON-dummy.m 查看文件

@@ -0,0 +1,5 @@
1
+#import <Foundation/Foundation.h>
2
+@interface PodsDummy_SwiftyJSON : NSObject
3
+@end
4
+@implementation PodsDummy_SwiftyJSON
5
+@end

+ 12
- 0
trolley/Pods/Target Support Files/SwiftyJSON/SwiftyJSON-prefix.pch 查看文件

@@ -0,0 +1,12 @@
1
+#ifdef __OBJC__
2
+#import <UIKit/UIKit.h>
3
+#else
4
+#ifndef FOUNDATION_EXPORT
5
+#if defined(__cplusplus)
6
+#define FOUNDATION_EXPORT extern "C"
7
+#else
8
+#define FOUNDATION_EXPORT extern
9
+#endif
10
+#endif
11
+#endif
12
+

+ 16
- 0
trolley/Pods/Target Support Files/SwiftyJSON/SwiftyJSON-umbrella.h 查看文件

@@ -0,0 +1,16 @@
1
+#ifdef __OBJC__
2
+#import <UIKit/UIKit.h>
3
+#else
4
+#ifndef FOUNDATION_EXPORT
5
+#if defined(__cplusplus)
6
+#define FOUNDATION_EXPORT extern "C"
7
+#else
8
+#define FOUNDATION_EXPORT extern
9
+#endif
10
+#endif
11
+#endif
12
+
13
+
14
+FOUNDATION_EXPORT double SwiftyJSONVersionNumber;
15
+FOUNDATION_EXPORT const unsigned char SwiftyJSONVersionString[];
16
+

+ 6
- 0
trolley/Pods/Target Support Files/SwiftyJSON/SwiftyJSON.modulemap 查看文件

@@ -0,0 +1,6 @@
1
+framework module SwiftyJSON {
2
+  umbrella header "SwiftyJSON-umbrella.h"
3
+
4
+  export *
5
+  module * { export * }
6
+}

+ 10
- 0
trolley/Pods/Target Support Files/SwiftyJSON/SwiftyJSON.xcconfig 查看文件

@@ -0,0 +1,10 @@
1
+CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/SwiftyJSON
2
+GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
3
+OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
4
+PODS_BUILD_DIR = ${BUILD_DIR}
5
+PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
6
+PODS_ROOT = ${SRCROOT}
7
+PODS_TARGET_SRCROOT = ${PODS_ROOT}/SwiftyJSON
8
+PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
9
+SKIP_INSTALL = YES
10
+USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

Trolley App.xcodeproj/project.pbxproj → trolley/Trolley App.xcodeproj/project.pbxproj 查看文件

@@ -3,7 +3,7 @@
3 3
 	archiveVersion = 1;
4 4
 	classes = {
5 5
 	};
6
-	objectVersion = 50;
6
+	objectVersion = 51;
7 7
 	objects = {
8 8
 
9 9
 /* Begin PBXBuildFile section */
@@ -13,6 +13,7 @@
13 13
 		5B319F07235DDC06009AD1A9 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5B319F05235DDC06009AD1A9 /* Main.storyboard */; };
14 14
 		5B319F09235DDC07009AD1A9 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5B319F08235DDC07009AD1A9 /* Assets.xcassets */; };
15 15
 		5B319F0C235DDC07009AD1A9 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5B319F0A235DDC07009AD1A9 /* LaunchScreen.storyboard */; };
16
+		E2E000AE10F252F66881171C /* Pods_Trolley_App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 92BC61886F41EF616207DB3F /* Pods_Trolley_App.framework */; };
16 17
 /* End PBXBuildFile section */
17 18
 
18 19
 /* Begin PBXFileReference section */
@@ -24,6 +25,9 @@
24 25
 		5B319F08235DDC07009AD1A9 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
25 26
 		5B319F0B235DDC07009AD1A9 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
26 27
 		5B319F0D235DDC07009AD1A9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
28
+		8F944001F21B0F4BA012D57F /* Pods-Trolley App.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Trolley App.release.xcconfig"; path = "Target Support Files/Pods-Trolley App/Pods-Trolley App.release.xcconfig"; sourceTree = "<group>"; };
29
+		92BC61886F41EF616207DB3F /* Pods_Trolley_App.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Trolley_App.framework; sourceTree = BUILT_PRODUCTS_DIR; };
30
+		F2207BFA1F7ED07354A184F0 /* Pods-Trolley App.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Trolley App.debug.xcconfig"; path = "Target Support Files/Pods-Trolley App/Pods-Trolley App.debug.xcconfig"; sourceTree = "<group>"; };
27 31
 /* End PBXFileReference section */
28 32
 
29 33
 /* Begin PBXFrameworksBuildPhase section */
@@ -31,17 +35,29 @@
31 35
 			isa = PBXFrameworksBuildPhase;
32 36
 			buildActionMask = 2147483647;
33 37
 			files = (
38
+				E2E000AE10F252F66881171C /* Pods_Trolley_App.framework in Frameworks */,
34 39
 			);
35 40
 			runOnlyForDeploymentPostprocessing = 0;
36 41
 		};
37 42
 /* End PBXFrameworksBuildPhase section */
38 43
 
39 44
 /* Begin PBXGroup section */
45
+		011FDEEB1B083FD33C7E3826 /* Pods */ = {
46
+			isa = PBXGroup;
47
+			children = (
48
+				F2207BFA1F7ED07354A184F0 /* Pods-Trolley App.debug.xcconfig */,
49
+				8F944001F21B0F4BA012D57F /* Pods-Trolley App.release.xcconfig */,
50
+			);
51
+			path = Pods;
52
+			sourceTree = "<group>";
53
+		};
40 54
 		5B319EF3235DDC06009AD1A9 = {
41 55
 			isa = PBXGroup;
42 56
 			children = (
43 57
 				5B319EFE235DDC06009AD1A9 /* Trolley App */,
44 58
 				5B319EFD235DDC06009AD1A9 /* Products */,
59
+				011FDEEB1B083FD33C7E3826 /* Pods */,
60
+				859E3FDE1532FF49C1AE4393 /* Frameworks */,
45 61
 			);
46 62
 			sourceTree = "<group>";
47 63
 		};
@@ -67,6 +83,14 @@
67 83
 			path = "Trolley App";
68 84
 			sourceTree = "<group>";
69 85
 		};
86
+		859E3FDE1532FF49C1AE4393 /* Frameworks */ = {
87
+			isa = PBXGroup;
88
+			children = (
89
+				92BC61886F41EF616207DB3F /* Pods_Trolley_App.framework */,
90
+			);
91
+			name = Frameworks;
92
+			sourceTree = "<group>";
93
+		};
70 94
 /* End PBXGroup section */
71 95
 
72 96
 /* Begin PBXNativeTarget section */
@@ -74,9 +98,11 @@
74 98
 			isa = PBXNativeTarget;
75 99
 			buildConfigurationList = 5B319F10235DDC07009AD1A9 /* Build configuration list for PBXNativeTarget "Trolley App" */;
76 100
 			buildPhases = (
101
+				6112C151479F678743A2819B /* [CP] Check Pods Manifest.lock */,
77 102
 				5B319EF8235DDC06009AD1A9 /* Sources */,
78 103
 				5B319EF9235DDC06009AD1A9 /* Frameworks */,
79 104
 				5B319EFA235DDC06009AD1A9 /* Resources */,
105
+				34077CDAC94F7E61986613C8 /* [CP] Embed Pods Frameworks */,
80 106
 			);
81 107
 			buildRules = (
82 108
 			);
@@ -133,6 +159,48 @@
133 159
 		};
134 160
 /* End PBXResourcesBuildPhase section */
135 161
 
162
+/* Begin PBXShellScriptBuildPhase section */
163
+		34077CDAC94F7E61986613C8 /* [CP] Embed Pods Frameworks */ = {
164
+			isa = PBXShellScriptBuildPhase;
165
+			buildActionMask = 2147483647;
166
+			files = (
167
+			);
168
+			inputFileListPaths = (
169
+				"${PODS_ROOT}/Target Support Files/Pods-Trolley App/Pods-Trolley App-frameworks-${CONFIGURATION}-input-files.xcfilelist",
170
+			);
171
+			name = "[CP] Embed Pods Frameworks";
172
+			outputFileListPaths = (
173
+				"${PODS_ROOT}/Target Support Files/Pods-Trolley App/Pods-Trolley App-frameworks-${CONFIGURATION}-output-files.xcfilelist",
174
+			);
175
+			runOnlyForDeploymentPostprocessing = 0;
176
+			shellPath = /bin/sh;
177
+			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Trolley App/Pods-Trolley App-frameworks.sh\"\n";
178
+			showEnvVarsInLog = 0;
179
+		};
180
+		6112C151479F678743A2819B /* [CP] Check Pods Manifest.lock */ = {
181
+			isa = PBXShellScriptBuildPhase;
182
+			buildActionMask = 2147483647;
183
+			files = (
184
+			);
185
+			inputFileListPaths = (
186
+			);
187
+			inputPaths = (
188
+				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
189
+				"${PODS_ROOT}/Manifest.lock",
190
+			);
191
+			name = "[CP] Check Pods Manifest.lock";
192
+			outputFileListPaths = (
193
+			);
194
+			outputPaths = (
195
+				"$(DERIVED_FILE_DIR)/Pods-Trolley App-checkManifestLockResult.txt",
196
+			);
197
+			runOnlyForDeploymentPostprocessing = 0;
198
+			shellPath = /bin/sh;
199
+			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
200
+			showEnvVarsInLog = 0;
201
+		};
202
+/* End PBXShellScriptBuildPhase section */
203
+
136 204
 /* Begin PBXSourcesBuildPhase section */
137 205
 		5B319EF8235DDC06009AD1A9 /* Sources */ = {
138 206
 			isa = PBXSourcesBuildPhase;
@@ -282,16 +350,18 @@
282 350
 		};
283 351
 		5B319F11235DDC07009AD1A9 /* Debug */ = {
284 352
 			isa = XCBuildConfiguration;
353
+			baseConfigurationReference = F2207BFA1F7ED07354A184F0 /* Pods-Trolley App.debug.xcconfig */;
285 354
 			buildSettings = {
286 355
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
287 356
 				CODE_SIGN_STYLE = Automatic;
288
-				DEVELOPMENT_TEAM = H67NFWVH5W;
357
+				DEVELOPMENT_TEAM = JZXSD8676R;
289 358
 				INFOPLIST_FILE = "Trolley App/Info.plist";
359
+				IPHONEOS_DEPLOYMENT_TARGET = 13.1;
290 360
 				LD_RUNPATH_SEARCH_PATHS = (
291 361
 					"$(inherited)",
292 362
 					"@executable_path/Frameworks",
293 363
 				);
294
-				PRODUCT_BUNDLE_IDENTIFIER = "com.uprrp.Trolley-App";
364
+				PRODUCT_BUNDLE_IDENTIFIER = com.uprrp.TrolleyApp;
295 365
 				PRODUCT_NAME = "$(TARGET_NAME)";
296 366
 				SWIFT_VERSION = 5.0;
297 367
 				TARGETED_DEVICE_FAMILY = 1;
@@ -300,16 +370,18 @@
300 370
 		};
301 371
 		5B319F12235DDC07009AD1A9 /* Release */ = {
302 372
 			isa = XCBuildConfiguration;
373
+			baseConfigurationReference = 8F944001F21B0F4BA012D57F /* Pods-Trolley App.release.xcconfig */;
303 374
 			buildSettings = {
304 375
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
305 376
 				CODE_SIGN_STYLE = Automatic;
306
-				DEVELOPMENT_TEAM = H67NFWVH5W;
377
+				DEVELOPMENT_TEAM = JZXSD8676R;
307 378
 				INFOPLIST_FILE = "Trolley App/Info.plist";
379
+				IPHONEOS_DEPLOYMENT_TARGET = 13.1;
308 380
 				LD_RUNPATH_SEARCH_PATHS = (
309 381
 					"$(inherited)",
310 382
 					"@executable_path/Frameworks",
311 383
 				);
312
-				PRODUCT_BUNDLE_IDENTIFIER = "com.uprrp.Trolley-App";
384
+				PRODUCT_BUNDLE_IDENTIFIER = com.uprrp.TrolleyApp;
313 385
 				PRODUCT_NAME = "$(TARGET_NAME)";
314 386
 				SWIFT_VERSION = 5.0;
315 387
 				TARGETED_DEVICE_FAMILY = 1;

Trolley App.xcodeproj/project.xcworkspace/contents.xcworkspacedata → trolley/Trolley App.xcodeproj/project.xcworkspace/contents.xcworkspacedata 查看文件


Trolley App.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist → trolley/Trolley App.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist 查看文件


二进制
trolley/Trolley App.xcodeproj/project.xcworkspace/xcuserdata/kendrickmorales.xcuserdatad/UserInterfaceState.xcuserstate 查看文件


二进制
trolley/Trolley App.xcodeproj/project.xcworkspace/xcuserdata/stephanie.marie.xcuserdatad/UserInterfaceState.xcuserstate 查看文件


二进制
trolley/Trolley App.xcodeproj/project.xcworkspace/xcuserdata/stephaniem.ramos.xcuserdatad/UserInterfaceState.xcuserstate 查看文件


Trolley App.xcodeproj/xcuserdata/kendrickmorales.xcuserdatad/xcschemes/xcschememanagement.plist → trolley/Trolley App.xcodeproj/xcuserdata/kendrickmorales.xcuserdatad/xcschemes/xcschememanagement.plist 查看文件


+ 14
- 0
trolley/Trolley App.xcodeproj/xcuserdata/stephanie.marie.xcuserdatad/xcschemes/xcschememanagement.plist 查看文件

@@ -0,0 +1,14 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+<plist version="1.0">
4
+<dict>
5
+	<key>SchemeUserState</key>
6
+	<dict>
7
+		<key>Trolley App.xcscheme_^#shared#^_</key>
8
+		<dict>
9
+			<key>orderHint</key>
10
+			<integer>3</integer>
11
+		</dict>
12
+	</dict>
13
+</dict>
14
+</plist>

+ 14
- 0
trolley/Trolley App.xcodeproj/xcuserdata/stephaniem.ramos.xcuserdatad/xcschemes/xcschememanagement.plist 查看文件

@@ -0,0 +1,14 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+<plist version="1.0">
4
+<dict>
5
+	<key>SchemeUserState</key>
6
+	<dict>
7
+		<key>Trolley App.xcscheme_^#shared#^_</key>
8
+		<dict>
9
+			<key>orderHint</key>
10
+			<integer>0</integer>
11
+		</dict>
12
+	</dict>
13
+</dict>
14
+</plist>

+ 10
- 0
trolley/Trolley App.xcworkspace/contents.xcworkspacedata 查看文件

@@ -0,0 +1,10 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<Workspace
3
+   version = "1.0">
4
+   <FileRef
5
+      location = "group:Trolley App.xcodeproj">
6
+   </FileRef>
7
+   <FileRef
8
+      location = "group:Pods/Pods.xcodeproj">
9
+   </FileRef>
10
+</Workspace>

+ 8
- 0
trolley/Trolley App.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist 查看文件

@@ -0,0 +1,8 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+<plist version="1.0">
4
+<dict>
5
+	<key>IDEDidComputeMac32BitWarning</key>
6
+	<true/>
7
+</dict>
8
+</plist>

二进制
trolley/Trolley App.xcworkspace/xcuserdata/stephanie.marie.xcuserdatad/UserInterfaceState.xcuserstate 查看文件


二进制
trolley/Trolley App.xcworkspace/xcuserdata/stephaniem.ramos.xcuserdatad/UserInterfaceState.xcuserstate 查看文件


二进制
trolley/Trolley App/.DS_Store 查看文件


Trolley App/AppDelegate.swift → trolley/Trolley App/AppDelegate.swift 查看文件


二进制
trolley/Trolley App/Assets.xcassets/.DS_Store 查看文件


Trolley App/Assets.xcassets/AppIcon.appiconset/Contents.json → trolley/Trolley App/Assets.xcassets/AppIcon.appiconset/Contents.json 查看文件


Trolley App/Assets.xcassets/Contents.json → trolley/Trolley App/Assets.xcassets/Contents.json 查看文件


+ 23
- 0
trolley/Trolley App/Assets.xcassets/biblio_Biblio.imageset/Contents.json 查看文件

@@ -0,0 +1,23 @@
1
+{
2
+  "images" : [
3
+    {
4
+      "idiom" : "universal",
5
+      "filename" : "biblio_Biblio.png",
6
+      "scale" : "1x"
7
+    },
8
+    {
9
+      "idiom" : "universal",
10
+      "filename" : "biblio_Biblio-1.png",
11
+      "scale" : "2x"
12
+    },
13
+    {
14
+      "idiom" : "universal",
15
+      "filename" : "biblio_Biblio-2.png",
16
+      "scale" : "3x"
17
+    }
18
+  ],
19
+  "info" : {
20
+    "version" : 1,
21
+    "author" : "xcode"
22
+  }
23
+}

+ 0
- 0
trolley/Trolley App/Assets.xcassets/biblio_Biblio.imageset/biblio_Biblio-1.png 查看文件


部分文件因为文件数量过多而无法显示