Browse Source

初始项目

zhangjidong 9 years ago
parent
commit
b60af4b7ac
100 changed files with 16883 additions and 0 deletions
  1. 414 0
      BingHaoBang.xcodeproj/project.pbxproj
  2. 7 0
      BingHaoBang.xcodeproj/project.xcworkspace/contents.xcworkspacedata
  3. BIN
      BingHaoBang.xcodeproj/project.xcworkspace/xcuserdata/zhangjidong.xcuserdatad/UserInterfaceState.xcuserstate
  4. 91 0
      BingHaoBang.xcodeproj/xcuserdata/zhangjidong.xcuserdatad/xcschemes/BingHaoBang.xcscheme
  5. 22 0
      BingHaoBang.xcodeproj/xcuserdata/zhangjidong.xcuserdatad/xcschemes/xcschememanagement.plist
  6. 10 0
      BingHaoBang.xcworkspace/contents.xcworkspacedata
  7. BIN
      BingHaoBang.xcworkspace/xcuserdata/zhangjidong.xcuserdatad/UserInterfaceState.xcuserstate
  8. BIN
      BingHaoBang/.DS_Store
  9. 53 0
      BingHaoBang/AppDelegate.swift
  10. BIN
      BingHaoBang/Assets.xcassets/AppIcon.appiconset/AppIcon29x29@2x.png
  11. BIN
      BingHaoBang/Assets.xcassets/AppIcon.appiconset/AppIcon29x29@3x.png
  12. BIN
      BingHaoBang/Assets.xcassets/AppIcon.appiconset/AppIcon40x40@2x.png
  13. BIN
      BingHaoBang/Assets.xcassets/AppIcon.appiconset/AppIcon40x40@3x.png
  14. BIN
      BingHaoBang/Assets.xcassets/AppIcon.appiconset/AppIcon60x60@2x.png
  15. BIN
      BingHaoBang/Assets.xcassets/AppIcon.appiconset/AppIcon60x60@3x.png
  16. 44 0
      BingHaoBang/Assets.xcassets/AppIcon.appiconset/Contents.json
  17. 6 0
      BingHaoBang/Assets.xcassets/Contents.json
  18. 6 0
      BingHaoBang/Assets.xcassets/tabbar/Contents.json
  19. 21 0
      BingHaoBang/Assets.xcassets/tabbar/tabbar_chat.imageset/Contents.json
  20. BIN
      BingHaoBang/Assets.xcassets/tabbar/tabbar_chat.imageset/tabbar_chat@2x.png
  21. 21 0
      BingHaoBang/Assets.xcassets/tabbar/tabbar_chat_selected.imageset/Contents.json
  22. BIN
      BingHaoBang/Assets.xcassets/tabbar/tabbar_chat_selected.imageset/tabbar_chat_selected@2x.png
  23. 21 0
      BingHaoBang/Assets.xcassets/tabbar/tabbar_home.imageset/Contents.json
  24. BIN
      BingHaoBang/Assets.xcassets/tabbar/tabbar_home.imageset/tabbar_home@2x.png
  25. 21 0
      BingHaoBang/Assets.xcassets/tabbar/tabbar_home_selected.imageset/Contents.json
  26. BIN
      BingHaoBang/Assets.xcassets/tabbar/tabbar_home_selected.imageset/tabbar_home_selected@2x.png
  27. 21 0
      BingHaoBang/Assets.xcassets/tabbar/tabbar_me.imageset/Contents.json
  28. BIN
      BingHaoBang/Assets.xcassets/tabbar/tabbar_me.imageset/tabbar_me@2x.png
  29. 21 0
      BingHaoBang/Assets.xcassets/tabbar/tabbar_me_selected.imageset/Contents.json
  30. BIN
      BingHaoBang/Assets.xcassets/tabbar/tabbar_me_selected.imageset/tabbar_me_selected@2x.png
  31. 27 0
      BingHaoBang/Base.lproj/LaunchScreen.storyboard
  32. 40 0
      BingHaoBang/Info.plist
  33. 25 0
      BingHaoBang/ViewController.swift
  34. BIN
      Common/.DS_Store
  35. 19 0
      Common/Config.swift
  36. 10 0
      Podfile
  37. 19 0
      Pods/Alamofire/LICENSE
  38. 1196 0
      Pods/Alamofire/README.md
  39. 368 0
      Pods/Alamofire/Source/Alamofire.swift
  40. 246 0
      Pods/Alamofire/Source/Download.swift
  41. 66 0
      Pods/Alamofire/Source/Error.swift
  42. 695 0
      Pods/Alamofire/Source/Manager.swift
  43. 669 0
      Pods/Alamofire/Source/MultipartFormData.swift
  44. 239 0
      Pods/Alamofire/Source/NetworkReachabilityManager.swift
  45. 45 0
      Pods/Alamofire/Source/Notifications.swift
  46. 259 0
      Pods/Alamofire/Source/ParameterEncoding.swift
  47. 552 0
      Pods/Alamofire/Source/Request.swift
  48. 95 0
      Pods/Alamofire/Source/Response.swift
  49. 366 0
      Pods/Alamofire/Source/ResponseSerialization.swift
  50. 101 0
      Pods/Alamofire/Source/Result.swift
  51. 302 0
      Pods/Alamofire/Source/ServerTrustPolicy.swift
  52. 180 0
      Pods/Alamofire/Source/Stream.swift
  53. 123 0
      Pods/Alamofire/Source/Timeline.swift
  54. 374 0
      Pods/Alamofire/Source/Upload.swift
  55. 189 0
      Pods/Alamofire/Source/Validation.swift
  56. 19 0
      Pods/AlamofireImage/LICENSE
  57. 540 0
      Pods/AlamofireImage/README.md
  58. 31 0
      Pods/AlamofireImage/Source/Image.swift
  59. 330 0
      Pods/AlamofireImage/Source/ImageCache.swift
  60. 530 0
      Pods/AlamofireImage/Source/ImageDownloader.swift
  61. 428 0
      Pods/AlamofireImage/Source/ImageFilter.swift
  62. 235 0
      Pods/AlamofireImage/Source/Request+AlamofireImage.swift
  63. 405 0
      Pods/AlamofireImage/Source/UIButton+AlamofireImage.swift
  64. 325 0
      Pods/AlamofireImage/Source/UIImage+AlamofireImage.swift
  65. 373 0
      Pods/AlamofireImage/Source/UIImageView+AlamofireImage.swift
  66. 172 0
      Pods/AlamofireObjectMapper/AlamofireObjectMapper/AlamofireObjectMapper.swift
  67. 22 0
      Pods/AlamofireObjectMapper/LICENSE
  68. 172 0
      Pods/AlamofireObjectMapper/README.md
  69. 21 0
      Pods/Manifest.lock
  70. 8 0
      Pods/ObjectMapper/LICENSE
  71. 181 0
      Pods/ObjectMapper/ObjectMapper/Core/FromJSON.swift
  72. 161 0
      Pods/ObjectMapper/ObjectMapper/Core/Map.swift
  73. 111 0
      Pods/ObjectMapper/ObjectMapper/Core/Mappable.swift
  74. 442 0
      Pods/ObjectMapper/ObjectMapper/Core/Mapper.swift
  75. 732 0
      Pods/ObjectMapper/ObjectMapper/Core/Operators.swift
  76. 174 0
      Pods/ObjectMapper/ObjectMapper/Core/ToJSON.swift
  77. 40 0
      Pods/ObjectMapper/ObjectMapper/Transforms/CustomDateFormatTransform.swift
  78. 54 0
      Pods/ObjectMapper/ObjectMapper/Transforms/DateFormatterTransform.swift
  79. 55 0
      Pods/ObjectMapper/ObjectMapper/Transforms/DateTransform.swift
  80. 50 0
      Pods/ObjectMapper/ObjectMapper/Transforms/EnumTransform.swift
  81. 41 0
      Pods/ObjectMapper/ObjectMapper/Transforms/ISO8601DateTransform.swift
  82. 48 0
      Pods/ObjectMapper/ObjectMapper/Transforms/TransformOf.swift
  83. 35 0
      Pods/ObjectMapper/ObjectMapper/Transforms/TransformType.swift
  84. 50 0
      Pods/ObjectMapper/ObjectMapper/Transforms/URLTransform.swift
  85. 316 0
      Pods/ObjectMapper/README.md
  86. 3379 0
      Pods/Pods.xcodeproj/project.pbxproj
  87. 60 0
      Pods/Pods.xcodeproj/xcuserdata/zhangjidong.xcuserdatad/xcschemes/Alamofire.xcscheme
  88. 60 0
      Pods/Pods.xcodeproj/xcuserdata/zhangjidong.xcuserdatad/xcschemes/AlamofireImage.xcscheme
  89. 60 0
      Pods/Pods.xcodeproj/xcuserdata/zhangjidong.xcuserdatad/xcschemes/AlamofireObjectMapper.xcscheme
  90. 60 0
      Pods/Pods.xcodeproj/xcuserdata/zhangjidong.xcuserdatad/xcschemes/ObjectMapper.xcscheme
  91. 60 0
      Pods/Pods.xcodeproj/xcuserdata/zhangjidong.xcuserdatad/xcschemes/Pods-BingHaoBang.xcscheme
  92. 62 0
      Pods/Pods.xcodeproj/xcuserdata/zhangjidong.xcuserdatad/xcschemes/xcschememanagement.plist
  93. 5 0
      Pods/Target Support Files/Alamofire/Alamofire-dummy.m
  94. 4 0
      Pods/Target Support Files/Alamofire/Alamofire-prefix.pch
  95. 6 0
      Pods/Target Support Files/Alamofire/Alamofire-umbrella.h
  96. 6 0
      Pods/Target Support Files/Alamofire/Alamofire.modulemap
  97. 5 0
      Pods/Target Support Files/Alamofire/Alamofire.xcconfig
  98. 26 0
      Pods/Target Support Files/Alamofire/Info.plist
  99. 5 0
      Pods/Target Support Files/AlamofireImage/AlamofireImage-dummy.m
  100. 0 0
      Pods/Target Support Files/AlamofireImage/AlamofireImage-prefix.pch

+ 414 - 0
BingHaoBang.xcodeproj/project.pbxproj

@@ -0,0 +1,414 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 46;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		A01B62C21CAC362200477FFE /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A01B62C11CAC362200477FFE /* AppDelegate.swift */; };
+		A01B62C41CAC362200477FFE /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A01B62C31CAC362200477FFE /* ViewController.swift */; };
+		A01B62C91CAC362200477FFE /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A01B62C81CAC362200477FFE /* Assets.xcassets */; };
+		A01B62CC1CAC362200477FFE /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A01B62CA1CAC362200477FFE /* LaunchScreen.storyboard */; };
+		A0EA700F1CAC47C100FEF2E3 /* Config.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0EA700E1CAC47C100FEF2E3 /* Config.swift */; };
+		A0EA70111CAC485C00FEF2E3 /* MyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0EA70101CAC485C00FEF2E3 /* MyViewController.swift */; };
+		A0EA70131CAC488500FEF2E3 /* IndexViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0EA70121CAC488500FEF2E3 /* IndexViewController.swift */; };
+		A0EA70151CAC489600FEF2E3 /* FindViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0EA70141CAC489600FEF2E3 /* FindViewController.swift */; };
+		A0EA70171CAC48BF00FEF2E3 /* MainTabBarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0EA70161CAC48BF00FEF2E3 /* MainTabBarViewController.swift */; };
+		A7A0A617BC974B6F44D7B093 /* Pods_BingHaoBang.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7826C879955B60301A0514A5 /* Pods_BingHaoBang.framework */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+		092C49D19851971B9A4BF69E /* Pods-BingHaoBang.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BingHaoBang.release.xcconfig"; path = "Pods/Target Support Files/Pods-BingHaoBang/Pods-BingHaoBang.release.xcconfig"; sourceTree = "<group>"; };
+		7826C879955B60301A0514A5 /* Pods_BingHaoBang.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_BingHaoBang.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+		9101E85183BB07FD008CA084 /* Pods-BingHaoBang.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BingHaoBang.debug.xcconfig"; path = "Pods/Target Support Files/Pods-BingHaoBang/Pods-BingHaoBang.debug.xcconfig"; sourceTree = "<group>"; };
+		A01B62BE1CAC362200477FFE /* BingHaoBang.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BingHaoBang.app; sourceTree = BUILT_PRODUCTS_DIR; };
+		A01B62C11CAC362200477FFE /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
+		A01B62C31CAC362200477FFE /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
+		A01B62C81CAC362200477FFE /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
+		A01B62CB1CAC362200477FFE /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
+		A01B62CD1CAC362200477FFE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+		A0EA700E1CAC47C100FEF2E3 /* Config.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Config.swift; path = Common/Config.swift; sourceTree = "<group>"; };
+		A0EA70101CAC485C00FEF2E3 /* MyViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MyViewController.swift; path = View/MyViewController.swift; sourceTree = "<group>"; };
+		A0EA70121CAC488500FEF2E3 /* IndexViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = IndexViewController.swift; path = View/IndexViewController.swift; sourceTree = "<group>"; };
+		A0EA70141CAC489600FEF2E3 /* FindViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = FindViewController.swift; path = View/FindViewController.swift; sourceTree = "<group>"; };
+		A0EA70161CAC48BF00FEF2E3 /* MainTabBarViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MainTabBarViewController.swift; path = View/MainTabBarViewController.swift; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		A01B62BB1CAC362200477FFE /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				A7A0A617BC974B6F44D7B093 /* Pods_BingHaoBang.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		A01B62B51CAC362200477FFE = {
+			isa = PBXGroup;
+			children = (
+				A0EA70031CAC3D9800FEF2E3 /* View */,
+				A0EA70021CAC3D8F00FEF2E3 /* Model */,
+				A0EA70011CAC3D6D00FEF2E3 /* Controller */,
+				A0EA70001CAC3D5100FEF2E3 /* Common */,
+				A01B62C01CAC362200477FFE /* BingHaoBang */,
+				A01B62BF1CAC362200477FFE /* Products */,
+				EB01FE650186C765656B9291 /* Pods */,
+				C4ABC6BE6FD3AE3CF23033D4 /* Frameworks */,
+			);
+			sourceTree = "<group>";
+		};
+		A01B62BF1CAC362200477FFE /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				A01B62BE1CAC362200477FFE /* BingHaoBang.app */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		A01B62C01CAC362200477FFE /* BingHaoBang */ = {
+			isa = PBXGroup;
+			children = (
+				A01B62C11CAC362200477FFE /* AppDelegate.swift */,
+				A01B62C31CAC362200477FFE /* ViewController.swift */,
+				A01B62C81CAC362200477FFE /* Assets.xcassets */,
+				A01B62CA1CAC362200477FFE /* LaunchScreen.storyboard */,
+				A01B62CD1CAC362200477FFE /* Info.plist */,
+			);
+			path = BingHaoBang;
+			sourceTree = "<group>";
+		};
+		A0EA70001CAC3D5100FEF2E3 /* Common */ = {
+			isa = PBXGroup;
+			children = (
+				A0EA700E1CAC47C100FEF2E3 /* Config.swift */,
+			);
+			name = Common;
+			sourceTree = "<group>";
+		};
+		A0EA70011CAC3D6D00FEF2E3 /* Controller */ = {
+			isa = PBXGroup;
+			children = (
+			);
+			name = Controller;
+			sourceTree = "<group>";
+		};
+		A0EA70021CAC3D8F00FEF2E3 /* Model */ = {
+			isa = PBXGroup;
+			children = (
+			);
+			name = Model;
+			sourceTree = "<group>";
+		};
+		A0EA70031CAC3D9800FEF2E3 /* View */ = {
+			isa = PBXGroup;
+			children = (
+				A0EA70101CAC485C00FEF2E3 /* MyViewController.swift */,
+				A0EA70121CAC488500FEF2E3 /* IndexViewController.swift */,
+				A0EA70141CAC489600FEF2E3 /* FindViewController.swift */,
+				A0EA70161CAC48BF00FEF2E3 /* MainTabBarViewController.swift */,
+			);
+			name = View;
+			sourceTree = "<group>";
+		};
+		C4ABC6BE6FD3AE3CF23033D4 /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				7826C879955B60301A0514A5 /* Pods_BingHaoBang.framework */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
+		EB01FE650186C765656B9291 /* Pods */ = {
+			isa = PBXGroup;
+			children = (
+				9101E85183BB07FD008CA084 /* Pods-BingHaoBang.debug.xcconfig */,
+				092C49D19851971B9A4BF69E /* Pods-BingHaoBang.release.xcconfig */,
+			);
+			name = Pods;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+		A01B62BD1CAC362200477FFE /* BingHaoBang */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = A01B62D01CAC362200477FFE /* Build configuration list for PBXNativeTarget "BingHaoBang" */;
+			buildPhases = (
+				825F93A492D8A2538D83E985 /* Check Pods Manifest.lock */,
+				A01B62BA1CAC362200477FFE /* Sources */,
+				A01B62BB1CAC362200477FFE /* Frameworks */,
+				A01B62BC1CAC362200477FFE /* Resources */,
+				91474CC53E9C4EF13AEBF2B5 /* Embed Pods Frameworks */,
+				719F641F6C5CF78A7C0A2E29 /* Copy Pods Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = BingHaoBang;
+			productName = BingHaoBang;
+			productReference = A01B62BE1CAC362200477FFE /* BingHaoBang.app */;
+			productType = "com.apple.product-type.application";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		A01B62B61CAC362200477FFE /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastSwiftUpdateCheck = 0730;
+				LastUpgradeCheck = 0730;
+				ORGANIZATIONNAME = Zjdboy;
+				TargetAttributes = {
+					A01B62BD1CAC362200477FFE = {
+						CreatedOnToolsVersion = 7.3;
+						DevelopmentTeam = 6U9V8U75HY;
+					};
+				};
+			};
+			buildConfigurationList = A01B62B91CAC362200477FFE /* Build configuration list for PBXProject "BingHaoBang" */;
+			compatibilityVersion = "Xcode 3.2";
+			developmentRegion = English;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+				Base,
+			);
+			mainGroup = A01B62B51CAC362200477FFE;
+			productRefGroup = A01B62BF1CAC362200477FFE /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				A01B62BD1CAC362200477FFE /* BingHaoBang */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+		A01B62BC1CAC362200477FFE /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				A01B62CC1CAC362200477FFE /* LaunchScreen.storyboard in Resources */,
+				A01B62C91CAC362200477FFE /* Assets.xcassets in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+		719F641F6C5CF78A7C0A2E29 /* Copy Pods Resources */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+			);
+			name = "Copy Pods Resources";
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-BingHaoBang/Pods-BingHaoBang-resources.sh\"\n";
+			showEnvVarsInLog = 0;
+		};
+		825F93A492D8A2538D83E985 /* Check Pods Manifest.lock */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+			);
+			name = "Check Pods Manifest.lock";
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n    cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n    exit 1\nfi\n";
+			showEnvVarsInLog = 0;
+		};
+		91474CC53E9C4EF13AEBF2B5 /* Embed Pods Frameworks */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+			);
+			name = "Embed Pods Frameworks";
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-BingHaoBang/Pods-BingHaoBang-frameworks.sh\"\n";
+			showEnvVarsInLog = 0;
+		};
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		A01B62BA1CAC362200477FFE /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				A01B62C41CAC362200477FFE /* ViewController.swift in Sources */,
+				A01B62C21CAC362200477FFE /* AppDelegate.swift in Sources */,
+				A0EA70111CAC485C00FEF2E3 /* MyViewController.swift in Sources */,
+				A0EA70171CAC48BF00FEF2E3 /* MainTabBarViewController.swift in Sources */,
+				A0EA700F1CAC47C100FEF2E3 /* Config.swift in Sources */,
+				A0EA70131CAC488500FEF2E3 /* IndexViewController.swift in Sources */,
+				A0EA70151CAC489600FEF2E3 /* FindViewController.swift in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+		A01B62CA1CAC362200477FFE /* LaunchScreen.storyboard */ = {
+			isa = PBXVariantGroup;
+			children = (
+				A01B62CB1CAC362200477FFE /* Base */,
+			);
+			name = LaunchScreen.storyboard;
+			sourceTree = "<group>";
+		};
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+		A01B62CE1CAC362200477FFE /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				ENABLE_TESTABILITY = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"DEBUG=1",
+					"$(inherited)",
+				);
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				MTL_ENABLE_DEBUG_INFO = YES;
+				ONLY_ACTIVE_ARCH = YES;
+				SDKROOT = iphoneos;
+				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+			};
+			name = Debug;
+		};
+		A01B62CF1CAC362200477FFE /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				ENABLE_NS_ASSERTIONS = NO;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				MTL_ENABLE_DEBUG_INFO = NO;
+				SDKROOT = iphoneos;
+				VALIDATE_PRODUCT = YES;
+			};
+			name = Release;
+		};
+		A01B62D11CAC362200477FFE /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 9101E85183BB07FD008CA084 /* Pods-BingHaoBang.debug.xcconfig */;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				INFOPLIST_FILE = BingHaoBang/Info.plist;
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+				PRODUCT_BUNDLE_IDENTIFIER = Com.Zjdboy.BingHaoBang;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Debug;
+		};
+		A01B62D21CAC362200477FFE /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 092C49D19851971B9A4BF69E /* Pods-BingHaoBang.release.xcconfig */;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				INFOPLIST_FILE = BingHaoBang/Info.plist;
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+				PRODUCT_BUNDLE_IDENTIFIER = Com.Zjdboy.BingHaoBang;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		A01B62B91CAC362200477FFE /* Build configuration list for PBXProject "BingHaoBang" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				A01B62CE1CAC362200477FFE /* Debug */,
+				A01B62CF1CAC362200477FFE /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		A01B62D01CAC362200477FFE /* Build configuration list for PBXNativeTarget "BingHaoBang" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				A01B62D11CAC362200477FFE /* Debug */,
+				A01B62D21CAC362200477FFE /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = A01B62B61CAC362200477FFE /* Project object */;
+}

+ 7 - 0
BingHaoBang.xcodeproj/project.xcworkspace/contents.xcworkspacedata

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "self:BingHaoBang.xcodeproj">
+   </FileRef>
+</Workspace>

BIN
BingHaoBang.xcodeproj/project.xcworkspace/xcuserdata/zhangjidong.xcuserdatad/UserInterfaceState.xcuserstate


+ 91 - 0
BingHaoBang.xcodeproj/xcuserdata/zhangjidong.xcuserdatad/xcschemes/BingHaoBang.xcscheme

@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0730"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "A01B62BD1CAC362200477FFE"
+               BuildableName = "BingHaoBang.app"
+               BlueprintName = "BingHaoBang"
+               ReferencedContainer = "container:BingHaoBang.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+      <Testables>
+      </Testables>
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "A01B62BD1CAC362200477FFE"
+            BuildableName = "BingHaoBang.app"
+            BlueprintName = "BingHaoBang"
+            ReferencedContainer = "container:BingHaoBang.xcodeproj">
+         </BuildableReference>
+      </MacroExpansion>
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "A01B62BD1CAC362200477FFE"
+            BuildableName = "BingHaoBang.app"
+            BlueprintName = "BingHaoBang"
+            ReferencedContainer = "container:BingHaoBang.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "A01B62BD1CAC362200477FFE"
+            BuildableName = "BingHaoBang.app"
+            BlueprintName = "BingHaoBang"
+            ReferencedContainer = "container:BingHaoBang.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>

+ 22 - 0
BingHaoBang.xcodeproj/xcuserdata/zhangjidong.xcuserdatad/xcschemes/xcschememanagement.plist

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>SchemeUserState</key>
+	<dict>
+		<key>BingHaoBang.xcscheme</key>
+		<dict>
+			<key>orderHint</key>
+			<integer>0</integer>
+		</dict>
+	</dict>
+	<key>SuppressBuildableAutocreation</key>
+	<dict>
+		<key>A01B62BD1CAC362200477FFE</key>
+		<dict>
+			<key>primary</key>
+			<true/>
+		</dict>
+	</dict>
+</dict>
+</plist>

+ 10 - 0
BingHaoBang.xcworkspace/contents.xcworkspacedata

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "group:BingHaoBang.xcodeproj">
+   </FileRef>
+   <FileRef
+      location = "group:Pods/Pods.xcodeproj">
+   </FileRef>
+</Workspace>

BIN
BingHaoBang.xcworkspace/xcuserdata/zhangjidong.xcuserdatad/UserInterfaceState.xcuserstate


BIN
BingHaoBang/.DS_Store


+ 53 - 0
BingHaoBang/AppDelegate.swift

@@ -0,0 +1,53 @@
+//
+//  AppDelegate.swift
+//  BingHaoBang
+//
+//  Created by zhangjidong on 16/3/31.
+//  Copyright © 2016年 Zjdboy. All rights reserved.
+//
+
+import UIKit
+
+@UIApplicationMain
+class AppDelegate: UIResponder, UIApplicationDelegate {
+
+    var window: UIWindow?
+
+
+    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
+        
+        //创建窗口
+        window = UIWindow(frame: SCREEN_BOUNDS)
+        //创建根视图控制器
+        let mainTabBarVC = MainTabBarController()
+        self.window?.rootViewController = mainTabBarVC
+        //显示窗口
+        window?.makeKeyAndVisible()
+        return true
+    }
+
+    func applicationWillResignActive(application: UIApplication) {
+        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
+        // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
+    }
+
+    func applicationDidEnterBackground(application: UIApplication) {
+        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
+        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
+    }
+
+    func applicationWillEnterForeground(application: UIApplication) {
+        // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
+    }
+
+    func applicationDidBecomeActive(application: UIApplication) {
+        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
+    }
+
+    func applicationWillTerminate(application: UIApplication) {
+        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
+    }
+
+
+}
+

BIN
BingHaoBang/Assets.xcassets/AppIcon.appiconset/AppIcon29x29@2x.png


BIN
BingHaoBang/Assets.xcassets/AppIcon.appiconset/AppIcon29x29@3x.png


BIN
BingHaoBang/Assets.xcassets/AppIcon.appiconset/AppIcon40x40@2x.png


BIN
BingHaoBang/Assets.xcassets/AppIcon.appiconset/AppIcon40x40@3x.png


BIN
BingHaoBang/Assets.xcassets/AppIcon.appiconset/AppIcon60x60@2x.png


BIN
BingHaoBang/Assets.xcassets/AppIcon.appiconset/AppIcon60x60@3x.png


+ 44 - 0
BingHaoBang/Assets.xcassets/AppIcon.appiconset/Contents.json

@@ -0,0 +1,44 @@
+{
+  "images" : [
+    {
+      "size" : "29x29",
+      "idiom" : "iphone",
+      "filename" : "AppIcon29x29@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "29x29",
+      "idiom" : "iphone",
+      "filename" : "AppIcon29x29@3x.png",
+      "scale" : "3x"
+    },
+    {
+      "size" : "40x40",
+      "idiom" : "iphone",
+      "filename" : "AppIcon40x40@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "40x40",
+      "idiom" : "iphone",
+      "filename" : "AppIcon40x40@3x.png",
+      "scale" : "3x"
+    },
+    {
+      "size" : "60x60",
+      "idiom" : "iphone",
+      "filename" : "AppIcon60x60@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "60x60",
+      "idiom" : "iphone",
+      "filename" : "AppIcon60x60@3x.png",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}

+ 6 - 0
BingHaoBang/Assets.xcassets/Contents.json

@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}

+ 6 - 0
BingHaoBang/Assets.xcassets/tabbar/Contents.json

@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}

+ 21 - 0
BingHaoBang/Assets.xcassets/tabbar/tabbar_chat.imageset/Contents.json

@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "tabbar_chat@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}

BIN
BingHaoBang/Assets.xcassets/tabbar/tabbar_chat.imageset/tabbar_chat@2x.png


+ 21 - 0
BingHaoBang/Assets.xcassets/tabbar/tabbar_chat_selected.imageset/Contents.json

@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "tabbar_chat_selected@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}

BIN
BingHaoBang/Assets.xcassets/tabbar/tabbar_chat_selected.imageset/tabbar_chat_selected@2x.png


+ 21 - 0
BingHaoBang/Assets.xcassets/tabbar/tabbar_home.imageset/Contents.json

@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "tabbar_home@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}

BIN
BingHaoBang/Assets.xcassets/tabbar/tabbar_home.imageset/tabbar_home@2x.png


+ 21 - 0
BingHaoBang/Assets.xcassets/tabbar/tabbar_home_selected.imageset/Contents.json

@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "tabbar_home_selected@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}

BIN
BingHaoBang/Assets.xcassets/tabbar/tabbar_home_selected.imageset/tabbar_home_selected@2x.png


+ 21 - 0
BingHaoBang/Assets.xcassets/tabbar/tabbar_me.imageset/Contents.json

@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "tabbar_me@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}

BIN
BingHaoBang/Assets.xcassets/tabbar/tabbar_me.imageset/tabbar_me@2x.png


+ 21 - 0
BingHaoBang/Assets.xcassets/tabbar/tabbar_me_selected.imageset/Contents.json

@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "tabbar_me_selected@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}

BIN
BingHaoBang/Assets.xcassets/tabbar/tabbar_me_selected.imageset/tabbar_me_selected@2x.png


+ 27 - 0
BingHaoBang/Base.lproj/LaunchScreen.storyboard

@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="8150" systemVersion="15A204g" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" initialViewController="01J-lp-oVM">
+    <dependencies>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8122"/>
+    </dependencies>
+    <scenes>
+        <!--View Controller-->
+        <scene sceneID="EHf-IW-A2E">
+            <objects>
+                <viewController id="01J-lp-oVM" sceneMemberID="viewController">
+                    <layoutGuides>
+                        <viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
+                        <viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
+                    </layoutGuides>
+                    <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
+                        <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <animations/>
+                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
+                    </view>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="53" y="375"/>
+        </scene>
+    </scenes>
+</document>

+ 40 - 0
BingHaoBang/Info.plist

@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>en</string>
+	<key>CFBundleExecutable</key>
+	<string>$(EXECUTABLE_NAME)</string>
+	<key>CFBundleIdentifier</key>
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>$(PRODUCT_NAME)</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>1</string>
+	<key>LSRequiresIPhoneOS</key>
+	<true/>
+	<key>UILaunchStoryboardName</key>
+	<string>LaunchScreen</string>
+	<key>UIMainStoryboardFile</key>
+	<string></string>
+	<key>UIRequiredDeviceCapabilities</key>
+	<array>
+		<string>armv7</string>
+	</array>
+	<key>UISupportedInterfaceOrientations</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+		<string>UIInterfaceOrientationLandscapeLeft</string>
+		<string>UIInterfaceOrientationLandscapeRight</string>
+	</array>
+</dict>
+</plist>

+ 25 - 0
BingHaoBang/ViewController.swift

@@ -0,0 +1,25 @@
+//
+//  ViewController.swift
+//  BingHaoBang
+//
+//  Created by zhangjidong on 16/3/31.
+//  Copyright © 2016年 Zjdboy. All rights reserved.
+//
+
+import UIKit
+
+class ViewController: UIViewController {
+
+    override func viewDidLoad() {
+        super.viewDidLoad()
+        // Do any additional setup after loading the view, typically from a nib.
+    }
+
+    override func didReceiveMemoryWarning() {
+        super.didReceiveMemoryWarning()
+        // Dispose of any resources that can be recreated.
+    }
+
+
+}
+

BIN
Common/.DS_Store


+ 19 - 0
Common/Config.swift

@@ -0,0 +1,19 @@
+//
+//  Config.swift
+//  BingHaoBang
+//
+//  Created by zhangjidong on 16/3/31.
+//  Copyright © 2016年 Zjdboy. All rights reserved.
+//
+
+import UIKit
+
+//屏幕大小
+let SCREEN_BOUNDS = UIScreen.mainScreen().bounds
+
+//屏幕宽高
+let SCREEN_WIDTH = UIScreen.mainScreen().bounds.size.width
+let SCREEN_HEIGHT = UIScreen.mainScreen().bounds.size.height
+
+//全局颜色
+let GLOBAL_COLOR = UIColor(red:0.86, green:0.52, blue:0.43, alpha:1)

+ 10 - 0
Podfile

@@ -0,0 +1,10 @@
+source 'https://github.com/CocoaPods/Specs.git'
+platform :ios, '8.0'
+use_frameworks!
+
+target 'BingHaoBang' do
+  pod 'Alamofire', '~> 3.0'
+  pod 'AlamofireImage', '~> 2.0'
+  pod 'AlamofireObjectMapper', '~> 2.1'
+end
+

+ 19 - 0
Pods/Alamofire/LICENSE

@@ -0,0 +1,19 @@
+Copyright (c) 2014–2016 Alamofire Software Foundation (http://alamofire.org/)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.

File diff suppressed because it is too large
+ 1196 - 0
Pods/Alamofire/README.md


+ 368 - 0
Pods/Alamofire/Source/Alamofire.swift

@@ -0,0 +1,368 @@
+// Alamofire.swift
+//
+// Copyright (c) 2014–2016 Alamofire Software Foundation (http://alamofire.org/)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+import Foundation
+
+// MARK: - URLStringConvertible
+
+/**
+    Types adopting the `URLStringConvertible` protocol can be used to construct URL strings, which are then used to 
+    construct URL requests.
+*/
+public protocol URLStringConvertible {
+    /**
+        A URL that conforms to RFC 2396.
+
+        Methods accepting a `URLStringConvertible` type parameter parse it according to RFCs 1738 and 1808.
+
+        See https://tools.ietf.org/html/rfc2396
+        See https://tools.ietf.org/html/rfc1738
+        See https://tools.ietf.org/html/rfc1808
+    */
+    var URLString: String { get }
+}
+
+extension String: URLStringConvertible {
+    public var URLString: String {
+        return self
+    }
+}
+
+extension NSURL: URLStringConvertible {
+    public var URLString: String {
+        return absoluteString
+    }
+}
+
+extension NSURLComponents: URLStringConvertible {
+    public var URLString: String {
+        return URL!.URLString
+    }
+}
+
+extension NSURLRequest: URLStringConvertible {
+    public var URLString: String {
+        return URL!.URLString
+    }
+}
+
+// MARK: - URLRequestConvertible
+
+/**
+    Types adopting the `URLRequestConvertible` protocol can be used to construct URL requests.
+*/
+public protocol URLRequestConvertible {
+    /// The URL request.
+    var URLRequest: NSMutableURLRequest { get }
+}
+
+extension NSURLRequest: URLRequestConvertible {
+    public var URLRequest: NSMutableURLRequest {
+        return self.mutableCopy() as! NSMutableURLRequest
+    }
+}
+
+// MARK: - Convenience
+
+func URLRequest(
+    method: Method,
+    _ URLString: URLStringConvertible,
+    headers: [String: String]? = nil)
+    -> NSMutableURLRequest
+{
+    let mutableURLRequest = NSMutableURLRequest(URL: NSURL(string: URLString.URLString)!)
+    mutableURLRequest.HTTPMethod = method.rawValue
+
+    if let headers = headers {
+        for (headerField, headerValue) in headers {
+            mutableURLRequest.setValue(headerValue, forHTTPHeaderField: headerField)
+        }
+    }
+
+    return mutableURLRequest
+}
+
+// MARK: - Request Methods
+
+/**
+    Creates a request using the shared manager instance for the specified method, URL string, parameters, and
+    parameter encoding.
+
+    - parameter method:     The HTTP method.
+    - parameter URLString:  The URL string.
+    - parameter parameters: The parameters. `nil` by default.
+    - parameter encoding:   The parameter encoding. `.URL` by default.
+    - parameter headers:    The HTTP headers. `nil` by default.
+
+    - returns: The created request.
+*/
+public func request(
+    method: Method,
+    _ URLString: URLStringConvertible,
+    parameters: [String: AnyObject]? = nil,
+    encoding: ParameterEncoding = .URL,
+    headers: [String: String]? = nil)
+    -> Request
+{
+    return Manager.sharedInstance.request(
+        method,
+        URLString,
+        parameters: parameters,
+        encoding: encoding,
+        headers: headers
+    )
+}
+
+/**
+    Creates a request using the shared manager instance for the specified URL request.
+
+    If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
+
+    - parameter URLRequest: The URL request
+
+    - returns: The created request.
+*/
+public func request(URLRequest: URLRequestConvertible) -> Request {
+    return Manager.sharedInstance.request(URLRequest.URLRequest)
+}
+
+// MARK: - Upload Methods
+
+// MARK: File
+
+/**
+    Creates an upload request using the shared manager instance for the specified method, URL string, and file.
+
+    - parameter method:    The HTTP method.
+    - parameter URLString: The URL string.
+    - parameter headers:   The HTTP headers. `nil` by default.
+    - parameter file:      The file to upload.
+
+    - returns: The created upload request.
+*/
+public func upload(
+    method: Method,
+    _ URLString: URLStringConvertible,
+    headers: [String: String]? = nil,
+    file: NSURL)
+    -> Request
+{
+    return Manager.sharedInstance.upload(method, URLString, headers: headers, file: file)
+}
+
+/**
+    Creates an upload request using the shared manager instance for the specified URL request and file.
+
+    - parameter URLRequest: The URL request.
+    - parameter file:       The file to upload.
+
+    - returns: The created upload request.
+*/
+public func upload(URLRequest: URLRequestConvertible, file: NSURL) -> Request {
+    return Manager.sharedInstance.upload(URLRequest, file: file)
+}
+
+// MARK: Data
+
+/**
+    Creates an upload request using the shared manager instance for the specified method, URL string, and data.
+
+    - parameter method:    The HTTP method.
+    - parameter URLString: The URL string.
+    - parameter headers:   The HTTP headers. `nil` by default.
+    - parameter data:      The data to upload.
+
+    - returns: The created upload request.
+*/
+public func upload(
+    method: Method,
+    _ URLString: URLStringConvertible,
+    headers: [String: String]? = nil,
+    data: NSData)
+    -> Request
+{
+    return Manager.sharedInstance.upload(method, URLString, headers: headers, data: data)
+}
+
+/**
+    Creates an upload request using the shared manager instance for the specified URL request and data.
+
+    - parameter URLRequest: The URL request.
+    - parameter data:       The data to upload.
+
+    - returns: The created upload request.
+*/
+public func upload(URLRequest: URLRequestConvertible, data: NSData) -> Request {
+    return Manager.sharedInstance.upload(URLRequest, data: data)
+}
+
+// MARK: Stream
+
+/**
+    Creates an upload request using the shared manager instance for the specified method, URL string, and stream.
+
+    - parameter method:    The HTTP method.
+    - parameter URLString: The URL string.
+    - parameter headers:   The HTTP headers. `nil` by default.
+    - parameter stream:    The stream to upload.
+
+    - returns: The created upload request.
+*/
+public func upload(
+    method: Method,
+    _ URLString: URLStringConvertible,
+    headers: [String: String]? = nil,
+    stream: NSInputStream)
+    -> Request
+{
+    return Manager.sharedInstance.upload(method, URLString, headers: headers, stream: stream)
+}
+
+/**
+    Creates an upload request using the shared manager instance for the specified URL request and stream.
+
+    - parameter URLRequest: The URL request.
+    - parameter stream:     The stream to upload.
+
+    - returns: The created upload request.
+*/
+public func upload(URLRequest: URLRequestConvertible, stream: NSInputStream) -> Request {
+    return Manager.sharedInstance.upload(URLRequest, stream: stream)
+}
+
+// MARK: MultipartFormData
+
+/**
+    Creates an upload request using the shared manager instance for the specified method and URL string.
+
+    - parameter method:                  The HTTP method.
+    - parameter URLString:               The URL string.
+    - parameter headers:                 The HTTP headers. `nil` by default.
+    - parameter multipartFormData:       The closure used to append body parts to the `MultipartFormData`.
+    - parameter encodingMemoryThreshold: The encoding memory threshold in bytes.
+                                         `MultipartFormDataEncodingMemoryThreshold` by default.
+    - parameter encodingCompletion:      The closure called when the `MultipartFormData` encoding is complete.
+*/
+public func upload(
+    method: Method,
+    _ URLString: URLStringConvertible,
+    headers: [String: String]? = nil,
+    multipartFormData: MultipartFormData -> Void,
+    encodingMemoryThreshold: UInt64 = Manager.MultipartFormDataEncodingMemoryThreshold,
+    encodingCompletion: (Manager.MultipartFormDataEncodingResult -> Void)?)
+{
+    return Manager.sharedInstance.upload(
+        method,
+        URLString,
+        headers: headers,
+        multipartFormData: multipartFormData,
+        encodingMemoryThreshold: encodingMemoryThreshold,
+        encodingCompletion: encodingCompletion
+    )
+}
+
+/**
+    Creates an upload request using the shared manager instance for the specified method and URL string.
+
+    - parameter URLRequest:              The URL request.
+    - parameter multipartFormData:       The closure used to append body parts to the `MultipartFormData`.
+    - parameter encodingMemoryThreshold: The encoding memory threshold in bytes.
+                                         `MultipartFormDataEncodingMemoryThreshold` by default.
+    - parameter encodingCompletion:      The closure called when the `MultipartFormData` encoding is complete.
+*/
+public func upload(
+    URLRequest: URLRequestConvertible,
+    multipartFormData: MultipartFormData -> Void,
+    encodingMemoryThreshold: UInt64 = Manager.MultipartFormDataEncodingMemoryThreshold,
+    encodingCompletion: (Manager.MultipartFormDataEncodingResult -> Void)?)
+{
+    return Manager.sharedInstance.upload(
+        URLRequest,
+        multipartFormData: multipartFormData,
+        encodingMemoryThreshold: encodingMemoryThreshold,
+        encodingCompletion: encodingCompletion
+    )
+}
+
+// MARK: - Download Methods
+
+// MARK: URL Request
+
+/**
+    Creates a download request using the shared manager instance for the specified method and URL string.
+
+    - parameter method:      The HTTP method.
+    - parameter URLString:   The URL string.
+    - parameter parameters:  The parameters. `nil` by default.
+    - parameter encoding:    The parameter encoding. `.URL` by default.
+    - parameter headers:     The HTTP headers. `nil` by default.
+    - parameter destination: The closure used to determine the destination of the downloaded file.
+
+    - returns: The created download request.
+*/
+public func download(
+    method: Method,
+    _ URLString: URLStringConvertible,
+    parameters: [String: AnyObject]? = nil,
+    encoding: ParameterEncoding = .URL,
+    headers: [String: String]? = nil,
+    destination: Request.DownloadFileDestination)
+    -> Request
+{
+    return Manager.sharedInstance.download(
+        method,
+        URLString,
+        parameters: parameters,
+        encoding: encoding,
+        headers: headers,
+        destination: destination
+    )
+}
+
+/**
+    Creates a download request using the shared manager instance for the specified URL request.
+
+    - parameter URLRequest:  The URL request.
+    - parameter destination: The closure used to determine the destination of the downloaded file.
+
+    - returns: The created download request.
+*/
+public func download(URLRequest: URLRequestConvertible, destination: Request.DownloadFileDestination) -> Request {
+    return Manager.sharedInstance.download(URLRequest, destination: destination)
+}
+
+// MARK: Resume Data
+
+/**
+    Creates a request using the shared manager instance for downloading from the resume data produced from a 
+    previous request cancellation.
+
+    - parameter resumeData:  The resume data. This is an opaque data blob produced by `NSURLSessionDownloadTask`
+                             when a task is cancelled. See `NSURLSession -downloadTaskWithResumeData:` for additional 
+                             information.
+    - parameter destination: The closure used to determine the destination of the downloaded file.
+
+    - returns: The created download request.
+*/
+public func download(resumeData data: NSData, destination: Request.DownloadFileDestination) -> Request {
+    return Manager.sharedInstance.download(data, destination: destination)
+}

+ 246 - 0
Pods/Alamofire/Source/Download.swift

@@ -0,0 +1,246 @@
+// Download.swift
+//
+// Copyright (c) 2014–2016 Alamofire Software Foundation (http://alamofire.org/)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+import Foundation
+
+extension Manager {
+    private enum Downloadable {
+        case Request(NSURLRequest)
+        case ResumeData(NSData)
+    }
+
+    private func download(downloadable: Downloadable, destination: Request.DownloadFileDestination) -> Request {
+        var downloadTask: NSURLSessionDownloadTask!
+
+        switch downloadable {
+        case .Request(let request):
+            dispatch_sync(queue) {
+                downloadTask = self.session.downloadTaskWithRequest(request)
+            }
+        case .ResumeData(let resumeData):
+            dispatch_sync(queue) {
+                downloadTask = self.session.downloadTaskWithResumeData(resumeData)
+            }
+        }
+
+        let request = Request(session: session, task: downloadTask)
+
+        if let downloadDelegate = request.delegate as? Request.DownloadTaskDelegate {
+            downloadDelegate.downloadTaskDidFinishDownloadingToURL = { session, downloadTask, URL in
+                return destination(URL, downloadTask.response as! NSHTTPURLResponse)
+            }
+        }
+
+        delegate[request.delegate.task] = request.delegate
+
+        if startRequestsImmediately {
+            request.resume()
+        }
+
+        return request
+    }
+
+    // MARK: Request
+
+    /**
+        Creates a download request for the specified method, URL string, parameters, parameter encoding, headers
+        and destination.
+
+        If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
+
+        - parameter method:      The HTTP method.
+        - parameter URLString:   The URL string.
+        - parameter parameters:  The parameters. `nil` by default.
+        - parameter encoding:    The parameter encoding. `.URL` by default.
+        - parameter headers:     The HTTP headers. `nil` by default.
+        - parameter destination: The closure used to determine the destination of the downloaded file.
+
+        - returns: The created download request.
+    */
+    public func download(
+        method: Method,
+        _ URLString: URLStringConvertible,
+        parameters: [String: AnyObject]? = nil,
+        encoding: ParameterEncoding = .URL,
+        headers: [String: String]? = nil,
+        destination: Request.DownloadFileDestination)
+        -> Request
+    {
+        let mutableURLRequest = URLRequest(method, URLString, headers: headers)
+        let encodedURLRequest = encoding.encode(mutableURLRequest, parameters: parameters).0
+
+        return download(encodedURLRequest, destination: destination)
+    }
+
+    /**
+        Creates a request for downloading from the specified URL request.
+
+        If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
+
+        - parameter URLRequest:  The URL request
+        - parameter destination: The closure used to determine the destination of the downloaded file.
+
+        - returns: The created download request.
+    */
+    public func download(URLRequest: URLRequestConvertible, destination: Request.DownloadFileDestination) -> Request {
+        return download(.Request(URLRequest.URLRequest), destination: destination)
+    }
+
+    // MARK: Resume Data
+
+    /**
+        Creates a request for downloading from the resume data produced from a previous request cancellation.
+
+        If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
+
+        - parameter resumeData:  The resume data. This is an opaque data blob produced by `NSURLSessionDownloadTask` 
+                                 when a task is cancelled. See `NSURLSession -downloadTaskWithResumeData:` for 
+                                 additional information.
+        - parameter destination: The closure used to determine the destination of the downloaded file.
+
+        - returns: The created download request.
+    */
+    public func download(resumeData: NSData, destination: Request.DownloadFileDestination) -> Request {
+        return download(.ResumeData(resumeData), destination: destination)
+    }
+}
+
+// MARK: -
+
+extension Request {
+    /**
+        A closure executed once a request has successfully completed in order to determine where to move the temporary 
+        file written to during the download process. The closure takes two arguments: the temporary file URL and the URL 
+        response, and returns a single argument: the file URL where the temporary file should be moved.
+    */
+    public typealias DownloadFileDestination = (NSURL, NSHTTPURLResponse) -> NSURL
+
+    /**
+        Creates a download file destination closure which uses the default file manager to move the temporary file to a 
+        file URL in the first available directory with the specified search path directory and search path domain mask.
+
+        - parameter directory: The search path directory. `.DocumentDirectory` by default.
+        - parameter domain:    The search path domain mask. `.UserDomainMask` by default.
+
+        - returns: A download file destination closure.
+    */
+    public class func suggestedDownloadDestination(
+        directory directory: NSSearchPathDirectory = .DocumentDirectory,
+        domain: NSSearchPathDomainMask = .UserDomainMask)
+        -> DownloadFileDestination
+    {
+        return { temporaryURL, response -> NSURL in
+            let directoryURLs = NSFileManager.defaultManager().URLsForDirectory(directory, inDomains: domain)
+
+            if !directoryURLs.isEmpty {
+                return directoryURLs[0].URLByAppendingPathComponent(response.suggestedFilename!)
+            }
+
+            return temporaryURL
+        }
+    }
+
+    /// The resume data of the underlying download task if available after a failure.
+    public var resumeData: NSData? {
+        var data: NSData?
+
+        if let delegate = delegate as? DownloadTaskDelegate {
+            data = delegate.resumeData
+        }
+
+        return data
+    }
+
+    // MARK: - DownloadTaskDelegate
+
+    class DownloadTaskDelegate: TaskDelegate, NSURLSessionDownloadDelegate {
+        var downloadTask: NSURLSessionDownloadTask? { return task as? NSURLSessionDownloadTask }
+        var downloadProgress: ((Int64, Int64, Int64) -> Void)?
+
+        var resumeData: NSData?
+        override var data: NSData? { return resumeData }
+
+        // MARK: - NSURLSessionDownloadDelegate
+
+        // MARK: Override Closures
+
+        var downloadTaskDidFinishDownloadingToURL: ((NSURLSession, NSURLSessionDownloadTask, NSURL) -> NSURL)?
+        var downloadTaskDidWriteData: ((NSURLSession, NSURLSessionDownloadTask, Int64, Int64, Int64) -> Void)?
+        var downloadTaskDidResumeAtOffset: ((NSURLSession, NSURLSessionDownloadTask, Int64, Int64) -> Void)?
+
+        // MARK: Delegate Methods
+
+        func URLSession(
+            session: NSURLSession,
+            downloadTask: NSURLSessionDownloadTask,
+            didFinishDownloadingToURL location: NSURL)
+        {
+            if let downloadTaskDidFinishDownloadingToURL = downloadTaskDidFinishDownloadingToURL {
+                do {
+                    let destination = downloadTaskDidFinishDownloadingToURL(session, downloadTask, location)
+                    try NSFileManager.defaultManager().moveItemAtURL(location, toURL: destination)
+                } catch {
+                    self.error = error as NSError
+                }
+            }
+        }
+
+        func URLSession(
+            session: NSURLSession,
+            downloadTask: NSURLSessionDownloadTask,
+            didWriteData bytesWritten: Int64,
+            totalBytesWritten: Int64,
+            totalBytesExpectedToWrite: Int64)
+        {
+            if initialResponseTime == nil { initialResponseTime = CFAbsoluteTimeGetCurrent() }
+
+            if let downloadTaskDidWriteData = downloadTaskDidWriteData {
+                downloadTaskDidWriteData(
+                    session,
+                    downloadTask,
+                    bytesWritten,
+                    totalBytesWritten, 
+                    totalBytesExpectedToWrite
+                )
+            } else {
+                progress.totalUnitCount = totalBytesExpectedToWrite
+                progress.completedUnitCount = totalBytesWritten
+
+                downloadProgress?(bytesWritten, totalBytesWritten, totalBytesExpectedToWrite)
+            }
+        }
+
+        func URLSession(
+            session: NSURLSession,
+            downloadTask: NSURLSessionDownloadTask,
+            didResumeAtOffset fileOffset: Int64,
+            expectedTotalBytes: Int64)
+        {
+            if let downloadTaskDidResumeAtOffset = downloadTaskDidResumeAtOffset {
+                downloadTaskDidResumeAtOffset(session, downloadTask, fileOffset, expectedTotalBytes)
+            } else {
+                progress.totalUnitCount = expectedTotalBytes
+                progress.completedUnitCount = fileOffset
+            }
+        }
+    }
+}

+ 66 - 0
Pods/Alamofire/Source/Error.swift

@@ -0,0 +1,66 @@
+// Error.swift
+//
+// Copyright (c) 2014–2016 Alamofire Software Foundation (http://alamofire.org/)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+import Foundation
+
+/// The `Error` struct provides a convenience for creating custom Alamofire NSErrors.
+public struct Error {
+    /// The domain used for creating all Alamofire errors.
+    public static let Domain = "com.alamofire.error"
+
+    /// The custom error codes generated by Alamofire.
+    public enum Code: Int {
+        case InputStreamReadFailed           = -6000
+        case OutputStreamWriteFailed         = -6001
+        case ContentTypeValidationFailed     = -6002
+        case StatusCodeValidationFailed      = -6003
+        case DataSerializationFailed         = -6004
+        case StringSerializationFailed       = -6005
+        case JSONSerializationFailed         = -6006
+        case PropertyListSerializationFailed = -6007
+    }
+
+    /**
+        Creates an `NSError` with the given error code and failure reason.
+
+        - parameter code:          The error code.
+        - parameter failureReason: The failure reason.
+
+        - returns: An `NSError` with the given error code and failure reason.
+    */
+    public static func errorWithCode(code: Code, failureReason: String) -> NSError {
+        return errorWithCode(code.rawValue, failureReason: failureReason)
+    }
+
+    /**
+        Creates an `NSError` with the given error code and failure reason.
+
+        - parameter code:          The error code.
+        - parameter failureReason: The failure reason.
+
+        - returns: An `NSError` with the given error code and failure reason.
+    */
+    public static func errorWithCode(code: Int, failureReason: String) -> NSError {
+        let userInfo = [NSLocalizedFailureReasonErrorKey: failureReason]
+        return NSError(domain: Domain, code: code, userInfo: userInfo)
+    }
+}

+ 695 - 0
Pods/Alamofire/Source/Manager.swift

@@ -0,0 +1,695 @@
+// Manager.swift
+//
+// Copyright (c) 2014–2016 Alamofire Software Foundation (http://alamofire.org/)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+import Foundation
+
+/**
+    Responsible for creating and managing `Request` objects, as well as their underlying `NSURLSession`.
+*/
+public class Manager {
+
+    // MARK: - Properties
+
+    /**
+        A shared instance of `Manager`, used by top-level Alamofire request methods, and suitable for use directly 
+        for any ad hoc requests.
+    */
+    public static let sharedInstance: Manager = {
+        let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
+        configuration.HTTPAdditionalHeaders = Manager.defaultHTTPHeaders
+
+        return Manager(configuration: configuration)
+    }()
+
+    /**
+        Creates default values for the "Accept-Encoding", "Accept-Language" and "User-Agent" headers.
+    */
+    public static let defaultHTTPHeaders: [String: String] = {
+        // Accept-Encoding HTTP Header; see https://tools.ietf.org/html/rfc7230#section-4.2.3
+        let acceptEncoding: String = "gzip;q=1.0, compress;q=0.5"
+
+        // Accept-Language HTTP Header; see https://tools.ietf.org/html/rfc7231#section-5.3.5
+        let acceptLanguage = NSLocale.preferredLanguages().prefix(6).enumerate().map { index, languageCode in
+            let quality = 1.0 - (Double(index) * 0.1)
+            return "\(languageCode);q=\(quality)"
+        }.joinWithSeparator(", ")
+
+        // User-Agent Header; see https://tools.ietf.org/html/rfc7231#section-5.5.3
+        let userAgent: String = {
+            if let info = NSBundle.mainBundle().infoDictionary {
+                let executable: AnyObject = info[kCFBundleExecutableKey as String] ?? "Unknown"
+                let bundle: AnyObject = info[kCFBundleIdentifierKey as String] ?? "Unknown"
+                let version: AnyObject = info[kCFBundleVersionKey as String] ?? "Unknown"
+                let os: AnyObject = NSProcessInfo.processInfo().operatingSystemVersionString ?? "Unknown"
+
+                var mutableUserAgent = NSMutableString(string: "\(executable)/\(bundle) (\(version); OS \(os))") as CFMutableString
+                let transform = NSString(string: "Any-Latin; Latin-ASCII; [:^ASCII:] Remove") as CFString
+
+                if CFStringTransform(mutableUserAgent, UnsafeMutablePointer<CFRange>(nil), transform, false) {
+                    return mutableUserAgent as String
+                }
+            }
+
+            return "Alamofire"
+        }()
+
+        return [
+            "Accept-Encoding": acceptEncoding,
+            "Accept-Language": acceptLanguage,
+            "User-Agent": userAgent
+        ]
+    }()
+
+    let queue = dispatch_queue_create(nil, DISPATCH_QUEUE_SERIAL)
+
+    /// The underlying session.
+    public let session: NSURLSession
+
+    /// The session delegate handling all the task and session delegate callbacks.
+    public let delegate: SessionDelegate
+
+    /// Whether to start requests immediately after being constructed. `true` by default.
+    public var startRequestsImmediately: Bool = true
+
+    /**
+        The background completion handler closure provided by the UIApplicationDelegate 
+        `application:handleEventsForBackgroundURLSession:completionHandler:` method. By setting the background 
+        completion handler, the SessionDelegate `sessionDidFinishEventsForBackgroundURLSession` closure implementation 
+        will automatically call the handler.
+    
+        If you need to handle your own events before the handler is called, then you need to override the 
+        SessionDelegate `sessionDidFinishEventsForBackgroundURLSession` and manually call the handler when finished.
+    
+        `nil` by default.
+    */
+    public var backgroundCompletionHandler: (() -> Void)?
+
+    // MARK: - Lifecycle
+
+    /**
+        Initializes the `Manager` instance with the specified configuration, delegate and server trust policy.
+
+        - parameter configuration:            The configuration used to construct the managed session. 
+                                              `NSURLSessionConfiguration.defaultSessionConfiguration()` by default.
+        - parameter delegate:                 The delegate used when initializing the session. `SessionDelegate()` by
+                                              default.
+        - parameter serverTrustPolicyManager: The server trust policy manager to use for evaluating all server trust 
+                                              challenges. `nil` by default.
+
+        - returns: The new `Manager` instance.
+    */
+    public init(
+        configuration: NSURLSessionConfiguration = NSURLSessionConfiguration.defaultSessionConfiguration(),
+        delegate: SessionDelegate = SessionDelegate(),
+        serverTrustPolicyManager: ServerTrustPolicyManager? = nil)
+    {
+        self.delegate = delegate
+        self.session = NSURLSession(configuration: configuration, delegate: delegate, delegateQueue: nil)
+
+        commonInit(serverTrustPolicyManager: serverTrustPolicyManager)
+    }
+
+    /**
+        Initializes the `Manager` instance with the specified session, delegate and server trust policy.
+
+        - parameter session:                  The URL session.
+        - parameter delegate:                 The delegate of the URL session. Must equal the URL session's delegate.
+        - parameter serverTrustPolicyManager: The server trust policy manager to use for evaluating all server trust
+                                              challenges. `nil` by default.
+
+        - returns: The new `Manager` instance if the URL session's delegate matches the delegate parameter.
+    */
+    public init?(
+        session: NSURLSession,
+        delegate: SessionDelegate,
+        serverTrustPolicyManager: ServerTrustPolicyManager? = nil)
+    {
+        self.delegate = delegate
+        self.session = session
+
+        guard delegate === session.delegate else { return nil }
+
+        commonInit(serverTrustPolicyManager: serverTrustPolicyManager)
+    }
+
+    private func commonInit(serverTrustPolicyManager serverTrustPolicyManager: ServerTrustPolicyManager?) {
+        session.serverTrustPolicyManager = serverTrustPolicyManager
+
+        delegate.sessionDidFinishEventsForBackgroundURLSession = { [weak self] session in
+            guard let strongSelf = self else { return }
+            dispatch_async(dispatch_get_main_queue()) { strongSelf.backgroundCompletionHandler?() }
+        }
+    }
+
+    deinit {
+        session.invalidateAndCancel()
+    }
+
+    // MARK: - Request
+
+    /**
+        Creates a request for the specified method, URL string, parameters, parameter encoding and headers.
+
+        - parameter method:     The HTTP method.
+        - parameter URLString:  The URL string.
+        - parameter parameters: The parameters. `nil` by default.
+        - parameter encoding:   The parameter encoding. `.URL` by default.
+        - parameter headers:    The HTTP headers. `nil` by default.
+
+        - returns: The created request.
+    */
+    public func request(
+        method: Method,
+        _ URLString: URLStringConvertible,
+        parameters: [String: AnyObject]? = nil,
+        encoding: ParameterEncoding = .URL,
+        headers: [String: String]? = nil)
+        -> Request
+    {
+        let mutableURLRequest = URLRequest(method, URLString, headers: headers)
+        let encodedURLRequest = encoding.encode(mutableURLRequest, parameters: parameters).0
+        return request(encodedURLRequest)
+    }
+
+    /**
+        Creates a request for the specified URL request.
+
+        If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
+
+        - parameter URLRequest: The URL request
+
+        - returns: The created request.
+    */
+    public func request(URLRequest: URLRequestConvertible) -> Request {
+        var dataTask: NSURLSessionDataTask!
+        dispatch_sync(queue) { dataTask = self.session.dataTaskWithRequest(URLRequest.URLRequest) }
+
+        let request = Request(session: session, task: dataTask)
+        delegate[request.delegate.task] = request.delegate
+
+        if startRequestsImmediately {
+            request.resume()
+        }
+
+        return request
+    }
+
+    // MARK: - SessionDelegate
+
+    /**
+        Responsible for handling all delegate callbacks for the underlying session.
+    */
+    public final class SessionDelegate: NSObject, NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDataDelegate, NSURLSessionDownloadDelegate {
+        private var subdelegates: [Int: Request.TaskDelegate] = [:]
+        private let subdelegateQueue = dispatch_queue_create(nil, DISPATCH_QUEUE_CONCURRENT)
+
+        subscript(task: NSURLSessionTask) -> Request.TaskDelegate? {
+            get {
+                var subdelegate: Request.TaskDelegate?
+                dispatch_sync(subdelegateQueue) { subdelegate = self.subdelegates[task.taskIdentifier] }
+
+                return subdelegate
+            }
+
+            set {
+                dispatch_barrier_async(subdelegateQueue) { self.subdelegates[task.taskIdentifier] = newValue }
+            }
+        }
+
+        /**
+            Initializes the `SessionDelegate` instance.
+
+            - returns: The new `SessionDelegate` instance.
+        */
+        public override init() {
+            super.init()
+        }
+
+        // MARK: - NSURLSessionDelegate
+
+        // MARK: Override Closures
+
+        /// Overrides default behavior for NSURLSessionDelegate method `URLSession:didBecomeInvalidWithError:`.
+        public var sessionDidBecomeInvalidWithError: ((NSURLSession, NSError?) -> Void)?
+
+        /// Overrides default behavior for NSURLSessionDelegate method `URLSession:didReceiveChallenge:completionHandler:`.
+        public var sessionDidReceiveChallenge: ((NSURLSession, NSURLAuthenticationChallenge) -> (NSURLSessionAuthChallengeDisposition, NSURLCredential?))?
+
+        /// Overrides default behavior for NSURLSessionDelegate method `URLSessionDidFinishEventsForBackgroundURLSession:`.
+        public var sessionDidFinishEventsForBackgroundURLSession: ((NSURLSession) -> Void)?
+
+        // MARK: Delegate Methods
+
+        /**
+            Tells the delegate that the session has been invalidated.
+
+            - parameter session: The session object that was invalidated.
+            - parameter error:   The error that caused invalidation, or nil if the invalidation was explicit.
+        */
+        public func URLSession(session: NSURLSession, didBecomeInvalidWithError error: NSError?) {
+            sessionDidBecomeInvalidWithError?(session, error)
+        }
+
+        /**
+            Requests credentials from the delegate in response to a session-level authentication request from the remote server.
+
+            - parameter session:           The session containing the task that requested authentication.
+            - parameter challenge:         An object that contains the request for authentication.
+            - parameter completionHandler: A handler that your delegate method must call providing the disposition and credential.
+        */
+        public func URLSession(
+            session: NSURLSession,
+            didReceiveChallenge challenge: NSURLAuthenticationChallenge,
+            completionHandler: ((NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void))
+        {
+            var disposition: NSURLSessionAuthChallengeDisposition = .PerformDefaultHandling
+            var credential: NSURLCredential?
+
+            if let sessionDidReceiveChallenge = sessionDidReceiveChallenge {
+                (disposition, credential) = sessionDidReceiveChallenge(session, challenge)
+            } else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
+                let host = challenge.protectionSpace.host
+
+                if let
+                    serverTrustPolicy = session.serverTrustPolicyManager?.serverTrustPolicyForHost(host),
+                    serverTrust = challenge.protectionSpace.serverTrust
+                {
+                    if serverTrustPolicy.evaluateServerTrust(serverTrust, isValidForHost: host) {
+                        disposition = .UseCredential
+                        credential = NSURLCredential(forTrust: serverTrust)
+                    } else {
+                        disposition = .CancelAuthenticationChallenge
+                    }
+                }
+            }
+
+            completionHandler(disposition, credential)
+        }
+
+        /**
+            Tells the delegate that all messages enqueued for a session have been delivered.
+
+            - parameter session: The session that no longer has any outstanding requests.
+        */
+        public func URLSessionDidFinishEventsForBackgroundURLSession(session: NSURLSession) {
+            sessionDidFinishEventsForBackgroundURLSession?(session)
+        }
+
+        // MARK: - NSURLSessionTaskDelegate
+
+        // MARK: Override Closures
+
+        /// Overrides default behavior for NSURLSessionTaskDelegate method `URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:`.
+        public var taskWillPerformHTTPRedirection: ((NSURLSession, NSURLSessionTask, NSHTTPURLResponse, NSURLRequest) -> NSURLRequest?)?
+
+        /// Overrides default behavior for NSURLSessionTaskDelegate method `URLSession:task:didReceiveChallenge:completionHandler:`.
+        public var taskDidReceiveChallenge: ((NSURLSession, NSURLSessionTask, NSURLAuthenticationChallenge) -> (NSURLSessionAuthChallengeDisposition, NSURLCredential?))?
+
+        /// Overrides default behavior for NSURLSessionTaskDelegate method `URLSession:session:task:needNewBodyStream:`.
+        public var taskNeedNewBodyStream: ((NSURLSession, NSURLSessionTask) -> NSInputStream!)?
+
+        /// Overrides default behavior for NSURLSessionTaskDelegate method `URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:`.
+        public var taskDidSendBodyData: ((NSURLSession, NSURLSessionTask, Int64, Int64, Int64) -> Void)?
+
+        /// Overrides default behavior for NSURLSessionTaskDelegate method `URLSession:task:didCompleteWithError:`.
+        public var taskDidComplete: ((NSURLSession, NSURLSessionTask, NSError?) -> Void)?
+
+        // MARK: Delegate Methods
+
+        /**
+            Tells the delegate that the remote server requested an HTTP redirect.
+
+            - parameter session:           The session containing the task whose request resulted in a redirect.
+            - parameter task:              The task whose request resulted in a redirect.
+            - parameter response:          An object containing the server’s response to the original request.
+            - parameter request:           A URL request object filled out with the new location.
+            - parameter completionHandler: A closure that your handler should call with either the value of the request 
+                                           parameter, a modified URL request object, or NULL to refuse the redirect and 
+                                           return the body of the redirect response.
+        */
+        public func URLSession(
+            session: NSURLSession,
+            task: NSURLSessionTask,
+            willPerformHTTPRedirection response: NSHTTPURLResponse,
+            newRequest request: NSURLRequest,
+            completionHandler: ((NSURLRequest?) -> Void))
+        {
+            var redirectRequest: NSURLRequest? = request
+
+            if let taskWillPerformHTTPRedirection = taskWillPerformHTTPRedirection {
+                redirectRequest = taskWillPerformHTTPRedirection(session, task, response, request)
+            }
+
+            completionHandler(redirectRequest)
+        }
+
+        /**
+            Requests credentials from the delegate in response to an authentication request from the remote server.
+
+            - parameter session:           The session containing the task whose request requires authentication.
+            - parameter task:              The task whose request requires authentication.
+            - parameter challenge:         An object that contains the request for authentication.
+            - parameter completionHandler: A handler that your delegate method must call providing the disposition and credential.
+        */
+        public func URLSession(
+            session: NSURLSession,
+            task: NSURLSessionTask,
+            didReceiveChallenge challenge: NSURLAuthenticationChallenge,
+            completionHandler: ((NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void))
+        {
+            if let taskDidReceiveChallenge = taskDidReceiveChallenge {
+                completionHandler(taskDidReceiveChallenge(session, task, challenge))
+            } else if let delegate = self[task] {
+                delegate.URLSession(
+                    session,
+                    task: task,
+                    didReceiveChallenge: challenge,
+                    completionHandler: completionHandler
+                )
+            } else {
+                URLSession(session, didReceiveChallenge: challenge, completionHandler: completionHandler)
+            }
+        }
+
+        /**
+            Tells the delegate when a task requires a new request body stream to send to the remote server.
+
+            - parameter session:           The session containing the task that needs a new body stream.
+            - parameter task:              The task that needs a new body stream.
+            - parameter completionHandler: A completion handler that your delegate method should call with the new body stream.
+        */
+        public func URLSession(
+            session: NSURLSession,
+            task: NSURLSessionTask,
+            needNewBodyStream completionHandler: ((NSInputStream?) -> Void))
+        {
+            if let taskNeedNewBodyStream = taskNeedNewBodyStream {
+                completionHandler(taskNeedNewBodyStream(session, task))
+            } else if let delegate = self[task] {
+                delegate.URLSession(session, task: task, needNewBodyStream: completionHandler)
+            }
+        }
+
+        /**
+            Periodically informs the delegate of the progress of sending body content to the server.
+
+            - parameter session:                  The session containing the data task.
+            - parameter task:                     The data task.
+            - parameter bytesSent:                The number of bytes sent since the last time this delegate method was called.
+            - parameter totalBytesSent:           The total number of bytes sent so far.
+            - parameter totalBytesExpectedToSend: The expected length of the body data.
+        */
+        public func URLSession(
+            session: NSURLSession,
+            task: NSURLSessionTask,
+            didSendBodyData bytesSent: Int64,
+            totalBytesSent: Int64,
+            totalBytesExpectedToSend: Int64)
+        {
+            if let taskDidSendBodyData = taskDidSendBodyData {
+                taskDidSendBodyData(session, task, bytesSent, totalBytesSent, totalBytesExpectedToSend)
+            } else if let delegate = self[task] as? Request.UploadTaskDelegate {
+                delegate.URLSession(
+                    session,
+                    task: task,
+                    didSendBodyData: bytesSent,
+                    totalBytesSent: totalBytesSent,
+                    totalBytesExpectedToSend: totalBytesExpectedToSend
+                )
+            }
+        }
+
+        /**
+            Tells the delegate that the task finished transferring data.
+
+            - parameter session: The session containing the task whose request finished transferring data.
+            - parameter task:    The task whose request finished transferring data.
+            - parameter error:   If an error occurred, an error object indicating how the transfer failed, otherwise nil.
+        */
+        public func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
+            if let taskDidComplete = taskDidComplete {
+                taskDidComplete(session, task, error)
+            } else if let delegate = self[task] {
+                delegate.URLSession(session, task: task, didCompleteWithError: error)
+            }
+
+            NSNotificationCenter.defaultCenter().postNotificationName(Notifications.Task.DidComplete, object: task)
+
+            self[task] = nil
+        }
+
+        // MARK: - NSURLSessionDataDelegate
+
+        // MARK: Override Closures
+
+        /// Overrides default behavior for NSURLSessionDataDelegate method `URLSession:dataTask:didReceiveResponse:completionHandler:`.
+        public var dataTaskDidReceiveResponse: ((NSURLSession, NSURLSessionDataTask, NSURLResponse) -> NSURLSessionResponseDisposition)?
+
+        /// Overrides default behavior for NSURLSessionDataDelegate method `URLSession:dataTask:didBecomeDownloadTask:`.
+        public var dataTaskDidBecomeDownloadTask: ((NSURLSession, NSURLSessionDataTask, NSURLSessionDownloadTask) -> Void)?
+
+        /// Overrides default behavior for NSURLSessionDataDelegate method `URLSession:dataTask:didReceiveData:`.
+        public var dataTaskDidReceiveData: ((NSURLSession, NSURLSessionDataTask, NSData) -> Void)?
+
+        /// Overrides default behavior for NSURLSessionDataDelegate method `URLSession:dataTask:willCacheResponse:completionHandler:`.
+        public var dataTaskWillCacheResponse: ((NSURLSession, NSURLSessionDataTask, NSCachedURLResponse) -> NSCachedURLResponse!)?
+
+        // MARK: Delegate Methods
+
+        /**
+            Tells the delegate that the data task received the initial reply (headers) from the server.
+
+            - parameter session:           The session containing the data task that received an initial reply.
+            - parameter dataTask:          The data task that received an initial reply.
+            - parameter response:          A URL response object populated with headers.
+            - parameter completionHandler: A completion handler that your code calls to continue the transfer, passing a 
+                                           constant to indicate whether the transfer should continue as a data task or 
+                                           should become a download task.
+        */
+        public func URLSession(
+            session: NSURLSession,
+            dataTask: NSURLSessionDataTask,
+            didReceiveResponse response: NSURLResponse,
+            completionHandler: ((NSURLSessionResponseDisposition) -> Void))
+        {
+            var disposition: NSURLSessionResponseDisposition = .Allow
+
+            if let dataTaskDidReceiveResponse = dataTaskDidReceiveResponse {
+                disposition = dataTaskDidReceiveResponse(session, dataTask, response)
+            }
+
+            completionHandler(disposition)
+        }
+
+        /**
+            Tells the delegate that the data task was changed to a download task.
+
+            - parameter session:      The session containing the task that was replaced by a download task.
+            - parameter dataTask:     The data task that was replaced by a download task.
+            - parameter downloadTask: The new download task that replaced the data task.
+        */
+        public func URLSession(
+            session: NSURLSession,
+            dataTask: NSURLSessionDataTask,
+            didBecomeDownloadTask downloadTask: NSURLSessionDownloadTask)
+        {
+            if let dataTaskDidBecomeDownloadTask = dataTaskDidBecomeDownloadTask {
+                dataTaskDidBecomeDownloadTask(session, dataTask, downloadTask)
+            } else {
+                let downloadDelegate = Request.DownloadTaskDelegate(task: downloadTask)
+                self[downloadTask] = downloadDelegate
+            }
+        }
+
+        /**
+            Tells the delegate that the data task has received some of the expected data.
+
+            - parameter session:  The session containing the data task that provided data.
+            - parameter dataTask: The data task that provided data.
+            - parameter data:     A data object containing the transferred data.
+        */
+        public func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData) {
+            if let dataTaskDidReceiveData = dataTaskDidReceiveData {
+                dataTaskDidReceiveData(session, dataTask, data)
+            } else if let delegate = self[dataTask] as? Request.DataTaskDelegate {
+                delegate.URLSession(session, dataTask: dataTask, didReceiveData: data)
+            }
+        }
+
+        /**
+            Asks the delegate whether the data (or upload) task should store the response in the cache.
+
+            - parameter session:           The session containing the data (or upload) task.
+            - parameter dataTask:          The data (or upload) task.
+            - parameter proposedResponse:  The default caching behavior. This behavior is determined based on the current 
+                                           caching policy and the values of certain received headers, such as the Pragma 
+                                           and Cache-Control headers.
+            - parameter completionHandler: A block that your handler must call, providing either the original proposed 
+                                           response, a modified version of that response, or NULL to prevent caching the 
+                                           response. If your delegate implements this method, it must call this completion 
+                                           handler; otherwise, your app leaks memory.
+        */
+        public func URLSession(
+            session: NSURLSession,
+            dataTask: NSURLSessionDataTask,
+            willCacheResponse proposedResponse: NSCachedURLResponse,
+            completionHandler: ((NSCachedURLResponse?) -> Void))
+        {
+            if let dataTaskWillCacheResponse = dataTaskWillCacheResponse {
+                completionHandler(dataTaskWillCacheResponse(session, dataTask, proposedResponse))
+            } else if let delegate = self[dataTask] as? Request.DataTaskDelegate {
+                delegate.URLSession(
+                    session,
+                    dataTask: dataTask,
+                    willCacheResponse: proposedResponse,
+                    completionHandler: completionHandler
+                )
+            } else {
+                completionHandler(proposedResponse)
+            }
+        }
+
+        // MARK: - NSURLSessionDownloadDelegate
+
+        // MARK: Override Closures
+
+        /// Overrides default behavior for NSURLSessionDownloadDelegate method `URLSession:downloadTask:didFinishDownloadingToURL:`.
+        public var downloadTaskDidFinishDownloadingToURL: ((NSURLSession, NSURLSessionDownloadTask, NSURL) -> Void)?
+
+        /// Overrides default behavior for NSURLSessionDownloadDelegate method `URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:`.
+        public var downloadTaskDidWriteData: ((NSURLSession, NSURLSessionDownloadTask, Int64, Int64, Int64) -> Void)?
+
+        /// Overrides default behavior for NSURLSessionDownloadDelegate method `URLSession:downloadTask:didResumeAtOffset:expectedTotalBytes:`.
+        public var downloadTaskDidResumeAtOffset: ((NSURLSession, NSURLSessionDownloadTask, Int64, Int64) -> Void)?
+
+        // MARK: Delegate Methods
+
+        /**
+            Tells the delegate that a download task has finished downloading.
+
+            - parameter session:      The session containing the download task that finished.
+            - parameter downloadTask: The download task that finished.
+            - parameter location:     A file URL for the temporary file. Because the file is temporary, you must either 
+                                      open the file for reading or move it to a permanent location in your app’s sandbox 
+                                      container directory before returning from this delegate method.
+        */
+        public func URLSession(
+            session: NSURLSession,
+            downloadTask: NSURLSessionDownloadTask,
+            didFinishDownloadingToURL location: NSURL)
+        {
+            if let downloadTaskDidFinishDownloadingToURL = downloadTaskDidFinishDownloadingToURL {
+                downloadTaskDidFinishDownloadingToURL(session, downloadTask, location)
+            } else if let delegate = self[downloadTask] as? Request.DownloadTaskDelegate {
+                delegate.URLSession(session, downloadTask: downloadTask, didFinishDownloadingToURL: location)
+            }
+        }
+
+        /**
+            Periodically informs the delegate about the download’s progress.
+
+            - parameter session:                   The session containing the download task.
+            - parameter downloadTask:              The download task.
+            - parameter bytesWritten:              The number of bytes transferred since the last time this delegate 
+                                                   method was called.
+            - parameter totalBytesWritten:         The total number of bytes transferred so far.
+            - parameter totalBytesExpectedToWrite: The expected length of the file, as provided by the Content-Length 
+                                                   header. If this header was not provided, the value is 
+                                                   `NSURLSessionTransferSizeUnknown`.
+        */
+        public func URLSession(
+            session: NSURLSession,
+            downloadTask: NSURLSessionDownloadTask,
+            didWriteData bytesWritten: Int64,
+            totalBytesWritten: Int64,
+            totalBytesExpectedToWrite: Int64)
+        {
+            if let downloadTaskDidWriteData = downloadTaskDidWriteData {
+                downloadTaskDidWriteData(session, downloadTask, bytesWritten, totalBytesWritten, totalBytesExpectedToWrite)
+            } else if let delegate = self[downloadTask] as? Request.DownloadTaskDelegate {
+                delegate.URLSession(
+                    session,
+                    downloadTask: downloadTask,
+                    didWriteData: bytesWritten,
+                    totalBytesWritten: totalBytesWritten,
+                    totalBytesExpectedToWrite: totalBytesExpectedToWrite
+                )
+            }
+        }
+
+        /**
+            Tells the delegate that the download task has resumed downloading.
+
+            - parameter session:            The session containing the download task that finished.
+            - parameter downloadTask:       The download task that resumed. See explanation in the discussion.
+            - parameter fileOffset:         If the file's cache policy or last modified date prevents reuse of the 
+                                            existing content, then this value is zero. Otherwise, this value is an 
+                                            integer representing the number of bytes on disk that do not need to be 
+                                            retrieved again.
+            - parameter expectedTotalBytes: The expected length of the file, as provided by the Content-Length header. 
+                                            If this header was not provided, the value is NSURLSessionTransferSizeUnknown.
+        */
+        public func URLSession(
+            session: NSURLSession,
+            downloadTask: NSURLSessionDownloadTask,
+            didResumeAtOffset fileOffset: Int64,
+            expectedTotalBytes: Int64)
+        {
+            if let downloadTaskDidResumeAtOffset = downloadTaskDidResumeAtOffset {
+                downloadTaskDidResumeAtOffset(session, downloadTask, fileOffset, expectedTotalBytes)
+            } else if let delegate = self[downloadTask] as? Request.DownloadTaskDelegate {
+                delegate.URLSession(
+                    session,
+                    downloadTask: downloadTask,
+                    didResumeAtOffset: fileOffset,
+                    expectedTotalBytes: expectedTotalBytes
+                )
+            }
+        }
+
+        // MARK: - NSURLSessionStreamDelegate
+
+        var _streamTaskReadClosed: Any?
+        var _streamTaskWriteClosed: Any?
+        var _streamTaskBetterRouteDiscovered: Any?
+        var _streamTaskDidBecomeInputStream: Any?
+
+        // MARK: - NSObject
+
+        public override func respondsToSelector(selector: Selector) -> Bool {
+            switch selector {
+            case "URLSession:didBecomeInvalidWithError:":
+                return sessionDidBecomeInvalidWithError != nil
+            case "URLSession:didReceiveChallenge:completionHandler:":
+                return sessionDidReceiveChallenge != nil
+            case "URLSessionDidFinishEventsForBackgroundURLSession:":
+                return sessionDidFinishEventsForBackgroundURLSession != nil
+            case "URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:":
+                return taskWillPerformHTTPRedirection != nil
+            case "URLSession:dataTask:didReceiveResponse:completionHandler:":
+                return dataTaskDidReceiveResponse != nil
+            default:
+                return self.dynamicType.instancesRespondToSelector(selector)
+            }
+        }
+    }
+}

+ 669 - 0
Pods/Alamofire/Source/MultipartFormData.swift

@@ -0,0 +1,669 @@
+// MultipartFormData.swift
+//
+// Copyright (c) 2014–2016 Alamofire Software Foundation (http://alamofire.org/)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+import Foundation
+
+#if os(iOS) || os(watchOS) || os(tvOS)
+import MobileCoreServices
+#elseif os(OSX)
+import CoreServices
+#endif
+
+/**
+    Constructs `multipart/form-data` for uploads within an HTTP or HTTPS body. There are currently two ways to encode 
+    multipart form data. The first way is to encode the data directly in memory. This is very efficient, but can lead 
+    to memory issues if the dataset is too large. The second way is designed for larger datasets and will write all the 
+    data to a single file on disk with all the proper boundary segmentation. The second approach MUST be used for 
+    larger datasets such as video content, otherwise your app may run out of memory when trying to encode the dataset.
+
+    For more information on `multipart/form-data` in general, please refer to the RFC-2388 and RFC-2045 specs as well
+    and the w3 form documentation.
+
+    - https://www.ietf.org/rfc/rfc2388.txt
+    - https://www.ietf.org/rfc/rfc2045.txt
+    - https://www.w3.org/TR/html401/interact/forms.html#h-17.13
+*/
+public class MultipartFormData {
+
+    // MARK: - Helper Types
+
+    struct EncodingCharacters {
+        static let CRLF = "\r\n"
+    }
+
+    struct BoundaryGenerator {
+        enum BoundaryType {
+            case Initial, Encapsulated, Final
+        }
+
+        static func randomBoundary() -> String {
+            return String(format: "alamofire.boundary.%08x%08x", arc4random(), arc4random())
+        }
+
+        static func boundaryData(boundaryType boundaryType: BoundaryType, boundary: String) -> NSData {
+            let boundaryText: String
+
+            switch boundaryType {
+            case .Initial:
+                boundaryText = "--\(boundary)\(EncodingCharacters.CRLF)"
+            case .Encapsulated:
+                boundaryText = "\(EncodingCharacters.CRLF)--\(boundary)\(EncodingCharacters.CRLF)"
+            case .Final:
+                boundaryText = "\(EncodingCharacters.CRLF)--\(boundary)--\(EncodingCharacters.CRLF)"
+            }
+
+            return boundaryText.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
+        }
+    }
+
+    class BodyPart {
+        let headers: [String: String]
+        let bodyStream: NSInputStream
+        let bodyContentLength: UInt64
+        var hasInitialBoundary = false
+        var hasFinalBoundary = false
+
+        init(headers: [String: String], bodyStream: NSInputStream, bodyContentLength: UInt64) {
+            self.headers = headers
+            self.bodyStream = bodyStream
+            self.bodyContentLength = bodyContentLength
+        }
+    }
+
+    // MARK: - Properties
+
+    /// The `Content-Type` header value containing the boundary used to generate the `multipart/form-data`.
+    public var contentType: String { return "multipart/form-data; boundary=\(boundary)" }
+
+    /// The content length of all body parts used to generate the `multipart/form-data` not including the boundaries.
+    public var contentLength: UInt64 { return bodyParts.reduce(0) { $0 + $1.bodyContentLength } }
+
+    /// The boundary used to separate the body parts in the encoded form data.
+    public let boundary: String
+
+    private var bodyParts: [BodyPart]
+    private var bodyPartError: NSError?
+    private let streamBufferSize: Int
+
+    // MARK: - Lifecycle
+
+    /**
+        Creates a multipart form data object.
+
+        - returns: The multipart form data object.
+    */
+    public init() {
+        self.boundary = BoundaryGenerator.randomBoundary()
+        self.bodyParts = []
+
+        /**
+         *  The optimal read/write buffer size in bytes for input and output streams is 1024 (1KB). For more 
+         *  information, please refer to the following article:
+         *    - https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Streams/Articles/ReadingInputStreams.html
+         */
+
+        self.streamBufferSize = 1024
+    }
+
+    // MARK: - Body Parts
+
+    /**
+        Creates a body part from the data and appends it to the multipart form data object.
+
+        The body part data will be encoded using the following format:
+
+        - `Content-Disposition: form-data; name=#{name}` (HTTP Header)
+        - Encoded data
+        - Multipart form boundary
+
+        - parameter data: The data to encode into the multipart form data.
+        - parameter name: The name to associate with the data in the `Content-Disposition` HTTP header.
+    */
+    public func appendBodyPart(data data: NSData, name: String) {
+        let headers = contentHeaders(name: name)
+        let stream = NSInputStream(data: data)
+        let length = UInt64(data.length)
+
+        appendBodyPart(stream: stream, length: length, headers: headers)
+    }
+
+    /**
+        Creates a body part from the data and appends it to the multipart form data object.
+
+        The body part data will be encoded using the following format:
+
+        - `Content-Disposition: form-data; name=#{name}` (HTTP Header)
+        - `Content-Type: #{generated mimeType}` (HTTP Header)
+        - Encoded data
+        - Multipart form boundary
+
+        - parameter data:     The data to encode into the multipart form data.
+        - parameter name:     The name to associate with the data in the `Content-Disposition` HTTP header.
+        - parameter mimeType: The MIME type to associate with the data content type in the `Content-Type` HTTP header.
+    */
+    public func appendBodyPart(data data: NSData, name: String, mimeType: String) {
+        let headers = contentHeaders(name: name, mimeType: mimeType)
+        let stream = NSInputStream(data: data)
+        let length = UInt64(data.length)
+
+        appendBodyPart(stream: stream, length: length, headers: headers)
+    }
+
+    /**
+        Creates a body part from the data and appends it to the multipart form data object.
+
+        The body part data will be encoded using the following format:
+
+        - `Content-Disposition: form-data; name=#{name}; filename=#{filename}` (HTTP Header)
+        - `Content-Type: #{mimeType}` (HTTP Header)
+        - Encoded file data
+        - Multipart form boundary
+
+        - parameter data:     The data to encode into the multipart form data.
+        - parameter name:     The name to associate with the data in the `Content-Disposition` HTTP header.
+        - parameter fileName: The filename to associate with the data in the `Content-Disposition` HTTP header.
+        - parameter mimeType: The MIME type to associate with the data in the `Content-Type` HTTP header.
+    */
+    public func appendBodyPart(data data: NSData, name: String, fileName: String, mimeType: String) {
+        let headers = contentHeaders(name: name, fileName: fileName, mimeType: mimeType)
+        let stream = NSInputStream(data: data)
+        let length = UInt64(data.length)
+
+        appendBodyPart(stream: stream, length: length, headers: headers)
+    }
+
+    /**
+        Creates a body part from the file and appends it to the multipart form data object.
+
+        The body part data will be encoded using the following format:
+
+        - `Content-Disposition: form-data; name=#{name}; filename=#{generated filename}` (HTTP Header)
+        - `Content-Type: #{generated mimeType}` (HTTP Header)
+        - Encoded file data
+        - Multipart form boundary
+
+        The filename in the `Content-Disposition` HTTP header is generated from the last path component of the
+        `fileURL`. The `Content-Type` HTTP header MIME type is generated by mapping the `fileURL` extension to the
+        system associated MIME type.
+
+        - parameter fileURL: The URL of the file whose content will be encoded into the multipart form data.
+        - parameter name:    The name to associate with the file content in the `Content-Disposition` HTTP header.
+    */
+    public func appendBodyPart(fileURL fileURL: NSURL, name: String) {
+        if let
+            fileName = fileURL.lastPathComponent,
+            pathExtension = fileURL.pathExtension
+        {
+            let mimeType = mimeTypeForPathExtension(pathExtension)
+            appendBodyPart(fileURL: fileURL, name: name, fileName: fileName, mimeType: mimeType)
+        } else {
+            let failureReason = "Failed to extract the fileName of the provided URL: \(fileURL)"
+            setBodyPartError(Error.errorWithCode(NSURLErrorBadURL, failureReason: failureReason))
+        }
+    }
+
+    /**
+        Creates a body part from the file and appends it to the multipart form data object.
+
+        The body part data will be encoded using the following format:
+
+        - Content-Disposition: form-data; name=#{name}; filename=#{filename} (HTTP Header)
+        - Content-Type: #{mimeType} (HTTP Header)
+        - Encoded file data
+        - Multipart form boundary
+
+        - parameter fileURL:  The URL of the file whose content will be encoded into the multipart form data.
+        - parameter name:     The name to associate with the file content in the `Content-Disposition` HTTP header.
+        - parameter fileName: The filename to associate with the file content in the `Content-Disposition` HTTP header.
+        - parameter mimeType: The MIME type to associate with the file content in the `Content-Type` HTTP header.
+    */
+    public func appendBodyPart(fileURL fileURL: NSURL, name: String, fileName: String, mimeType: String) {
+        let headers = contentHeaders(name: name, fileName: fileName, mimeType: mimeType)
+
+        //============================================================
+        //                 Check 1 - is file URL?
+        //============================================================
+
+        guard fileURL.fileURL else {
+            let failureReason = "The file URL does not point to a file URL: \(fileURL)"
+            let error = Error.errorWithCode(NSURLErrorBadURL, failureReason: failureReason)
+            setBodyPartError(error)
+            return
+        }
+
+        //============================================================
+        //              Check 2 - is file URL reachable?
+        //============================================================
+
+        var isReachable = true
+
+        if #available(OSX 10.10, *) {
+            isReachable = fileURL.checkPromisedItemIsReachableAndReturnError(nil)
+        }
+
+        guard isReachable else {
+            let error = Error.errorWithCode(NSURLErrorBadURL, failureReason: "The file URL is not reachable: \(fileURL)")
+            setBodyPartError(error)
+            return
+        }
+
+        //============================================================
+        //            Check 3 - is file URL a directory?
+        //============================================================
+
+        var isDirectory: ObjCBool = false
+
+        guard let
+            path = fileURL.path
+            where NSFileManager.defaultManager().fileExistsAtPath(path, isDirectory: &isDirectory) && !isDirectory else
+        {
+            let failureReason = "The file URL is a directory, not a file: \(fileURL)"
+            let error = Error.errorWithCode(NSURLErrorBadURL, failureReason: failureReason)
+            setBodyPartError(error)
+            return
+        }
+
+        //============================================================
+        //          Check 4 - can the file size be extracted?
+        //============================================================
+
+        var bodyContentLength: UInt64?
+
+        do {
+            if let
+                path = fileURL.path,
+                fileSize = try NSFileManager.defaultManager().attributesOfItemAtPath(path)[NSFileSize] as? NSNumber
+            {
+                bodyContentLength = fileSize.unsignedLongLongValue
+            }
+        } catch {
+            // No-op
+        }
+
+        guard let length = bodyContentLength else {
+            let failureReason = "Could not fetch attributes from the file URL: \(fileURL)"
+            let error = Error.errorWithCode(NSURLErrorBadURL, failureReason: failureReason)
+            setBodyPartError(error)
+            return
+        }
+
+        //============================================================
+        //       Check 5 - can a stream be created from file URL?
+        //============================================================
+
+        guard let stream = NSInputStream(URL: fileURL) else {
+            let failureReason = "Failed to create an input stream from the file URL: \(fileURL)"
+            let error = Error.errorWithCode(NSURLErrorCannotOpenFile, failureReason: failureReason)
+            setBodyPartError(error)
+            return
+        }
+
+        appendBodyPart(stream: stream, length: length, headers: headers)
+    }
+
+    /**
+        Creates a body part from the stream and appends it to the multipart form data object.
+
+        The body part data will be encoded using the following format:
+
+        - `Content-Disposition: form-data; name=#{name}; filename=#{filename}` (HTTP Header)
+        - `Content-Type: #{mimeType}` (HTTP Header)
+        - Encoded stream data
+        - Multipart form boundary
+
+        - parameter stream:   The input stream to encode in the multipart form data.
+        - parameter length:   The content length of the stream.
+        - parameter name:     The name to associate with the stream content in the `Content-Disposition` HTTP header.
+        - parameter fileName: The filename to associate with the stream content in the `Content-Disposition` HTTP header.
+        - parameter mimeType: The MIME type to associate with the stream content in the `Content-Type` HTTP header.
+    */
+    public func appendBodyPart(
+        stream stream: NSInputStream,
+        length: UInt64,
+        name: String,
+        fileName: String,
+        mimeType: String)
+    {
+        let headers = contentHeaders(name: name, fileName: fileName, mimeType: mimeType)
+        appendBodyPart(stream: stream, length: length, headers: headers)
+    }
+
+    /**
+        Creates a body part with the headers, stream and length and appends it to the multipart form data object.
+
+        The body part data will be encoded using the following format:
+
+        - HTTP headers
+        - Encoded stream data
+        - Multipart form boundary
+
+        - parameter stream:  The input stream to encode in the multipart form data.
+        - parameter length:  The content length of the stream.
+        - parameter headers: The HTTP headers for the body part.
+    */
+    public func appendBodyPart(stream stream: NSInputStream, length: UInt64, headers: [String: String]) {
+        let bodyPart = BodyPart(headers: headers, bodyStream: stream, bodyContentLength: length)
+        bodyParts.append(bodyPart)
+    }
+
+    // MARK: - Data Encoding
+
+    /**
+        Encodes all the appended body parts into a single `NSData` object.
+
+        It is important to note that this method will load all the appended body parts into memory all at the same 
+        time. This method should only be used when the encoded data will have a small memory footprint. For large data 
+        cases, please use the `writeEncodedDataToDisk(fileURL:completionHandler:)` method.
+
+        - throws: An `NSError` if encoding encounters an error.
+
+        - returns: The encoded `NSData` if encoding is successful.
+    */
+    public func encode() throws -> NSData {
+        if let bodyPartError = bodyPartError {
+            throw bodyPartError
+        }
+
+        let encoded = NSMutableData()
+
+        bodyParts.first?.hasInitialBoundary = true
+        bodyParts.last?.hasFinalBoundary = true
+
+        for bodyPart in bodyParts {
+            let encodedData = try encodeBodyPart(bodyPart)
+            encoded.appendData(encodedData)
+        }
+
+        return encoded
+    }
+
+    /**
+        Writes the appended body parts into the given file URL.
+
+        This process is facilitated by reading and writing with input and output streams, respectively. Thus,
+        this approach is very memory efficient and should be used for large body part data.
+
+        - parameter fileURL: The file URL to write the multipart form data into.
+
+        - throws: An `NSError` if encoding encounters an error.
+    */
+    public func writeEncodedDataToDisk(fileURL: NSURL) throws {
+        if let bodyPartError = bodyPartError {
+            throw bodyPartError
+        }
+
+        if let path = fileURL.path where NSFileManager.defaultManager().fileExistsAtPath(path) {
+            let failureReason = "A file already exists at the given file URL: \(fileURL)"
+            throw Error.errorWithCode(NSURLErrorBadURL, failureReason: failureReason)
+        } else if !fileURL.fileURL {
+            let failureReason = "The URL does not point to a valid file: \(fileURL)"
+            throw Error.errorWithCode(NSURLErrorBadURL, failureReason: failureReason)
+        }
+
+        let outputStream: NSOutputStream
+
+        if let possibleOutputStream = NSOutputStream(URL: fileURL, append: false) {
+            outputStream = possibleOutputStream
+        } else {
+            let failureReason = "Failed to create an output stream with the given URL: \(fileURL)"
+            throw Error.errorWithCode(NSURLErrorCannotOpenFile, failureReason: failureReason)
+        }
+
+        outputStream.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
+        outputStream.open()
+
+        self.bodyParts.first?.hasInitialBoundary = true
+        self.bodyParts.last?.hasFinalBoundary = true
+
+        for bodyPart in self.bodyParts {
+            try writeBodyPart(bodyPart, toOutputStream: outputStream)
+        }
+
+        outputStream.close()
+        outputStream.removeFromRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
+    }
+
+    // MARK: - Private - Body Part Encoding
+
+    private func encodeBodyPart(bodyPart: BodyPart) throws -> NSData {
+        let encoded = NSMutableData()
+
+        let initialData = bodyPart.hasInitialBoundary ? initialBoundaryData() : encapsulatedBoundaryData()
+        encoded.appendData(initialData)
+
+        let headerData = encodeHeaderDataForBodyPart(bodyPart)
+        encoded.appendData(headerData)
+
+        let bodyStreamData = try encodeBodyStreamDataForBodyPart(bodyPart)
+        encoded.appendData(bodyStreamData)
+
+        if bodyPart.hasFinalBoundary {
+            encoded.appendData(finalBoundaryData())
+        }
+
+        return encoded
+    }
+
+    private func encodeHeaderDataForBodyPart(bodyPart: BodyPart) -> NSData {
+        var headerText = ""
+
+        for (key, value) in bodyPart.headers {
+            headerText += "\(key): \(value)\(EncodingCharacters.CRLF)"
+        }
+        headerText += EncodingCharacters.CRLF
+
+        return headerText.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
+    }
+
+    private func encodeBodyStreamDataForBodyPart(bodyPart: BodyPart) throws -> NSData {
+        let inputStream = bodyPart.bodyStream
+        inputStream.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
+        inputStream.open()
+
+        var error: NSError?
+        let encoded = NSMutableData()
+
+        while inputStream.hasBytesAvailable {
+            var buffer = [UInt8](count: streamBufferSize, repeatedValue: 0)
+            let bytesRead = inputStream.read(&buffer, maxLength: streamBufferSize)
+
+            if inputStream.streamError != nil {
+                error = inputStream.streamError
+                break
+            }
+
+            if bytesRead > 0 {
+                encoded.appendBytes(buffer, length: bytesRead)
+            } else if bytesRead < 0 {
+                let failureReason = "Failed to read from input stream: \(inputStream)"
+                error = Error.errorWithCode(.InputStreamReadFailed, failureReason: failureReason)
+                break
+            } else {
+                break
+            }
+        }
+
+        inputStream.close()
+        inputStream.removeFromRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
+
+        if let error = error {
+            throw error
+        }
+
+        return encoded
+    }
+
+    // MARK: - Private - Writing Body Part to Output Stream
+
+    private func writeBodyPart(bodyPart: BodyPart, toOutputStream outputStream: NSOutputStream) throws {
+        try writeInitialBoundaryDataForBodyPart(bodyPart, toOutputStream: outputStream)
+        try writeHeaderDataForBodyPart(bodyPart, toOutputStream: outputStream)
+        try writeBodyStreamForBodyPart(bodyPart, toOutputStream: outputStream)
+        try writeFinalBoundaryDataForBodyPart(bodyPart, toOutputStream: outputStream)
+    }
+
+    private func writeInitialBoundaryDataForBodyPart(
+        bodyPart: BodyPart,
+        toOutputStream outputStream: NSOutputStream)
+        throws
+    {
+        let initialData = bodyPart.hasInitialBoundary ? initialBoundaryData() : encapsulatedBoundaryData()
+        return try writeData(initialData, toOutputStream: outputStream)
+    }
+
+    private func writeHeaderDataForBodyPart(bodyPart: BodyPart, toOutputStream outputStream: NSOutputStream) throws {
+        let headerData = encodeHeaderDataForBodyPart(bodyPart)
+        return try writeData(headerData, toOutputStream: outputStream)
+    }
+
+    private func writeBodyStreamForBodyPart(bodyPart: BodyPart, toOutputStream outputStream: NSOutputStream) throws {
+        let inputStream = bodyPart.bodyStream
+        inputStream.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
+        inputStream.open()
+
+        while inputStream.hasBytesAvailable {
+            var buffer = [UInt8](count: streamBufferSize, repeatedValue: 0)
+            let bytesRead = inputStream.read(&buffer, maxLength: streamBufferSize)
+
+            if let streamError = inputStream.streamError {
+                throw streamError
+            }
+
+            if bytesRead > 0 {
+                if buffer.count != bytesRead {
+                    buffer = Array(buffer[0..<bytesRead])
+                }
+
+                try writeBuffer(&buffer, toOutputStream: outputStream)
+            } else if bytesRead < 0 {
+                let failureReason = "Failed to read from input stream: \(inputStream)"
+                throw Error.errorWithCode(.InputStreamReadFailed, failureReason: failureReason)
+            } else {
+                break
+            }
+        }
+
+        inputStream.close()
+        inputStream.removeFromRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
+    }
+
+    private func writeFinalBoundaryDataForBodyPart(
+        bodyPart: BodyPart,
+        toOutputStream outputStream: NSOutputStream)
+        throws
+    {
+        if bodyPart.hasFinalBoundary {
+            return try writeData(finalBoundaryData(), toOutputStream: outputStream)
+        }
+    }
+
+    // MARK: - Private - Writing Buffered Data to Output Stream
+
+    private func writeData(data: NSData, toOutputStream outputStream: NSOutputStream) throws {
+        var buffer = [UInt8](count: data.length, repeatedValue: 0)
+        data.getBytes(&buffer, length: data.length)
+
+        return try writeBuffer(&buffer, toOutputStream: outputStream)
+    }
+
+    private func writeBuffer(inout buffer: [UInt8], toOutputStream outputStream: NSOutputStream) throws {
+        var bytesToWrite = buffer.count
+
+        while bytesToWrite > 0 {
+            if outputStream.hasSpaceAvailable {
+                let bytesWritten = outputStream.write(buffer, maxLength: bytesToWrite)
+
+                if let streamError = outputStream.streamError {
+                    throw streamError
+                }
+
+                if bytesWritten < 0 {
+                    let failureReason = "Failed to write to output stream: \(outputStream)"
+                    throw Error.errorWithCode(.OutputStreamWriteFailed, failureReason: failureReason)
+                }
+
+                bytesToWrite -= bytesWritten
+
+                if bytesToWrite > 0 {
+                    buffer = Array(buffer[bytesWritten..<buffer.count])
+                }
+            } else if let streamError = outputStream.streamError {
+                throw streamError
+            }
+        }
+    }
+
+    // MARK: - Private - Mime Type
+
+    private func mimeTypeForPathExtension(pathExtension: String) -> String {
+        if let
+            id = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, pathExtension, nil)?.takeRetainedValue(),
+            contentType = UTTypeCopyPreferredTagWithClass(id, kUTTagClassMIMEType)?.takeRetainedValue()
+        {
+            return contentType as String
+        }
+
+        return "application/octet-stream"
+    }
+
+    // MARK: - Private - Content Headers
+
+    private func contentHeaders(name name: String) -> [String: String] {
+        return ["Content-Disposition": "form-data; name=\"\(name)\""]
+    }
+
+    private func contentHeaders(name name: String, mimeType: String) -> [String: String] {
+        return [
+            "Content-Disposition": "form-data; name=\"\(name)\"",
+            "Content-Type": "\(mimeType)"
+        ]
+    }
+
+    private func contentHeaders(name name: String, fileName: String, mimeType: String) -> [String: String] {
+        return [
+            "Content-Disposition": "form-data; name=\"\(name)\"; filename=\"\(fileName)\"",
+            "Content-Type": "\(mimeType)"
+        ]
+    }
+
+    // MARK: - Private - Boundary Encoding
+
+    private func initialBoundaryData() -> NSData {
+        return BoundaryGenerator.boundaryData(boundaryType: .Initial, boundary: boundary)
+    }
+
+    private func encapsulatedBoundaryData() -> NSData {
+        return BoundaryGenerator.boundaryData(boundaryType: .Encapsulated, boundary: boundary)
+    }
+
+    private func finalBoundaryData() -> NSData {
+        return BoundaryGenerator.boundaryData(boundaryType: .Final, boundary: boundary)
+    }
+
+    // MARK: - Private - Errors
+
+    private func setBodyPartError(error: NSError) {
+        if bodyPartError == nil {
+            bodyPartError = error
+        }
+    }
+}

+ 239 - 0
Pods/Alamofire/Source/NetworkReachabilityManager.swift

@@ -0,0 +1,239 @@
+// NetworkReachabilityManager.swift
+//
+// Copyright (c) 2014–2016 Alamofire Software Foundation (http://alamofire.org/)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#if !os(watchOS)
+
+import Foundation
+import SystemConfiguration
+
+/**
+    The `NetworkReachabilityManager` class listens for reachability changes of hosts and addresses for both WWAN and
+    WiFi network interfaces.
+
+    Reachability can be used to determine background information about why a network operation failed, or to retry
+    network requests when a connection is established. It should not be used to prevent a user from initiating a network
+    request, as it's possible that an initial request may be required to establish reachability.
+*/
+public class NetworkReachabilityManager {
+    /**
+        Defines the various states of network reachability.
+
+        - Unknown:         It is unknown whether the network is reachable.
+        - NotReachable:    The network is not reachable.
+        - ReachableOnWWAN: The network is reachable over the WWAN connection.
+        - ReachableOnWiFi: The network is reachable over the WiFi connection.
+    */
+    public enum NetworkReachabilityStatus {
+        case Unknown
+        case NotReachable
+        case Reachable(ConnectionType)
+    }
+
+    /**
+        Defines the various connection types detected by reachability flags.
+
+        - EthernetOrWiFi: The connection type is either over Ethernet or WiFi.
+        - WWAN:           The connection type is a WWAN connection.
+    */
+    public enum ConnectionType {
+        case EthernetOrWiFi
+        case WWAN
+    }
+
+    /// A closure executed when the network reachability status changes. The closure takes a single argument: the 
+    /// network reachability status.
+    public typealias Listener = NetworkReachabilityStatus -> Void
+
+    // MARK: - Properties
+
+    /// Whether the network is currently reachable.
+    public var isReachable: Bool { return isReachableOnWWAN || isReachableOnEthernetOrWiFi }
+
+    /// Whether the network is currently reachable over the WWAN interface.
+    public var isReachableOnWWAN: Bool { return networkReachabilityStatus == .Reachable(.WWAN) }
+
+    /// Whether the network is currently reachable over Ethernet or WiFi interface.
+    public var isReachableOnEthernetOrWiFi: Bool { return networkReachabilityStatus == .Reachable(.EthernetOrWiFi) }
+
+    /// The current network reachability status.
+    public var networkReachabilityStatus: NetworkReachabilityStatus {
+        guard let flags = self.flags else { return .Unknown }
+        return networkReachabilityStatusForFlags(flags)
+    }
+
+    /// The dispatch queue to execute the `listener` closure on.
+    public var listenerQueue: dispatch_queue_t = dispatch_get_main_queue()
+
+    /// A closure executed when the network reachability status changes.
+    public var listener: Listener?
+
+    private var flags: SCNetworkReachabilityFlags? {
+        var flags = SCNetworkReachabilityFlags()
+
+        if SCNetworkReachabilityGetFlags(reachability, &flags) {
+            return flags
+        }
+
+        return nil
+    }
+
+    private let reachability: SCNetworkReachability
+    private var previousFlags: SCNetworkReachabilityFlags
+
+    // MARK: - Initialization
+
+    /**
+        Creates a `NetworkReachabilityManager` instance with the specified host.
+
+        - parameter host: The host used to evaluate network reachability.
+
+        - returns: The new `NetworkReachabilityManager` instance.
+    */
+    public convenience init?(host: String) {
+        guard let reachability = SCNetworkReachabilityCreateWithName(nil, host) else { return nil }
+        self.init(reachability: reachability)
+    }
+
+    /**
+        Creates a `NetworkReachabilityManager` instance with the default socket address (`sockaddr_in6`).
+
+        - returns: The new `NetworkReachabilityManager` instance.
+     */
+    public convenience init?() {
+        var address = sockaddr_in6()
+        address.sin6_len = UInt8(sizeofValue(address))
+        address.sin6_family = sa_family_t(AF_INET6)
+
+        guard let reachability = withUnsafePointer(&address, {
+            SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0))
+        }) else { return nil }
+
+        self.init(reachability: reachability)
+    }
+
+    private init(reachability: SCNetworkReachability) {
+        self.reachability = reachability
+        self.previousFlags = SCNetworkReachabilityFlags()
+    }
+
+    deinit {
+        stopListening()
+    }
+
+    // MARK: - Listening
+
+    /**
+        Starts listening for changes in network reachability status.
+
+        - returns: `true` if listening was started successfully, `false` otherwise.
+    */
+    public func startListening() -> Bool {
+        var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil)
+        context.info = UnsafeMutablePointer(Unmanaged.passUnretained(self).toOpaque())
+
+        let callbackEnabled = SCNetworkReachabilitySetCallback(
+            reachability,
+            { (_, flags, info) in
+                let reachability = Unmanaged<NetworkReachabilityManager>.fromOpaque(COpaquePointer(info)).takeUnretainedValue()
+                reachability.notifyListener(flags)
+            },
+            &context
+        )
+
+        let queueEnabled = SCNetworkReachabilitySetDispatchQueue(reachability, listenerQueue)
+
+        dispatch_async(listenerQueue) {
+            self.previousFlags = SCNetworkReachabilityFlags()
+            self.notifyListener(self.flags ?? SCNetworkReachabilityFlags())
+        }
+
+        return callbackEnabled && queueEnabled
+    }
+
+    /**
+        Stops listening for changes in network reachability status.
+    */
+    public func stopListening() {
+        SCNetworkReachabilitySetCallback(reachability, nil, nil)
+        SCNetworkReachabilitySetDispatchQueue(reachability, nil)
+    }
+
+    // MARK: - Internal - Listener Notification
+
+    func notifyListener(flags: SCNetworkReachabilityFlags) {
+        guard previousFlags != flags else { return }
+        previousFlags = flags
+
+        listener?(networkReachabilityStatusForFlags(flags))
+    }
+
+    // MARK: - Internal - Network Reachability Status
+
+    func networkReachabilityStatusForFlags(flags: SCNetworkReachabilityFlags) -> NetworkReachabilityStatus {
+        guard flags.contains(.Reachable) else { return .NotReachable }
+
+        var networkStatus: NetworkReachabilityStatus = .NotReachable
+
+        if !flags.contains(.ConnectionRequired) { networkStatus = .Reachable(.EthernetOrWiFi) }
+
+        if flags.contains(.ConnectionOnDemand) || flags.contains(.ConnectionOnTraffic) {
+            if !flags.contains(.InterventionRequired) { networkStatus = .Reachable(.EthernetOrWiFi) }
+        }
+
+        #if os(iOS)
+            if flags.contains(.IsWWAN) { networkStatus = .Reachable(.WWAN) }
+        #endif
+
+        return networkStatus
+    }
+}
+
+// MARK: -
+
+extension NetworkReachabilityManager.NetworkReachabilityStatus: Equatable {}
+
+/**
+    Returns whether the two network reachability status values are equal.
+
+    - parameter lhs: The left-hand side value to compare.
+    - parameter rhs: The right-hand side value to compare.
+
+    - returns: `true` if the two values are equal, `false` otherwise.
+*/
+public func ==(
+    lhs: NetworkReachabilityManager.NetworkReachabilityStatus,
+    rhs: NetworkReachabilityManager.NetworkReachabilityStatus)
+    -> Bool
+{
+    switch (lhs, rhs) {
+    case (.Unknown, .Unknown):
+        return true
+    case (.NotReachable, .NotReachable):
+        return true
+    case let (.Reachable(lhsConnectionType), .Reachable(rhsConnectionType)):
+        return lhsConnectionType == rhsConnectionType
+    default:
+        return false
+    }
+}
+
+#endif

+ 45 - 0
Pods/Alamofire/Source/Notifications.swift

@@ -0,0 +1,45 @@
+// Notifications.swift
+//
+// Copyright (c) 2014–2016 Alamofire Software Foundation (http://alamofire.org/)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+import Foundation
+
+/// Contains all the `NSNotification` names posted by Alamofire with descriptions of each notification's payload.
+public struct Notifications {
+    /// Used as a namespace for all `NSURLSessionTask` related notifications.
+    public struct Task {
+        /// Notification posted when an `NSURLSessionTask` is resumed. The notification `object` contains the resumed
+        /// `NSURLSessionTask`.
+        public static let DidResume = "com.alamofire.notifications.task.didResume"
+
+        /// Notification posted when an `NSURLSessionTask` is suspended. The notification `object` contains the 
+        /// suspended `NSURLSessionTask`.
+        public static let DidSuspend = "com.alamofire.notifications.task.didSuspend"
+
+        /// Notification posted when an `NSURLSessionTask` is cancelled. The notification `object` contains the
+        /// cancelled `NSURLSessionTask`.
+        public static let DidCancel = "com.alamofire.notifications.task.didCancel"
+
+        /// Notification posted when an `NSURLSessionTask` is completed. The notification `object` contains the
+        /// completed `NSURLSessionTask`.
+        public static let DidComplete = "com.alamofire.notifications.task.didComplete"
+    }
+}

+ 259 - 0
Pods/Alamofire/Source/ParameterEncoding.swift

@@ -0,0 +1,259 @@
+// ParameterEncoding.swift
+//
+// Copyright (c) 2014–2016 Alamofire Software Foundation (http://alamofire.org/)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+import Foundation
+
+/**
+    HTTP method definitions.
+
+    See https://tools.ietf.org/html/rfc7231#section-4.3
+*/
+public enum Method: String {
+    case OPTIONS, GET, HEAD, POST, PUT, PATCH, DELETE, TRACE, CONNECT
+}
+
+// MARK: ParameterEncoding
+
+/**
+    Used to specify the way in which a set of parameters are applied to a URL request.
+
+    - `URL`:             Creates a query string to be set as or appended to any existing URL query for `GET`, `HEAD`, 
+                         and `DELETE` requests, or set as the body for requests with any other HTTP method. The 
+                         `Content-Type` HTTP header field of an encoded request with HTTP body is set to
+                         `application/x-www-form-urlencoded; charset=utf-8`. Since there is no published specification
+                         for how to encode collection types, the convention of appending `[]` to the key for array
+                         values (`foo[]=1&foo[]=2`), and appending the key surrounded by square brackets for nested
+                         dictionary values (`foo[bar]=baz`).
+
+    - `URLEncodedInURL`: Creates query string to be set as or appended to any existing URL query. Uses the same
+                         implementation as the `.URL` case, but always applies the encoded result to the URL.
+
+    - `JSON`:            Uses `NSJSONSerialization` to create a JSON representation of the parameters object, which is 
+                         set as the body of the request. The `Content-Type` HTTP header field of an encoded request is 
+                         set to `application/json`.
+
+    - `PropertyList`:    Uses `NSPropertyListSerialization` to create a plist representation of the parameters object,
+                         according to the associated format and write options values, which is set as the body of the
+                         request. The `Content-Type` HTTP header field of an encoded request is set to
+                         `application/x-plist`.
+
+    - `Custom`:          Uses the associated closure value to construct a new request given an existing request and
+                         parameters.
+*/
+public enum ParameterEncoding {
+    case URL
+    case URLEncodedInURL
+    case JSON
+    case PropertyList(NSPropertyListFormat, NSPropertyListWriteOptions)
+    case Custom((URLRequestConvertible, [String: AnyObject]?) -> (NSMutableURLRequest, NSError?))
+
+    /**
+        Creates a URL request by encoding parameters and applying them onto an existing request.
+
+        - parameter URLRequest: The request to have parameters applied.
+        - parameter parameters: The parameters to apply.
+
+        - returns: A tuple containing the constructed request and the error that occurred during parameter encoding, 
+                   if any.
+    */
+    public func encode(
+        URLRequest: URLRequestConvertible,
+        parameters: [String: AnyObject]?)
+        -> (NSMutableURLRequest, NSError?)
+    {
+        var mutableURLRequest = URLRequest.URLRequest
+
+        guard let parameters = parameters else { return (mutableURLRequest, nil) }
+
+        var encodingError: NSError? = nil
+
+        switch self {
+        case .URL, .URLEncodedInURL:
+            func query(parameters: [String: AnyObject]) -> String {
+                var components: [(String, String)] = []
+
+                for key in parameters.keys.sort(<) {
+                    let value = parameters[key]!
+                    components += queryComponents(key, value)
+                }
+
+                return (components.map { "\($0)=\($1)" } as [String]).joinWithSeparator("&")
+            }
+
+            func encodesParametersInURL(method: Method) -> Bool {
+                switch self {
+                case .URLEncodedInURL:
+                    return true
+                default:
+                    break
+                }
+
+                switch method {
+                case .GET, .HEAD, .DELETE:
+                    return true
+                default:
+                    return false
+                }
+            }
+
+            if let method = Method(rawValue: mutableURLRequest.HTTPMethod) where encodesParametersInURL(method) {
+                if let
+                    URLComponents = NSURLComponents(URL: mutableURLRequest.URL!, resolvingAgainstBaseURL: false)
+                    where !parameters.isEmpty
+                {
+                    let percentEncodedQuery = (URLComponents.percentEncodedQuery.map { $0 + "&" } ?? "") + query(parameters)
+                    URLComponents.percentEncodedQuery = percentEncodedQuery
+                    mutableURLRequest.URL = URLComponents.URL
+                }
+            } else {
+                if mutableURLRequest.valueForHTTPHeaderField("Content-Type") == nil {
+                    mutableURLRequest.setValue(
+                        "application/x-www-form-urlencoded; charset=utf-8",
+                        forHTTPHeaderField: "Content-Type"
+                    )
+                }
+
+                mutableURLRequest.HTTPBody = query(parameters).dataUsingEncoding(
+                    NSUTF8StringEncoding,
+                    allowLossyConversion: false
+                )
+            }
+        case .JSON:
+            do {
+                let options = NSJSONWritingOptions()
+                let data = try NSJSONSerialization.dataWithJSONObject(parameters, options: options)
+
+                if mutableURLRequest.valueForHTTPHeaderField("Content-Type") == nil {
+                    mutableURLRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
+                }
+
+                mutableURLRequest.HTTPBody = data
+            } catch {
+                encodingError = error as NSError
+            }
+        case .PropertyList(let format, let options):
+            do {
+                let data = try NSPropertyListSerialization.dataWithPropertyList(
+                    parameters,
+                    format: format,
+                    options: options
+                )
+
+                if mutableURLRequest.valueForHTTPHeaderField("Content-Type") == nil {
+                    mutableURLRequest.setValue("application/x-plist", forHTTPHeaderField: "Content-Type")
+                }
+
+                mutableURLRequest.HTTPBody = data
+            } catch {
+                encodingError = error as NSError
+            }
+        case .Custom(let closure):
+            (mutableURLRequest, encodingError) = closure(mutableURLRequest, parameters)
+        }
+
+        return (mutableURLRequest, encodingError)
+    }
+
+    /**
+        Creates percent-escaped, URL encoded query string components from the given key-value pair using recursion.
+
+        - parameter key:   The key of the query component.
+        - parameter value: The value of the query component.
+
+        - returns: The percent-escaped, URL encoded query string components.
+    */
+    public func queryComponents(key: String, _ value: AnyObject) -> [(String, String)] {
+        var components: [(String, String)] = []
+
+        if let dictionary = value as? [String: AnyObject] {
+            for (nestedKey, value) in dictionary {
+                components += queryComponents("\(key)[\(nestedKey)]", value)
+            }
+        } else if let array = value as? [AnyObject] {
+            for value in array {
+                components += queryComponents("\(key)[]", value)
+            }
+        } else {
+            components.append((escape(key), escape("\(value)")))
+        }
+
+        return components
+    }
+
+    /**
+        Returns a percent-escaped string following RFC 3986 for a query string key or value.
+
+        RFC 3986 states that the following characters are "reserved" characters.
+
+        - General Delimiters: ":", "#", "[", "]", "@", "?", "/"
+        - Sub-Delimiters: "!", "$", "&", "'", "(", ")", "*", "+", ",", ";", "="
+
+        In RFC 3986 - Section 3.4, it states that the "?" and "/" characters should not be escaped to allow
+        query strings to include a URL. Therefore, all "reserved" characters with the exception of "?" and "/"
+        should be percent-escaped in the query string.
+
+        - parameter string: The string to be percent-escaped.
+
+        - returns: The percent-escaped string.
+    */
+    public func escape(string: String) -> String {
+        let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4
+        let subDelimitersToEncode = "!$&'()*+,;="
+
+        let allowedCharacterSet = NSCharacterSet.URLQueryAllowedCharacterSet().mutableCopy() as! NSMutableCharacterSet
+        allowedCharacterSet.removeCharactersInString(generalDelimitersToEncode + subDelimitersToEncode)
+
+        var escaped = ""
+
+        //==========================================================================================================
+        //
+        //  Batching is required for escaping due to an internal bug in iOS 8.1 and 8.2. Encoding more than a few
+        //  hundred Chinense characters causes various malloc error crashes. To avoid this issue until iOS 8 is no
+        //  longer supported, batching MUST be used for encoding. This introduces roughly a 20% overhead. For more
+        //  info, please refer to:
+        //
+        //      - https://github.com/Alamofire/Alamofire/issues/206
+        //
+        //==========================================================================================================
+
+        if #available(iOS 8.3, OSX 10.10, *) {
+            escaped = string.stringByAddingPercentEncodingWithAllowedCharacters(allowedCharacterSet) ?? string
+        } else {
+            let batchSize = 50
+            var index = string.startIndex
+
+            while index != string.endIndex {
+                let startIndex = index
+                let endIndex = index.advancedBy(batchSize, limit: string.endIndex)
+                let range = Range(start: startIndex, end: endIndex)
+
+                let substring = string.substringWithRange(range)
+
+                escaped += substring.stringByAddingPercentEncodingWithAllowedCharacters(allowedCharacterSet) ?? substring
+
+                index = endIndex
+            }
+        }
+
+        return escaped
+    }
+}

+ 552 - 0
Pods/Alamofire/Source/Request.swift

@@ -0,0 +1,552 @@
+// Request.swift
+//
+// Copyright (c) 2014–2016 Alamofire Software Foundation (http://alamofire.org/)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+import Foundation
+
+/**
+    Responsible for sending a request and receiving the response and associated data from the server, as well as 
+    managing its underlying `NSURLSessionTask`.
+*/
+public class Request {
+
+    // MARK: - Properties
+
+    /// The delegate for the underlying task.
+    public let delegate: TaskDelegate
+
+    /// The underlying task.
+    public var task: NSURLSessionTask { return delegate.task }
+
+    /// The session belonging to the underlying task.
+    public let session: NSURLSession
+
+    /// The request sent or to be sent to the server.
+    public var request: NSURLRequest? { return task.originalRequest }
+
+    /// The response received from the server, if any.
+    public var response: NSHTTPURLResponse? { return task.response as? NSHTTPURLResponse }
+
+    /// The progress of the request lifecycle.
+    public var progress: NSProgress { return delegate.progress }
+
+    var startTime: CFAbsoluteTime?
+    var endTime: CFAbsoluteTime?
+
+    // MARK: - Lifecycle
+
+    init(session: NSURLSession, task: NSURLSessionTask) {
+        self.session = session
+
+        switch task {
+        case is NSURLSessionUploadTask:
+            delegate = UploadTaskDelegate(task: task)
+        case is NSURLSessionDataTask:
+            delegate = DataTaskDelegate(task: task)
+        case is NSURLSessionDownloadTask:
+            delegate = DownloadTaskDelegate(task: task)
+        default:
+            delegate = TaskDelegate(task: task)
+        }
+
+        delegate.queue.addOperationWithBlock { self.endTime = CFAbsoluteTimeGetCurrent() }
+    }
+
+    // MARK: - Authentication
+
+    /**
+        Associates an HTTP Basic credential with the request.
+
+        - parameter user:        The user.
+        - parameter password:    The password.
+        - parameter persistence: The URL credential persistence. `.ForSession` by default.
+
+        - returns: The request.
+    */
+    public func authenticate(
+        user user: String,
+        password: String,
+        persistence: NSURLCredentialPersistence = .ForSession)
+        -> Self
+    {
+        let credential = NSURLCredential(user: user, password: password, persistence: persistence)
+
+        return authenticate(usingCredential: credential)
+    }
+
+    /**
+        Associates a specified credential with the request.
+
+        - parameter credential: The credential.
+
+        - returns: The request.
+    */
+    public func authenticate(usingCredential credential: NSURLCredential) -> Self {
+        delegate.credential = credential
+
+        return self
+    }
+
+    // MARK: - Progress
+
+    /**
+        Sets a closure to be called periodically during the lifecycle of the request as data is written to or read 
+        from the server.
+
+        - For uploads, the progress closure returns the bytes written, total bytes written, and total bytes expected 
+          to write.
+        - For downloads and data tasks, the progress closure returns the bytes read, total bytes read, and total bytes 
+          expected to read.
+
+        - parameter closure: The code to be executed periodically during the lifecycle of the request.
+
+        - returns: The request.
+    */
+    public func progress(closure: ((Int64, Int64, Int64) -> Void)? = nil) -> Self {
+        if let uploadDelegate = delegate as? UploadTaskDelegate {
+            uploadDelegate.uploadProgress = closure
+        } else if let dataDelegate = delegate as? DataTaskDelegate {
+            dataDelegate.dataProgress = closure
+        } else if let downloadDelegate = delegate as? DownloadTaskDelegate {
+            downloadDelegate.downloadProgress = closure
+        }
+
+        return self
+    }
+
+    /**
+        Sets a closure to be called periodically during the lifecycle of the request as data is read from the server.
+
+        This closure returns the bytes most recently received from the server, not including data from previous calls. 
+        If this closure is set, data will only be available within this closure, and will not be saved elsewhere. It is 
+        also important to note that the `response` closure will be called with nil `responseData`.
+
+        - parameter closure: The code to be executed periodically during the lifecycle of the request.
+
+        - returns: The request.
+    */
+    public func stream(closure: (NSData -> Void)? = nil) -> Self {
+        if let dataDelegate = delegate as? DataTaskDelegate {
+            dataDelegate.dataStream = closure
+        }
+
+        return self
+    }
+
+    // MARK: - State
+
+    /**
+        Resumes the request.
+    */
+    public func resume() {
+        if startTime == nil { startTime = CFAbsoluteTimeGetCurrent() }
+
+        task.resume()
+        NSNotificationCenter.defaultCenter().postNotificationName(Notifications.Task.DidResume, object: task)
+    }
+
+    /**
+        Suspends the request.
+    */
+    public func suspend() {
+        task.suspend()
+        NSNotificationCenter.defaultCenter().postNotificationName(Notifications.Task.DidSuspend, object: task)
+    }
+
+    /**
+        Cancels the request.
+    */
+    public func cancel() {
+        if let
+            downloadDelegate = delegate as? DownloadTaskDelegate,
+            downloadTask = downloadDelegate.downloadTask
+        {
+            downloadTask.cancelByProducingResumeData { data in
+                downloadDelegate.resumeData = data
+            }
+        } else {
+            task.cancel()
+        }
+
+        NSNotificationCenter.defaultCenter().postNotificationName(Notifications.Task.DidCancel, object: task)
+    }
+
+    // MARK: - TaskDelegate
+
+    /**
+        The task delegate is responsible for handling all delegate callbacks for the underlying task as well as 
+        executing all operations attached to the serial operation queue upon task completion.
+    */
+    public class TaskDelegate: NSObject {
+
+        /// The serial operation queue used to execute all operations after the task completes.
+        public let queue: NSOperationQueue
+
+        let task: NSURLSessionTask
+        let progress: NSProgress
+
+        var data: NSData? { return nil }
+        var error: NSError?
+
+        var initialResponseTime: CFAbsoluteTime?
+        var credential: NSURLCredential?
+
+        init(task: NSURLSessionTask) {
+            self.task = task
+            self.progress = NSProgress(totalUnitCount: 0)
+            self.queue = {
+                let operationQueue = NSOperationQueue()
+                operationQueue.maxConcurrentOperationCount = 1
+                operationQueue.suspended = true
+
+                if #available(OSX 10.10, *) {
+                    operationQueue.qualityOfService = NSQualityOfService.Utility
+                }
+
+                return operationQueue
+            }()
+        }
+
+        deinit {
+            queue.cancelAllOperations()
+            queue.suspended = false
+        }
+
+        // MARK: - NSURLSessionTaskDelegate
+
+        // MARK: Override Closures
+
+        var taskWillPerformHTTPRedirection: ((NSURLSession, NSURLSessionTask, NSHTTPURLResponse, NSURLRequest) -> NSURLRequest?)?
+        var taskDidReceiveChallenge: ((NSURLSession, NSURLSessionTask, NSURLAuthenticationChallenge) -> (NSURLSessionAuthChallengeDisposition, NSURLCredential?))?
+        var taskNeedNewBodyStream: ((NSURLSession, NSURLSessionTask) -> NSInputStream?)?
+        var taskDidCompleteWithError: ((NSURLSession, NSURLSessionTask, NSError?) -> Void)?
+
+        // MARK: Delegate Methods
+
+        func URLSession(
+            session: NSURLSession,
+            task: NSURLSessionTask,
+            willPerformHTTPRedirection response: NSHTTPURLResponse,
+            newRequest request: NSURLRequest,
+            completionHandler: ((NSURLRequest?) -> Void))
+        {
+            var redirectRequest: NSURLRequest? = request
+
+            if let taskWillPerformHTTPRedirection = taskWillPerformHTTPRedirection {
+                redirectRequest = taskWillPerformHTTPRedirection(session, task, response, request)
+            }
+
+            completionHandler(redirectRequest)
+        }
+
+        func URLSession(
+            session: NSURLSession,
+            task: NSURLSessionTask,
+            didReceiveChallenge challenge: NSURLAuthenticationChallenge,
+            completionHandler: ((NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void))
+        {
+            var disposition: NSURLSessionAuthChallengeDisposition = .PerformDefaultHandling
+            var credential: NSURLCredential?
+
+            if let taskDidReceiveChallenge = taskDidReceiveChallenge {
+                (disposition, credential) = taskDidReceiveChallenge(session, task, challenge)
+            } else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
+                let host = challenge.protectionSpace.host
+
+                if let
+                    serverTrustPolicy = session.serverTrustPolicyManager?.serverTrustPolicyForHost(host),
+                    serverTrust = challenge.protectionSpace.serverTrust
+                {
+                    if serverTrustPolicy.evaluateServerTrust(serverTrust, isValidForHost: host) {
+                        disposition = .UseCredential
+                        credential = NSURLCredential(forTrust: serverTrust)
+                    } else {
+                        disposition = .CancelAuthenticationChallenge
+                    }
+                }
+            } else {
+                if challenge.previousFailureCount > 0 {
+                    disposition = .CancelAuthenticationChallenge
+                } else {
+                    credential = self.credential ?? session.configuration.URLCredentialStorage?.defaultCredentialForProtectionSpace(challenge.protectionSpace)
+
+                    if credential != nil {
+                        disposition = .UseCredential
+                    }
+                }
+            }
+
+            completionHandler(disposition, credential)
+        }
+
+        func URLSession(
+            session: NSURLSession,
+            task: NSURLSessionTask,
+            needNewBodyStream completionHandler: ((NSInputStream?) -> Void))
+        {
+            var bodyStream: NSInputStream?
+
+            if let taskNeedNewBodyStream = taskNeedNewBodyStream {
+                bodyStream = taskNeedNewBodyStream(session, task)
+            }
+
+            completionHandler(bodyStream)
+        }
+
+        func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
+            if let taskDidCompleteWithError = taskDidCompleteWithError {
+                taskDidCompleteWithError(session, task, error)
+            } else {
+                if let error = error {
+                    self.error = error
+
+                    if let
+                        downloadDelegate = self as? DownloadTaskDelegate,
+                        userInfo = error.userInfo as? [String: AnyObject],
+                        resumeData = userInfo[NSURLSessionDownloadTaskResumeData] as? NSData
+                    {
+                        downloadDelegate.resumeData = resumeData
+                    }
+                }
+
+                queue.suspended = false
+            }
+        }
+    }
+
+    // MARK: - DataTaskDelegate
+
+    class DataTaskDelegate: TaskDelegate, NSURLSessionDataDelegate {
+        var dataTask: NSURLSessionDataTask? { return task as? NSURLSessionDataTask }
+
+        private var totalBytesReceived: Int64 = 0
+        private var mutableData: NSMutableData
+        override var data: NSData? {
+            if dataStream != nil {
+                return nil
+            } else {
+                return mutableData
+            }
+        }
+
+        private var expectedContentLength: Int64?
+        private var dataProgress: ((bytesReceived: Int64, totalBytesReceived: Int64, totalBytesExpectedToReceive: Int64) -> Void)?
+        private var dataStream: ((data: NSData) -> Void)?
+
+        override init(task: NSURLSessionTask) {
+            mutableData = NSMutableData()
+            super.init(task: task)
+        }
+
+        // MARK: - NSURLSessionDataDelegate
+
+        // MARK: Override Closures
+
+        var dataTaskDidReceiveResponse: ((NSURLSession, NSURLSessionDataTask, NSURLResponse) -> NSURLSessionResponseDisposition)?
+        var dataTaskDidBecomeDownloadTask: ((NSURLSession, NSURLSessionDataTask, NSURLSessionDownloadTask) -> Void)?
+        var dataTaskDidReceiveData: ((NSURLSession, NSURLSessionDataTask, NSData) -> Void)?
+        var dataTaskWillCacheResponse: ((NSURLSession, NSURLSessionDataTask, NSCachedURLResponse) -> NSCachedURLResponse?)?
+
+        // MARK: Delegate Methods
+
+        func URLSession(
+            session: NSURLSession,
+            dataTask: NSURLSessionDataTask,
+            didReceiveResponse response: NSURLResponse,
+            completionHandler: (NSURLSessionResponseDisposition -> Void))
+        {
+            var disposition: NSURLSessionResponseDisposition = .Allow
+
+            expectedContentLength = response.expectedContentLength
+
+            if let dataTaskDidReceiveResponse = dataTaskDidReceiveResponse {
+                disposition = dataTaskDidReceiveResponse(session, dataTask, response)
+            }
+
+            completionHandler(disposition)
+        }
+
+        func URLSession(
+            session: NSURLSession,
+            dataTask: NSURLSessionDataTask,
+            didBecomeDownloadTask downloadTask: NSURLSessionDownloadTask)
+        {
+            dataTaskDidBecomeDownloadTask?(session, dataTask, downloadTask)
+        }
+
+        func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData) {
+            if initialResponseTime == nil { initialResponseTime = CFAbsoluteTimeGetCurrent() }
+
+            if let dataTaskDidReceiveData = dataTaskDidReceiveData {
+                dataTaskDidReceiveData(session, dataTask, data)
+            } else {
+                if let dataStream = dataStream {
+                    dataStream(data: data)
+                } else {
+                    mutableData.appendData(data)
+                }
+
+                totalBytesReceived += data.length
+                let totalBytesExpected = dataTask.response?.expectedContentLength ?? NSURLSessionTransferSizeUnknown
+
+                progress.totalUnitCount = totalBytesExpected
+                progress.completedUnitCount = totalBytesReceived
+
+                dataProgress?(
+                    bytesReceived: Int64(data.length),
+                    totalBytesReceived: totalBytesReceived,
+                    totalBytesExpectedToReceive: totalBytesExpected
+                )
+            }
+        }
+
+        func URLSession(
+            session: NSURLSession,
+            dataTask: NSURLSessionDataTask,
+            willCacheResponse proposedResponse: NSCachedURLResponse,
+            completionHandler: ((NSCachedURLResponse?) -> Void))
+        {
+            var cachedResponse: NSCachedURLResponse? = proposedResponse
+
+            if let dataTaskWillCacheResponse = dataTaskWillCacheResponse {
+                cachedResponse = dataTaskWillCacheResponse(session, dataTask, proposedResponse)
+            }
+
+            completionHandler(cachedResponse)
+        }
+    }
+}
+
+// MARK: - CustomStringConvertible
+
+extension Request: CustomStringConvertible {
+
+    /**
+        The textual representation used when written to an output stream, which includes the HTTP method and URL, as 
+        well as the response status code if a response has been received.
+    */
+    public var description: String {
+        var components: [String] = []
+
+        if let HTTPMethod = request?.HTTPMethod {
+            components.append(HTTPMethod)
+        }
+
+        if let URLString = request?.URL?.absoluteString {
+            components.append(URLString)
+        }
+
+        if let response = response {
+            components.append("(\(response.statusCode))")
+        }
+
+        return components.joinWithSeparator(" ")
+    }
+}
+
+// MARK: - CustomDebugStringConvertible
+
+extension Request: CustomDebugStringConvertible {
+    func cURLRepresentation() -> String {
+        var components = ["$ curl -i"]
+
+        guard let
+            request = self.request,
+            URL = request.URL,
+            host = URL.host
+        else {
+            return "$ curl command could not be created"
+        }
+
+        if let HTTPMethod = request.HTTPMethod where HTTPMethod != "GET" {
+            components.append("-X \(HTTPMethod)")
+        }
+
+        if let credentialStorage = self.session.configuration.URLCredentialStorage {
+            let protectionSpace = NSURLProtectionSpace(
+                host: host,
+                port: URL.port?.integerValue ?? 0,
+                `protocol`: URL.scheme,
+                realm: host,
+                authenticationMethod: NSURLAuthenticationMethodHTTPBasic
+            )
+
+            if let credentials = credentialStorage.credentialsForProtectionSpace(protectionSpace)?.values {
+                for credential in credentials {
+                    components.append("-u \(credential.user!):\(credential.password!)")
+                }
+            } else {
+                if let credential = delegate.credential {
+                    components.append("-u \(credential.user!):\(credential.password!)")
+                }
+            }
+        }
+
+        if session.configuration.HTTPShouldSetCookies {
+            if let
+                cookieStorage = session.configuration.HTTPCookieStorage,
+                cookies = cookieStorage.cookiesForURL(URL) where !cookies.isEmpty
+            {
+                let string = cookies.reduce("") { $0 + "\($1.name)=\($1.value ?? String());" }
+                components.append("-b \"\(string.substringToIndex(string.endIndex.predecessor()))\"")
+            }
+        }
+
+        if let headerFields = request.allHTTPHeaderFields {
+            for (field, value) in headerFields {
+                switch field {
+                case "Cookie":
+                    continue
+                default:
+                    components.append("-H \"\(field): \(value)\"")
+                }
+            }
+        }
+
+        if let additionalHeaders = session.configuration.HTTPAdditionalHeaders {
+            for (field, value) in additionalHeaders {
+                switch field {
+                case "Cookie":
+                    continue
+                default:
+                    components.append("-H \"\(field): \(value)\"")
+                }
+            }
+        }
+
+        if let
+            HTTPBodyData = request.HTTPBody,
+            HTTPBody = String(data: HTTPBodyData, encoding: NSUTF8StringEncoding)
+        {
+            let escapedBody = HTTPBody.stringByReplacingOccurrencesOfString("\"", withString: "\\\"")
+            components.append("-d \"\(escapedBody)\"")
+        }
+
+        components.append("\"\(URL.absoluteString)\"")
+
+        return components.joinWithSeparator(" \\\n\t")
+    }
+
+    /// The textual representation used when written to an output stream, in the form of a cURL command.
+    public var debugDescription: String {
+        return cURLRepresentation()
+    }
+}

+ 95 - 0
Pods/Alamofire/Source/Response.swift

@@ -0,0 +1,95 @@
+// Response.swift
+//
+// Copyright (c) 2014–2016 Alamofire Software Foundation (http://alamofire.org/)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+import Foundation
+
+/// Used to store all response data returned from a completed `Request`.
+public struct Response<Value, Error: ErrorType> {
+    /// The URL request sent to the server.
+    public let request: NSURLRequest?
+
+    /// The server's response to the URL request.
+    public let response: NSHTTPURLResponse?
+
+    /// The data returned by the server.
+    public let data: NSData?
+
+    /// The result of response serialization.
+    public let result: Result<Value, Error>
+
+    /// The timeline of the complete lifecycle of the `Request`.
+    public let timeline: Timeline
+
+    /**
+        Initializes the `Response` instance with the specified URL request, URL response, server data and response
+        serialization result.
+    
+        - parameter request:  The URL request sent to the server.
+        - parameter response: The server's response to the URL request.
+        - parameter data:     The data returned by the server.
+        - parameter result:   The result of response serialization.
+        - parameter timeline: The timeline of the complete lifecycle of the `Request`. Defaults to `Timeline()`.
+
+        - returns: the new `Response` instance.
+    */
+    public init(
+        request: NSURLRequest?,
+        response: NSHTTPURLResponse?,
+        data: NSData?,
+        result: Result<Value, Error>,
+        timeline: Timeline = Timeline())
+    {
+        self.request = request
+        self.response = response
+        self.data = data
+        self.result = result
+        self.timeline = timeline
+    }
+}
+
+// MARK: - CustomStringConvertible
+
+extension Response: CustomStringConvertible {
+    /// The textual representation used when written to an output stream, which includes whether the result was a
+    /// success or failure.
+    public var description: String {
+        return result.debugDescription
+    }
+}
+
+// MARK: - CustomDebugStringConvertible
+
+extension Response: CustomDebugStringConvertible {
+    /// The debug textual representation used when written to an output stream, which includes the URL request, the URL
+    /// response, the server data and the response serialization result.
+    public var debugDescription: String {
+        var output: [String] = []
+
+        output.append(request != nil ? "[Request]: \(request!)" : "[Request]: nil")
+        output.append(response != nil ? "[Response]: \(response!)" : "[Response]: nil")
+        output.append("[Data]: \(data?.length ?? 0) bytes")
+        output.append("[Result]: \(result.debugDescription)")
+        output.append("[Timeline]: \(timeline.debugDescription)")
+
+        return output.joinWithSeparator("\n")
+    }
+}

+ 366 - 0
Pods/Alamofire/Source/ResponseSerialization.swift

@@ -0,0 +1,366 @@
+// ResponseSerialization.swift
+//
+// Copyright (c) 2014–2016 Alamofire Software Foundation (http://alamofire.org/)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+import Foundation
+
+// MARK: ResponseSerializer
+
+/**
+    The type in which all response serializers must conform to in order to serialize a response.
+*/
+public protocol ResponseSerializerType {
+    /// The type of serialized object to be created by this `ResponseSerializerType`.
+    typealias SerializedObject
+
+    /// The type of error to be created by this `ResponseSerializer` if serialization fails.
+    typealias ErrorObject: ErrorType
+
+    /**
+        A closure used by response handlers that takes a request, response, data and error and returns a result.
+    */
+    var serializeResponse: (NSURLRequest?, NSHTTPURLResponse?, NSData?, NSError?) -> Result<SerializedObject, ErrorObject> { get }
+}
+
+// MARK: -
+
+/**
+    A generic `ResponseSerializerType` used to serialize a request, response, and data into a serialized object.
+*/
+public struct ResponseSerializer<Value, Error: ErrorType>: ResponseSerializerType {
+    /// The type of serialized object to be created by this `ResponseSerializer`.
+    public typealias SerializedObject = Value
+
+    /// The type of error to be created by this `ResponseSerializer` if serialization fails.
+    public typealias ErrorObject = Error
+
+    /**
+        A closure used by response handlers that takes a request, response, data and error and returns a result.
+    */
+    public var serializeResponse: (NSURLRequest?, NSHTTPURLResponse?, NSData?, NSError?) -> Result<Value, Error>
+
+    /**
+        Initializes the `ResponseSerializer` instance with the given serialize response closure.
+
+        - parameter serializeResponse: The closure used to serialize the response.
+
+        - returns: The new generic response serializer instance.
+    */
+    public init(serializeResponse: (NSURLRequest?, NSHTTPURLResponse?, NSData?, NSError?) -> Result<Value, Error>) {
+        self.serializeResponse = serializeResponse
+    }
+}
+
+// MARK: - Default
+
+extension Request {
+
+    /**
+        Adds a handler to be called once the request has finished.
+
+        - parameter queue:             The queue on which the completion handler is dispatched.
+        - parameter completionHandler: The code to be executed once the request has finished.
+
+        - returns: The request.
+    */
+    public func response(
+        queue queue: dispatch_queue_t? = nil,
+        completionHandler: (NSURLRequest?, NSHTTPURLResponse?, NSData?, NSError?) -> Void)
+        -> Self
+    {
+        delegate.queue.addOperationWithBlock {
+            dispatch_async(queue ?? dispatch_get_main_queue()) {
+                completionHandler(self.request, self.response, self.delegate.data, self.delegate.error)
+            }
+        }
+
+        return self
+    }
+
+    /**
+        Adds a handler to be called once the request has finished.
+
+        - parameter queue:              The queue on which the completion handler is dispatched.
+        - parameter responseSerializer: The response serializer responsible for serializing the request, response, 
+                                        and data.
+        - parameter completionHandler:  The code to be executed once the request has finished.
+
+        - returns: The request.
+    */
+    public func response<T: ResponseSerializerType>(
+        queue queue: dispatch_queue_t? = nil,
+        responseSerializer: T,
+        completionHandler: Response<T.SerializedObject, T.ErrorObject> -> Void)
+        -> Self
+    {
+        delegate.queue.addOperationWithBlock {
+            let result = responseSerializer.serializeResponse(
+                self.request,
+                self.response,
+                self.delegate.data,
+                self.delegate.error
+            )
+
+            let requestCompletedTime = self.endTime ?? CFAbsoluteTimeGetCurrent()
+            let initialResponseTime = self.delegate.initialResponseTime ?? requestCompletedTime
+
+            let timeline = Timeline(
+                requestStartTime: self.startTime ?? CFAbsoluteTimeGetCurrent(),
+                initialResponseTime: initialResponseTime,
+                requestCompletedTime: requestCompletedTime,
+                serializationCompletedTime: CFAbsoluteTimeGetCurrent()
+            )
+
+            let response = Response<T.SerializedObject, T.ErrorObject>(
+                request: self.request,
+                response: self.response,
+                data: self.delegate.data,
+                result: result,
+                timeline: timeline
+            )
+
+            dispatch_async(queue ?? dispatch_get_main_queue()) { completionHandler(response) }
+        }
+
+        return self
+    }
+}
+
+// MARK: - Data
+
+extension Request {
+
+    /**
+        Creates a response serializer that returns the associated data as-is.
+
+        - returns: A data response serializer.
+    */
+    public static func dataResponseSerializer() -> ResponseSerializer<NSData, NSError> {
+        return ResponseSerializer { _, response, data, error in
+            guard error == nil else { return .Failure(error!) }
+
+            if let response = response where response.statusCode == 204 { return .Success(NSData()) }
+
+            guard let validData = data else {
+                let failureReason = "Data could not be serialized. Input data was nil."
+                let error = Error.errorWithCode(.DataSerializationFailed, failureReason: failureReason)
+                return .Failure(error)
+            }
+
+            return .Success(validData)
+        }
+    }
+
+    /**
+        Adds a handler to be called once the request has finished.
+
+        - parameter completionHandler: The code to be executed once the request has finished.
+
+        - returns: The request.
+    */
+    public func responseData(completionHandler: Response<NSData, NSError> -> Void) -> Self {
+        return response(responseSerializer: Request.dataResponseSerializer(), completionHandler: completionHandler)
+    }
+}
+
+// MARK: - String
+
+extension Request {
+
+    /**
+        Creates a response serializer that returns a string initialized from the response data with the specified 
+        string encoding.
+
+        - parameter encoding: The string encoding. If `nil`, the string encoding will be determined from the server 
+                              response, falling back to the default HTTP default character set, ISO-8859-1.
+
+        - returns: A string response serializer.
+    */
+    public static func stringResponseSerializer(
+        encoding encoding: NSStringEncoding? = nil)
+        -> ResponseSerializer<String, NSError>
+    {
+        return ResponseSerializer { _, response, data, error in
+            guard error == nil else { return .Failure(error!) }
+
+            if let response = response where response.statusCode == 204 { return .Success("") }
+
+            guard let validData = data else {
+                let failureReason = "String could not be serialized. Input data was nil."
+                let error = Error.errorWithCode(.StringSerializationFailed, failureReason: failureReason)
+                return .Failure(error)
+            }
+            
+            var convertedEncoding = encoding
+            
+            if let encodingName = response?.textEncodingName where convertedEncoding == nil {
+                convertedEncoding = CFStringConvertEncodingToNSStringEncoding(
+                    CFStringConvertIANACharSetNameToEncoding(encodingName)
+                )
+            }
+
+            let actualEncoding = convertedEncoding ?? NSISOLatin1StringEncoding
+
+            if let string = String(data: validData, encoding: actualEncoding) {
+                return .Success(string)
+            } else {
+                let failureReason = "String could not be serialized with encoding: \(actualEncoding)"
+                let error = Error.errorWithCode(.StringSerializationFailed, failureReason: failureReason)
+                return .Failure(error)
+            }
+        }
+    }
+
+    /**
+        Adds a handler to be called once the request has finished.
+
+        - parameter encoding:          The string encoding. If `nil`, the string encoding will be determined from the 
+                                       server response, falling back to the default HTTP default character set, 
+                                       ISO-8859-1.
+        - parameter completionHandler: A closure to be executed once the request has finished.
+
+        - returns: The request.
+    */
+    public func responseString(
+        encoding encoding: NSStringEncoding? = nil,
+        completionHandler: Response<String, NSError> -> Void)
+        -> Self
+    {
+        return response(
+            responseSerializer: Request.stringResponseSerializer(encoding: encoding),
+            completionHandler: completionHandler
+        )
+    }
+}
+
+// MARK: - JSON
+
+extension Request {
+
+    /**
+        Creates a response serializer that returns a JSON object constructed from the response data using 
+        `NSJSONSerialization` with the specified reading options.
+
+        - parameter options: The JSON serialization reading options. `.AllowFragments` by default.
+
+        - returns: A JSON object response serializer.
+    */
+    public static func JSONResponseSerializer(
+        options options: NSJSONReadingOptions = .AllowFragments)
+        -> ResponseSerializer<AnyObject, NSError>
+    {
+        return ResponseSerializer { _, response, data, error in
+            guard error == nil else { return .Failure(error!) }
+
+            if let response = response where response.statusCode == 204 { return .Success(NSNull()) }
+
+            guard let validData = data where validData.length > 0 else {
+                let failureReason = "JSON could not be serialized. Input data was nil or zero length."
+                let error = Error.errorWithCode(.JSONSerializationFailed, failureReason: failureReason)
+                return .Failure(error)
+            }
+
+            do {
+                let JSON = try NSJSONSerialization.JSONObjectWithData(validData, options: options)
+                return .Success(JSON)
+            } catch {
+                return .Failure(error as NSError)
+            }
+        }
+    }
+
+    /**
+        Adds a handler to be called once the request has finished.
+
+        - parameter options:           The JSON serialization reading options. `.AllowFragments` by default.
+        - parameter completionHandler: A closure to be executed once the request has finished.
+
+        - returns: The request.
+    */
+    public func responseJSON(
+        options options: NSJSONReadingOptions = .AllowFragments,
+        completionHandler: Response<AnyObject, NSError> -> Void)
+        -> Self
+    {
+        return response(
+            responseSerializer: Request.JSONResponseSerializer(options: options),
+            completionHandler: completionHandler
+        )
+    }
+}
+
+// MARK: - Property List
+
+extension Request {
+
+    /**
+        Creates a response serializer that returns an object constructed from the response data using 
+        `NSPropertyListSerialization` with the specified reading options.
+
+        - parameter options: The property list reading options. `NSPropertyListReadOptions()` by default.
+
+        - returns: A property list object response serializer.
+    */
+    public static func propertyListResponseSerializer(
+        options options: NSPropertyListReadOptions = NSPropertyListReadOptions())
+        -> ResponseSerializer<AnyObject, NSError>
+    {
+        return ResponseSerializer { _, response, data, error in
+            guard error == nil else { return .Failure(error!) }
+
+            if let response = response where response.statusCode == 204 { return .Success(NSNull()) }
+
+            guard let validData = data where validData.length > 0 else {
+                let failureReason = "Property list could not be serialized. Input data was nil or zero length."
+                let error = Error.errorWithCode(.PropertyListSerializationFailed, failureReason: failureReason)
+                return .Failure(error)
+            }
+
+            do {
+                let plist = try NSPropertyListSerialization.propertyListWithData(validData, options: options, format: nil)
+                return .Success(plist)
+            } catch {
+                return .Failure(error as NSError)
+            }
+        }
+    }
+
+    /**
+        Adds a handler to be called once the request has finished.
+
+        - parameter options:           The property list reading options. `0` by default.
+        - parameter completionHandler: A closure to be executed once the request has finished. The closure takes 3
+                                       arguments: the URL request, the URL response, the server data and the result 
+                                       produced while creating the property list.
+
+        - returns: The request.
+    */
+    public func responsePropertyList(
+        options options: NSPropertyListReadOptions = NSPropertyListReadOptions(),
+        completionHandler: Response<AnyObject, NSError> -> Void)
+        -> Self
+    {
+        return response(
+            responseSerializer: Request.propertyListResponseSerializer(options: options),
+            completionHandler: completionHandler
+        )
+    }
+}

+ 101 - 0
Pods/Alamofire/Source/Result.swift

@@ -0,0 +1,101 @@
+// Result.swift
+//
+// Copyright (c) 2014–2016 Alamofire Software Foundation (http://alamofire.org/)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+import Foundation
+
+/**
+    Used to represent whether a request was successful or encountered an error.
+
+    - Success: The request and all post processing operations were successful resulting in the serialization of the 
+               provided associated value.
+    - Failure: The request encountered an error resulting in a failure. The associated values are the original data 
+               provided by the server as well as the error that caused the failure.
+*/
+public enum Result<Value, Error: ErrorType> {
+    case Success(Value)
+    case Failure(Error)
+
+    /// Returns `true` if the result is a success, `false` otherwise.
+    public var isSuccess: Bool {
+        switch self {
+        case .Success:
+            return true
+        case .Failure:
+            return false
+        }
+    }
+
+    /// Returns `true` if the result is a failure, `false` otherwise.
+    public var isFailure: Bool {
+        return !isSuccess
+    }
+
+    /// Returns the associated value if the result is a success, `nil` otherwise.
+    public var value: Value? {
+        switch self {
+        case .Success(let value):
+            return value
+        case .Failure:
+            return nil
+        }
+    }
+
+    /// Returns the associated error value if the result is a failure, `nil` otherwise.
+    public var error: Error? {
+        switch self {
+        case .Success:
+            return nil
+        case .Failure(let error):
+            return error
+        }
+    }
+}
+
+// MARK: - CustomStringConvertible
+
+extension Result: CustomStringConvertible {
+    /// The textual representation used when written to an output stream, which includes whether the result was a 
+    /// success or failure.
+    public var description: String {
+        switch self {
+        case .Success:
+            return "SUCCESS"
+        case .Failure:
+            return "FAILURE"
+        }
+    }
+}
+
+// MARK: - CustomDebugStringConvertible
+
+extension Result: CustomDebugStringConvertible {
+    /// The debug textual representation used when written to an output stream, which includes whether the result was a
+    /// success or failure in addition to the value or error.
+    public var debugDescription: String {
+        switch self {
+        case .Success(let value):
+            return "SUCCESS: \(value)"
+        case .Failure(let error):
+            return "FAILURE: \(error)"
+        }
+    }
+}

+ 302 - 0
Pods/Alamofire/Source/ServerTrustPolicy.swift

@@ -0,0 +1,302 @@
+// ServerTrustPolicy.swift
+//
+// Copyright (c) 2014–2016 Alamofire Software Foundation (http://alamofire.org/)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+import Foundation
+
+/// Responsible for managing the mapping of `ServerTrustPolicy` objects to a given host.
+public class ServerTrustPolicyManager {
+    /// The dictionary of policies mapped to a particular host.
+    public let policies: [String: ServerTrustPolicy]
+
+    /**
+        Initializes the `ServerTrustPolicyManager` instance with the given policies.
+
+        Since different servers and web services can have different leaf certificates, intermediate and even root 
+        certficates, it is important to have the flexibility to specify evaluation policies on a per host basis. This 
+        allows for scenarios such as using default evaluation for host1, certificate pinning for host2, public key 
+        pinning for host3 and disabling evaluation for host4.
+
+        - parameter policies: A dictionary of all policies mapped to a particular host.
+
+        - returns: The new `ServerTrustPolicyManager` instance.
+    */
+    public init(policies: [String: ServerTrustPolicy]) {
+        self.policies = policies
+    }
+
+    /**
+        Returns the `ServerTrustPolicy` for the given host if applicable.
+
+        By default, this method will return the policy that perfectly matches the given host. Subclasses could override
+        this method and implement more complex mapping implementations such as wildcards.
+
+        - parameter host: The host to use when searching for a matching policy.
+
+        - returns: The server trust policy for the given host if found.
+    */
+    public func serverTrustPolicyForHost(host: String) -> ServerTrustPolicy? {
+        return policies[host]
+    }
+}
+
+// MARK: -
+
+extension NSURLSession {
+    private struct AssociatedKeys {
+        static var ManagerKey = "NSURLSession.ServerTrustPolicyManager"
+    }
+
+    var serverTrustPolicyManager: ServerTrustPolicyManager? {
+        get {
+            return objc_getAssociatedObject(self, &AssociatedKeys.ManagerKey) as? ServerTrustPolicyManager
+        }
+        set (manager) {
+            objc_setAssociatedObject(self, &AssociatedKeys.ManagerKey, manager, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
+        }
+    }
+}
+
+// MARK: - ServerTrustPolicy
+
+/**
+    The `ServerTrustPolicy` evaluates the server trust generally provided by an `NSURLAuthenticationChallenge` when 
+    connecting to a server over a secure HTTPS connection. The policy configuration then evaluates the server trust 
+    with a given set of criteria to determine whether the server trust is valid and the connection should be made.
+
+    Using pinned certificates or public keys for evaluation helps prevent man-in-the-middle (MITM) attacks and other 
+    vulnerabilities. Applications dealing with sensitive customer data or financial information are strongly encouraged 
+    to route all communication over an HTTPS connection with pinning enabled.
+
+    - PerformDefaultEvaluation: Uses the default server trust evaluation while allowing you to control whether to 
+                                validate the host provided by the challenge. Applications are encouraged to always 
+                                validate the host in production environments to guarantee the validity of the server's 
+                                certificate chain.
+
+    - PinCertificates:          Uses the pinned certificates to validate the server trust. The server trust is
+                                considered valid if one of the pinned certificates match one of the server certificates. 
+                                By validating both the certificate chain and host, certificate pinning provides a very 
+                                secure form of server trust validation mitigating most, if not all, MITM attacks. 
+                                Applications are encouraged to always validate the host and require a valid certificate 
+                                chain in production environments.
+
+    - PinPublicKeys:            Uses the pinned public keys to validate the server trust. The server trust is considered
+                                valid if one of the pinned public keys match one of the server certificate public keys. 
+                                By validating both the certificate chain and host, public key pinning provides a very 
+                                secure form of server trust validation mitigating most, if not all, MITM attacks. 
+                                Applications are encouraged to always validate the host and require a valid certificate 
+                                chain in production environments.
+
+    - DisableEvaluation:        Disables all evaluation which in turn will always consider any server trust as valid.
+
+    - CustomEvaluation:         Uses the associated closure to evaluate the validity of the server trust.
+*/
+public enum ServerTrustPolicy {
+    case PerformDefaultEvaluation(validateHost: Bool)
+    case PinCertificates(certificates: [SecCertificate], validateCertificateChain: Bool, validateHost: Bool)
+    case PinPublicKeys(publicKeys: [SecKey], validateCertificateChain: Bool, validateHost: Bool)
+    case DisableEvaluation
+    case CustomEvaluation((serverTrust: SecTrust, host: String) -> Bool)
+
+    // MARK: - Bundle Location
+
+    /**
+        Returns all certificates within the given bundle with a `.cer` file extension.
+
+        - parameter bundle: The bundle to search for all `.cer` files.
+
+        - returns: All certificates within the given bundle.
+    */
+    public static func certificatesInBundle(bundle: NSBundle = NSBundle.mainBundle()) -> [SecCertificate] {
+        var certificates: [SecCertificate] = []
+
+        let paths = Set([".cer", ".CER", ".crt", ".CRT", ".der", ".DER"].map { fileExtension in
+            bundle.pathsForResourcesOfType(fileExtension, inDirectory: nil)
+        }.flatten())
+
+        for path in paths {
+            if let
+                certificateData = NSData(contentsOfFile: path),
+                certificate = SecCertificateCreateWithData(nil, certificateData)
+            {
+                certificates.append(certificate)
+            }
+        }
+
+        return certificates
+    }
+
+    /**
+        Returns all public keys within the given bundle with a `.cer` file extension.
+
+        - parameter bundle: The bundle to search for all `*.cer` files.
+
+        - returns: All public keys within the given bundle.
+    */
+    public static func publicKeysInBundle(bundle: NSBundle = NSBundle.mainBundle()) -> [SecKey] {
+        var publicKeys: [SecKey] = []
+
+        for certificate in certificatesInBundle(bundle) {
+            if let publicKey = publicKeyForCertificate(certificate) {
+                publicKeys.append(publicKey)
+            }
+        }
+
+        return publicKeys
+    }
+
+    // MARK: - Evaluation
+
+    /**
+        Evaluates whether the server trust is valid for the given host.
+
+        - parameter serverTrust: The server trust to evaluate.
+        - parameter host:        The host of the challenge protection space.
+
+        - returns: Whether the server trust is valid.
+    */
+    public func evaluateServerTrust(serverTrust: SecTrust, isValidForHost host: String) -> Bool {
+        var serverTrustIsValid = false
+
+        switch self {
+        case let .PerformDefaultEvaluation(validateHost):
+            let policy = SecPolicyCreateSSL(true, validateHost ? host as CFString : nil)
+            SecTrustSetPolicies(serverTrust, [policy])
+
+            serverTrustIsValid = trustIsValid(serverTrust)
+        case let .PinCertificates(pinnedCertificates, validateCertificateChain, validateHost):
+            if validateCertificateChain {
+                let policy = SecPolicyCreateSSL(true, validateHost ? host as CFString : nil)
+                SecTrustSetPolicies(serverTrust, [policy])
+
+                SecTrustSetAnchorCertificates(serverTrust, pinnedCertificates)
+                SecTrustSetAnchorCertificatesOnly(serverTrust, true)
+
+                serverTrustIsValid = trustIsValid(serverTrust)
+            } else {
+                let serverCertificatesDataArray = certificateDataForTrust(serverTrust)
+                let pinnedCertificatesDataArray = certificateDataForCertificates(pinnedCertificates)
+
+                outerLoop: for serverCertificateData in serverCertificatesDataArray {
+                    for pinnedCertificateData in pinnedCertificatesDataArray {
+                        if serverCertificateData.isEqualToData(pinnedCertificateData) {
+                            serverTrustIsValid = true
+                            break outerLoop
+                        }
+                    }
+                }
+            }
+        case let .PinPublicKeys(pinnedPublicKeys, validateCertificateChain, validateHost):
+            var certificateChainEvaluationPassed = true
+
+            if validateCertificateChain {
+                let policy = SecPolicyCreateSSL(true, validateHost ? host as CFString : nil)
+                SecTrustSetPolicies(serverTrust, [policy])
+
+                certificateChainEvaluationPassed = trustIsValid(serverTrust)
+            }
+
+            if certificateChainEvaluationPassed {
+                outerLoop: for serverPublicKey in ServerTrustPolicy.publicKeysForTrust(serverTrust) as [AnyObject] {
+                    for pinnedPublicKey in pinnedPublicKeys as [AnyObject] {
+                        if serverPublicKey.isEqual(pinnedPublicKey) {
+                            serverTrustIsValid = true
+                            break outerLoop
+                        }
+                    }
+                }
+            }
+        case .DisableEvaluation:
+            serverTrustIsValid = true
+        case let .CustomEvaluation(closure):
+            serverTrustIsValid = closure(serverTrust: serverTrust, host: host)
+        }
+
+        return serverTrustIsValid
+    }
+
+    // MARK: - Private - Trust Validation
+
+    private func trustIsValid(trust: SecTrust) -> Bool {
+        var isValid = false
+
+        var result = SecTrustResultType(kSecTrustResultInvalid)
+        let status = SecTrustEvaluate(trust, &result)
+
+        if status == errSecSuccess {
+            let unspecified = SecTrustResultType(kSecTrustResultUnspecified)
+            let proceed = SecTrustResultType(kSecTrustResultProceed)
+
+            isValid = result == unspecified || result == proceed
+        }
+
+        return isValid
+    }
+
+    // MARK: - Private - Certificate Data
+
+    private func certificateDataForTrust(trust: SecTrust) -> [NSData] {
+        var certificates: [SecCertificate] = []
+
+        for index in 0..<SecTrustGetCertificateCount(trust) {
+            if let certificate = SecTrustGetCertificateAtIndex(trust, index) {
+                certificates.append(certificate)
+            }
+        }
+
+        return certificateDataForCertificates(certificates)
+    }
+
+    private func certificateDataForCertificates(certificates: [SecCertificate]) -> [NSData] {
+        return certificates.map { SecCertificateCopyData($0) as NSData }
+    }
+
+    // MARK: - Private - Public Key Extraction
+
+    private static func publicKeysForTrust(trust: SecTrust) -> [SecKey] {
+        var publicKeys: [SecKey] = []
+
+        for index in 0..<SecTrustGetCertificateCount(trust) {
+            if let
+                certificate = SecTrustGetCertificateAtIndex(trust, index),
+                publicKey = publicKeyForCertificate(certificate)
+            {
+                publicKeys.append(publicKey)
+            }
+        }
+
+        return publicKeys
+    }
+
+    private static func publicKeyForCertificate(certificate: SecCertificate) -> SecKey? {
+        var publicKey: SecKey?
+
+        let policy = SecPolicyCreateBasicX509()
+        var trust: SecTrust?
+        let trustCreationStatus = SecTrustCreateWithCertificates(certificate, policy, &trust)
+
+        if let trust = trust where trustCreationStatus == errSecSuccess {
+            publicKey = SecTrustCopyPublicKey(trust)
+        }
+
+        return publicKey
+    }
+}

+ 180 - 0
Pods/Alamofire/Source/Stream.swift

@@ -0,0 +1,180 @@
+// Stream.swift
+//
+// Copyright (c) 2014–2016 Alamofire Software Foundation (http://alamofire.org/)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+import Foundation
+
+#if !os(watchOS)
+
+@available(iOS 9.0, OSX 10.11, tvOS 9.0, *)
+extension Manager {
+    private enum Streamable {
+        case Stream(String, Int)
+        case NetService(NSNetService)
+    }
+
+    private func stream(streamable: Streamable) -> Request {
+        var streamTask: NSURLSessionStreamTask!
+
+        switch streamable {
+        case .Stream(let hostName, let port):
+            dispatch_sync(queue) {
+                streamTask = self.session.streamTaskWithHostName(hostName, port: port)
+            }
+        case .NetService(let netService):
+            dispatch_sync(queue) {
+                streamTask = self.session.streamTaskWithNetService(netService)
+            }
+        }
+
+        let request = Request(session: session, task: streamTask)
+
+        delegate[request.delegate.task] = request.delegate
+
+        if startRequestsImmediately {
+            request.resume()
+        }
+
+        return request
+    }
+
+    /**
+        Creates a request for bidirectional streaming with the given hostname and port.
+
+        - parameter hostName: The hostname of the server to connect to.
+        - parameter port:     The port of the server to connect to.
+
+        :returns: The created stream request.
+    */
+    public func stream(hostName hostName: String, port: Int) -> Request {
+        return stream(.Stream(hostName, port))
+    }
+
+    /**
+        Creates a request for bidirectional streaming with the given `NSNetService`.
+
+        - parameter netService: The net service used to identify the endpoint.
+
+        - returns: The created stream request.
+    */
+    public func stream(netService netService: NSNetService) -> Request {
+        return stream(.NetService(netService))
+    }
+}
+
+// MARK: -
+
+@available(iOS 9.0, OSX 10.11, tvOS 9.0, *)
+extension Manager.SessionDelegate: NSURLSessionStreamDelegate {
+
+    // MARK: Override Closures
+
+    /// Overrides default behavior for NSURLSessionStreamDelegate method `URLSession:readClosedForStreamTask:`.
+    public var streamTaskReadClosed: ((NSURLSession, NSURLSessionStreamTask) -> Void)? {
+        get {
+            return _streamTaskReadClosed as? (NSURLSession, NSURLSessionStreamTask) -> Void
+        }
+        set {
+            _streamTaskReadClosed = newValue
+        }
+    }
+
+    /// Overrides default behavior for NSURLSessionStreamDelegate method `URLSession:writeClosedForStreamTask:`.
+    public var streamTaskWriteClosed: ((NSURLSession, NSURLSessionStreamTask) -> Void)? {
+        get {
+            return _streamTaskWriteClosed as? (NSURLSession, NSURLSessionStreamTask) -> Void
+        }
+        set {
+            _streamTaskWriteClosed = newValue
+        }
+    }
+
+    /// Overrides default behavior for NSURLSessionStreamDelegate method `URLSession:betterRouteDiscoveredForStreamTask:`.
+    public var streamTaskBetterRouteDiscovered: ((NSURLSession, NSURLSessionStreamTask) -> Void)? {
+        get {
+            return _streamTaskBetterRouteDiscovered as? (NSURLSession, NSURLSessionStreamTask) -> Void
+        }
+        set {
+            _streamTaskBetterRouteDiscovered = newValue
+        }
+    }
+
+    /// Overrides default behavior for NSURLSessionStreamDelegate method `URLSession:streamTask:didBecomeInputStream:outputStream:`.
+    public var streamTaskDidBecomeInputStream: ((NSURLSession, NSURLSessionStreamTask, NSInputStream, NSOutputStream) -> Void)? {
+        get {
+            return _streamTaskDidBecomeInputStream as? (NSURLSession, NSURLSessionStreamTask, NSInputStream, NSOutputStream) -> Void
+        }
+        set {
+            _streamTaskDidBecomeInputStream = newValue
+        }
+    }
+
+    // MARK: Delegate Methods
+
+    /**
+        Tells the delegate that the read side of the connection has been closed.
+
+        - parameter session:    The session.
+        - parameter streamTask: The stream task.
+    */
+    public func URLSession(session: NSURLSession, readClosedForStreamTask streamTask: NSURLSessionStreamTask) {
+        streamTaskReadClosed?(session, streamTask)
+    }
+
+    /**
+        Tells the delegate that the write side of the connection has been closed.
+
+        - parameter session:    The session.
+        - parameter streamTask: The stream task.
+    */
+    public func URLSession(session: NSURLSession, writeClosedForStreamTask streamTask: NSURLSessionStreamTask) {
+        streamTaskWriteClosed?(session, streamTask)
+    }
+
+    /**
+        Tells the delegate that the system has determined that a better route to the host is available.
+
+        - parameter session:    The session.
+        - parameter streamTask: The stream task.
+    */
+    public func URLSession(session: NSURLSession, betterRouteDiscoveredForStreamTask streamTask: NSURLSessionStreamTask) {
+        streamTaskBetterRouteDiscovered?(session, streamTask)
+    }
+
+    /**
+        Tells the delegate that the stream task has been completed and provides the unopened stream objects.
+
+        - parameter session:      The session.
+        - parameter streamTask:   The stream task.
+        - parameter inputStream:  The new input stream.
+        - parameter outputStream: The new output stream.
+    */
+    public func URLSession(
+        session: NSURLSession,
+        streamTask: NSURLSessionStreamTask,
+        didBecomeInputStream inputStream: NSInputStream,
+        outputStream: NSOutputStream)
+    {
+        streamTaskDidBecomeInputStream?(session, streamTask, inputStream, outputStream)
+    }
+}
+
+#endif

+ 123 - 0
Pods/Alamofire/Source/Timeline.swift

@@ -0,0 +1,123 @@
+// Timeline.swift
+//
+// Copyright (c) 2014–2016 Alamofire Software Foundation (http://alamofire.org/)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+import Foundation
+
+/// Responsible for computing the timing metrics for the complete lifecycle of a `Request`.
+public struct Timeline {
+    /// The time the request was initialized.
+    public let requestStartTime: CFAbsoluteTime
+
+    /// The time the first bytes were received from or sent to the server.
+    public let initialResponseTime: CFAbsoluteTime
+
+    /// The time when the request was completed.
+    public let requestCompletedTime: CFAbsoluteTime
+
+    /// The time when the response serialization was completed.
+    public let serializationCompletedTime: CFAbsoluteTime
+
+    /// The time interval in seconds from the time the request started to the initial response from the server.
+    public let latency: NSTimeInterval
+
+    /// The time interval in seconds from the time the request started to the time the request completed.
+    public let requestDuration: NSTimeInterval
+
+    /// The time interval in seconds from the time the request completed to the time response serialization completed.
+    public let serializationDuration: NSTimeInterval
+
+    /// The time interval in seconds from the time the request started to the time response serialization completed.
+    public let totalDuration: NSTimeInterval
+
+    /**
+        Creates a new `Timeline` instance with the specified request times.
+
+        - parameter requestStartTime:           The time the request was initialized. Defaults to `0.0`.
+        - parameter initialResponseTime:        The time the first bytes were received from or sent to the server. 
+                                                Defaults to `0.0`.
+        - parameter requestCompletedTime:       The time when the request was completed. Defaults to `0.0`.
+        - parameter serializationCompletedTime: The time when the response serialization was completed. Defaults 
+                                                to `0.0`.
+
+        - returns: The new `Timeline` instance.
+    */
+    public init(
+        requestStartTime: CFAbsoluteTime = 0.0,
+        initialResponseTime: CFAbsoluteTime = 0.0,
+        requestCompletedTime: CFAbsoluteTime = 0.0,
+        serializationCompletedTime: CFAbsoluteTime = 0.0)
+    {
+        self.requestStartTime = requestStartTime
+        self.initialResponseTime = initialResponseTime
+        self.requestCompletedTime = requestCompletedTime
+        self.serializationCompletedTime = serializationCompletedTime
+
+        self.latency = initialResponseTime - requestStartTime
+        self.requestDuration = requestCompletedTime - requestStartTime
+        self.serializationDuration = serializationCompletedTime - requestCompletedTime
+        self.totalDuration = serializationCompletedTime - requestStartTime
+    }
+}
+
+// MARK: - CustomStringConvertible
+
+extension Timeline: CustomStringConvertible {
+    /// The textual representation used when written to an output stream, which includes the latency, the request 
+    /// duration and the total duration.
+    public var description: String {
+        let latency = String(format: "%.3f", self.latency)
+        let requestDuration = String(format: "%.3f", self.requestDuration)
+        let serializationDuration = String(format: "%.3f", self.serializationDuration)
+        let totalDuration = String(format: "%.3f", self.totalDuration)
+
+        let timings = [
+            "\"Latency\": \(latency) secs",
+            "\"Request Duration\": \(requestDuration) secs",
+            "\"Serialization Duration\": \(serializationDuration) secs",
+            "\"Total Duration\": \(totalDuration) secs"
+        ]
+
+        return "Timeline: { \(timings.joinWithSeparator(", ")) }"
+    }
+}
+
+// MARK: - CustomDebugStringConvertible
+
+extension Timeline: CustomDebugStringConvertible {
+    /// The textual representation used when written to an output stream, which includes the request start time, the 
+    /// initial response time, the request completed time, the serialization completed time, the latency, the request
+    /// duration and the total duration.
+    public var debugDescription: String {
+        let timings = [
+            "\"Request Start Time\": \(requestStartTime)",
+            "\"Initial Response Time\": \(initialResponseTime)",
+            "\"Request Completed Time\": \(requestCompletedTime)",
+            "\"Serialization Completed Time\": \(serializationCompletedTime)",
+            "\"Latency\": \(latency) secs",
+            "\"Request Duration\": \(requestDuration) secs",
+            "\"Serialization Duration\": \(serializationDuration) secs",
+            "\"Total Duration\": \(totalDuration) secs"
+        ]
+
+        return "Timeline: { \(timings.joinWithSeparator(", ")) }"
+    }
+}

+ 374 - 0
Pods/Alamofire/Source/Upload.swift

@@ -0,0 +1,374 @@
+// Upload.swift
+//
+// Copyright (c) 2014–2016 Alamofire Software Foundation (http://alamofire.org/)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+import Foundation
+
+extension Manager {
+    private enum Uploadable {
+        case Data(NSURLRequest, NSData)
+        case File(NSURLRequest, NSURL)
+        case Stream(NSURLRequest, NSInputStream)
+    }
+
+    private func upload(uploadable: Uploadable) -> Request {
+        var uploadTask: NSURLSessionUploadTask!
+        var HTTPBodyStream: NSInputStream?
+
+        switch uploadable {
+        case .Data(let request, let data):
+            dispatch_sync(queue) {
+                uploadTask = self.session.uploadTaskWithRequest(request, fromData: data)
+            }
+        case .File(let request, let fileURL):
+            dispatch_sync(queue) {
+                uploadTask = self.session.uploadTaskWithRequest(request, fromFile: fileURL)
+            }
+        case .Stream(let request, let stream):
+            dispatch_sync(queue) {
+                uploadTask = self.session.uploadTaskWithStreamedRequest(request)
+            }
+
+            HTTPBodyStream = stream
+        }
+
+        let request = Request(session: session, task: uploadTask)
+
+        if HTTPBodyStream != nil {
+            request.delegate.taskNeedNewBodyStream = { _, _ in
+                return HTTPBodyStream
+            }
+        }
+
+        delegate[request.delegate.task] = request.delegate
+
+        if startRequestsImmediately {
+            request.resume()
+        }
+
+        return request
+    }
+
+    // MARK: File
+
+    /**
+        Creates a request for uploading a file to the specified URL request.
+
+        If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
+
+        - parameter URLRequest: The URL request
+        - parameter file:       The file to upload
+
+        - returns: The created upload request.
+    */
+    public func upload(URLRequest: URLRequestConvertible, file: NSURL) -> Request {
+        return upload(.File(URLRequest.URLRequest, file))
+    }
+
+    /**
+        Creates a request for uploading a file to the specified URL request.
+
+        If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
+
+        - parameter method:    The HTTP method.
+        - parameter URLString: The URL string.
+        - parameter headers:   The HTTP headers. `nil` by default.
+        - parameter file:      The file to upload
+
+        - returns: The created upload request.
+    */
+    public func upload(
+        method: Method,
+        _ URLString: URLStringConvertible,
+        headers: [String: String]? = nil,
+        file: NSURL)
+        -> Request
+    {
+        let mutableURLRequest = URLRequest(method, URLString, headers: headers)
+        return upload(mutableURLRequest, file: file)
+    }
+
+    // MARK: Data
+
+    /**
+        Creates a request for uploading data to the specified URL request.
+
+        If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
+
+        - parameter URLRequest: The URL request.
+        - parameter data:       The data to upload.
+
+        - returns: The created upload request.
+    */
+    public func upload(URLRequest: URLRequestConvertible, data: NSData) -> Request {
+        return upload(.Data(URLRequest.URLRequest, data))
+    }
+
+    /**
+        Creates a request for uploading data to the specified URL request.
+
+        If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
+
+        - parameter method:    The HTTP method.
+        - parameter URLString: The URL string.
+        - parameter headers:   The HTTP headers. `nil` by default.
+        - parameter data:      The data to upload
+
+        - returns: The created upload request.
+    */
+    public func upload(
+        method: Method,
+        _ URLString: URLStringConvertible,
+        headers: [String: String]? = nil,
+        data: NSData)
+        -> Request
+    {
+        let mutableURLRequest = URLRequest(method, URLString, headers: headers)
+
+        return upload(mutableURLRequest, data: data)
+    }
+
+    // MARK: Stream
+
+    /**
+        Creates a request for uploading a stream to the specified URL request.
+
+        If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
+
+        - parameter URLRequest: The URL request.
+        - parameter stream:     The stream to upload.
+
+        - returns: The created upload request.
+    */
+    public func upload(URLRequest: URLRequestConvertible, stream: NSInputStream) -> Request {
+        return upload(.Stream(URLRequest.URLRequest, stream))
+    }
+
+    /**
+        Creates a request for uploading a stream to the specified URL request.
+
+        If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
+
+        - parameter method:    The HTTP method.
+        - parameter URLString: The URL string.
+        - parameter headers:   The HTTP headers. `nil` by default.
+        - parameter stream:    The stream to upload.
+
+        - returns: The created upload request.
+    */
+    public func upload(
+        method: Method,
+        _ URLString: URLStringConvertible,
+        headers: [String: String]? = nil,
+        stream: NSInputStream)
+        -> Request
+    {
+        let mutableURLRequest = URLRequest(method, URLString, headers: headers)
+
+        return upload(mutableURLRequest, stream: stream)
+    }
+
+    // MARK: MultipartFormData
+
+    /// Default memory threshold used when encoding `MultipartFormData`.
+    public static let MultipartFormDataEncodingMemoryThreshold: UInt64 = 10 * 1024 * 1024
+
+    /**
+        Defines whether the `MultipartFormData` encoding was successful and contains result of the encoding as 
+        associated values.
+
+        - Success: Represents a successful `MultipartFormData` encoding and contains the new `Request` along with 
+                   streaming information.
+        - Failure: Used to represent a failure in the `MultipartFormData` encoding and also contains the encoding 
+                   error.
+    */
+    public enum MultipartFormDataEncodingResult {
+        case Success(request: Request, streamingFromDisk: Bool, streamFileURL: NSURL?)
+        case Failure(ErrorType)
+    }
+
+    /**
+        Encodes the `MultipartFormData` and creates a request to upload the result to the specified URL request.
+
+        It is important to understand the memory implications of uploading `MultipartFormData`. If the cummulative 
+        payload is small, encoding the data in-memory and directly uploading to a server is the by far the most 
+        efficient approach. However, if the payload is too large, encoding the data in-memory could cause your app to 
+        be terminated. Larger payloads must first be written to disk using input and output streams to keep the memory 
+        footprint low, then the data can be uploaded as a stream from the resulting file. Streaming from disk MUST be 
+        used for larger payloads such as video content.
+
+        The `encodingMemoryThreshold` parameter allows Alamofire to automatically determine whether to encode in-memory 
+        or stream from disk. If the content length of the `MultipartFormData` is below the `encodingMemoryThreshold`,
+        encoding takes place in-memory. If the content length exceeds the threshold, the data is streamed to disk 
+        during the encoding process. Then the result is uploaded as data or as a stream depending on which encoding 
+        technique was used.
+
+        If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
+
+        - parameter method:                  The HTTP method.
+        - parameter URLString:               The URL string.
+        - parameter headers:                 The HTTP headers. `nil` by default.
+        - parameter multipartFormData:       The closure used to append body parts to the `MultipartFormData`.
+        - parameter encodingMemoryThreshold: The encoding memory threshold in bytes.
+                                             `MultipartFormDataEncodingMemoryThreshold` by default.
+        - parameter encodingCompletion:      The closure called when the `MultipartFormData` encoding is complete.
+    */
+    public func upload(
+        method: Method,
+        _ URLString: URLStringConvertible,
+        headers: [String: String]? = nil,
+        multipartFormData: MultipartFormData -> Void,
+        encodingMemoryThreshold: UInt64 = Manager.MultipartFormDataEncodingMemoryThreshold,
+        encodingCompletion: (MultipartFormDataEncodingResult -> Void)?)
+    {
+        let mutableURLRequest = URLRequest(method, URLString, headers: headers)
+
+        return upload(
+            mutableURLRequest,
+            multipartFormData: multipartFormData,
+            encodingMemoryThreshold: encodingMemoryThreshold,
+            encodingCompletion: encodingCompletion
+        )
+    }
+
+    /**
+        Encodes the `MultipartFormData` and creates a request to upload the result to the specified URL request.
+
+        It is important to understand the memory implications of uploading `MultipartFormData`. If the cummulative
+        payload is small, encoding the data in-memory and directly uploading to a server is the by far the most
+        efficient approach. However, if the payload is too large, encoding the data in-memory could cause your app to
+        be terminated. Larger payloads must first be written to disk using input and output streams to keep the memory
+        footprint low, then the data can be uploaded as a stream from the resulting file. Streaming from disk MUST be
+        used for larger payloads such as video content.
+
+        The `encodingMemoryThreshold` parameter allows Alamofire to automatically determine whether to encode in-memory
+        or stream from disk. If the content length of the `MultipartFormData` is below the `encodingMemoryThreshold`,
+        encoding takes place in-memory. If the content length exceeds the threshold, the data is streamed to disk
+        during the encoding process. Then the result is uploaded as data or as a stream depending on which encoding
+        technique was used.
+
+        If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
+
+        - parameter URLRequest:              The URL request.
+        - parameter multipartFormData:       The closure used to append body parts to the `MultipartFormData`.
+        - parameter encodingMemoryThreshold: The encoding memory threshold in bytes.
+                                             `MultipartFormDataEncodingMemoryThreshold` by default.
+        - parameter encodingCompletion:      The closure called when the `MultipartFormData` encoding is complete.
+    */
+    public func upload(
+        URLRequest: URLRequestConvertible,
+        multipartFormData: MultipartFormData -> Void,
+        encodingMemoryThreshold: UInt64 = Manager.MultipartFormDataEncodingMemoryThreshold,
+        encodingCompletion: (MultipartFormDataEncodingResult -> Void)?)
+    {
+        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
+            let formData = MultipartFormData()
+            multipartFormData(formData)
+
+            let URLRequestWithContentType = URLRequest.URLRequest
+            URLRequestWithContentType.setValue(formData.contentType, forHTTPHeaderField: "Content-Type")
+
+            let isBackgroundSession = self.session.configuration.identifier != nil
+
+            if formData.contentLength < encodingMemoryThreshold && !isBackgroundSession {
+                do {
+                    let data = try formData.encode()
+                    let encodingResult = MultipartFormDataEncodingResult.Success(
+                        request: self.upload(URLRequestWithContentType, data: data),
+                        streamingFromDisk: false,
+                        streamFileURL: nil
+                    )
+
+                    dispatch_async(dispatch_get_main_queue()) {
+                        encodingCompletion?(encodingResult)
+                    }
+                } catch {
+                    dispatch_async(dispatch_get_main_queue()) {
+                        encodingCompletion?(.Failure(error as NSError))
+                    }
+                }
+            } else {
+                let fileManager = NSFileManager.defaultManager()
+                let tempDirectoryURL = NSURL(fileURLWithPath: NSTemporaryDirectory())
+                let directoryURL = tempDirectoryURL.URLByAppendingPathComponent("com.alamofire.manager/multipart.form.data")
+                let fileName = NSUUID().UUIDString
+                let fileURL = directoryURL.URLByAppendingPathComponent(fileName)
+
+                do {
+                    try fileManager.createDirectoryAtURL(directoryURL, withIntermediateDirectories: true, attributes: nil)
+                    try formData.writeEncodedDataToDisk(fileURL)
+
+                    dispatch_async(dispatch_get_main_queue()) {
+                        let encodingResult = MultipartFormDataEncodingResult.Success(
+                            request: self.upload(URLRequestWithContentType, file: fileURL),
+                            streamingFromDisk: true,
+                            streamFileURL: fileURL
+                        )
+                        encodingCompletion?(encodingResult)
+                    }
+                } catch {
+                    dispatch_async(dispatch_get_main_queue()) {
+                        encodingCompletion?(.Failure(error as NSError))
+                    }
+                }
+            }
+        }
+    }
+}
+
+// MARK: -
+
+extension Request {
+
+    // MARK: - UploadTaskDelegate
+
+    class UploadTaskDelegate: DataTaskDelegate {
+        var uploadTask: NSURLSessionUploadTask? { return task as? NSURLSessionUploadTask }
+        var uploadProgress: ((Int64, Int64, Int64) -> Void)!
+
+        // MARK: - NSURLSessionTaskDelegate
+
+        // MARK: Override Closures
+
+        var taskDidSendBodyData: ((NSURLSession, NSURLSessionTask, Int64, Int64, Int64) -> Void)?
+
+        // MARK: Delegate Methods
+
+        func URLSession(
+            session: NSURLSession,
+            task: NSURLSessionTask,
+            didSendBodyData bytesSent: Int64,
+            totalBytesSent: Int64,
+            totalBytesExpectedToSend: Int64)
+        {
+            if initialResponseTime == nil { initialResponseTime = CFAbsoluteTimeGetCurrent() }
+
+            if let taskDidSendBodyData = taskDidSendBodyData {
+                taskDidSendBodyData(session, task, bytesSent, totalBytesSent, totalBytesExpectedToSend)
+            } else {
+                progress.totalUnitCount = totalBytesExpectedToSend
+                progress.completedUnitCount = totalBytesSent
+
+                uploadProgress?(bytesSent, totalBytesSent, totalBytesExpectedToSend)
+            }
+        }
+    }
+}

+ 189 - 0
Pods/Alamofire/Source/Validation.swift

@@ -0,0 +1,189 @@
+// Validation.swift
+//
+// Copyright (c) 2014–2016 Alamofire Software Foundation (http://alamofire.org/)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+import Foundation
+
+extension Request {
+
+    /**
+        Used to represent whether validation was successful or encountered an error resulting in a failure.
+
+        - Success: The validation was successful.
+        - Failure: The validation failed encountering the provided error.
+    */
+    public enum ValidationResult {
+        case Success
+        case Failure(NSError)
+    }
+
+    /**
+        A closure used to validate a request that takes a URL request and URL response, and returns whether the 
+        request was valid.
+    */
+    public typealias Validation = (NSURLRequest?, NSHTTPURLResponse) -> ValidationResult
+
+    /**
+        Validates the request, using the specified closure.
+
+        If validation fails, subsequent calls to response handlers will have an associated error.
+
+        - parameter validation: A closure to validate the request.
+
+        - returns: The request.
+    */
+    public func validate(validation: Validation) -> Self {
+        delegate.queue.addOperationWithBlock {
+            if let
+                response = self.response where self.delegate.error == nil,
+                case let .Failure(error) = validation(self.request, response)
+            {
+                self.delegate.error = error
+            }
+        }
+
+        return self
+    }
+
+    // MARK: - Status Code
+
+    /**
+        Validates that the response has a status code in the specified range.
+
+        If validation fails, subsequent calls to response handlers will have an associated error.
+
+        - parameter range: The range of acceptable status codes.
+
+        - returns: The request.
+    */
+    public func validate<S: SequenceType where S.Generator.Element == Int>(statusCode acceptableStatusCode: S) -> Self {
+        return validate { _, response in
+            if acceptableStatusCode.contains(response.statusCode) {
+                return .Success
+            } else {
+                let failureReason = "Response status code was unacceptable: \(response.statusCode)"
+                return .Failure(Error.errorWithCode(.StatusCodeValidationFailed, failureReason: failureReason))
+            }
+        }
+    }
+
+    // MARK: - Content-Type
+
+    private struct MIMEType {
+        let type: String
+        let subtype: String
+
+        init?(_ string: String) {
+            let components: [String] = {
+                let stripped = string.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
+                let split = stripped.substringToIndex(stripped.rangeOfString(";")?.startIndex ?? stripped.endIndex)
+                return split.componentsSeparatedByString("/")
+            }()
+
+            if let
+                type = components.first,
+                subtype = components.last
+            {
+                self.type = type
+                self.subtype = subtype
+            } else {
+                return nil
+            }
+        }
+
+        func matches(MIME: MIMEType) -> Bool {
+            switch (type, subtype) {
+            case (MIME.type, MIME.subtype), (MIME.type, "*"), ("*", MIME.subtype), ("*", "*"):
+                return true
+            default:
+                return false
+            }
+        }
+    }
+
+    /**
+        Validates that the response has a content type in the specified array.
+
+        If validation fails, subsequent calls to response handlers will have an associated error.
+
+        - parameter contentType: The acceptable content types, which may specify wildcard types and/or subtypes.
+
+        - returns: The request.
+    */
+    public func validate<S : SequenceType where S.Generator.Element == String>(contentType acceptableContentTypes: S) -> Self {
+        return validate { _, response in
+            guard let validData = self.delegate.data where validData.length > 0 else { return .Success }
+
+            if let
+                responseContentType = response.MIMEType,
+                responseMIMEType = MIMEType(responseContentType)
+            {
+                for contentType in acceptableContentTypes {
+                    if let acceptableMIMEType = MIMEType(contentType) where acceptableMIMEType.matches(responseMIMEType) {
+                        return .Success
+                    }
+                }
+            } else {
+                for contentType in acceptableContentTypes {
+                    if let MIMEType = MIMEType(contentType) where MIMEType.type == "*" && MIMEType.subtype == "*" {
+                        return .Success
+                    }
+                }
+            }
+
+            let failureReason: String
+
+            if let responseContentType = response.MIMEType {
+                failureReason = (
+                    "Response content type \"\(responseContentType)\" does not match any acceptable " +
+                    "content types: \(acceptableContentTypes)"
+                )
+            } else {
+                failureReason = "Response content type was missing and acceptable content type does not match \"*/*\""
+            }
+
+            return .Failure(Error.errorWithCode(.ContentTypeValidationFailed, failureReason: failureReason))
+        }
+    }
+
+    // MARK: - Automatic
+
+    /**
+        Validates that the response has a status code in the default acceptable range of 200...299, and that the content 
+        type matches any specified in the Accept HTTP header field.
+
+        If validation fails, subsequent calls to response handlers will have an associated error.
+
+        - returns: The request.
+    */
+    public func validate() -> Self {
+        let acceptableStatusCodes: Range<Int> = 200..<300
+        let acceptableContentTypes: [String] = {
+            if let accept = request?.valueForHTTPHeaderField("Accept") {
+                return accept.componentsSeparatedByString(",")
+            }
+
+            return ["*/*"]
+        }()
+
+        return validate(statusCode: acceptableStatusCodes).validate(contentType: acceptableContentTypes)
+    }
+}

+ 19 - 0
Pods/AlamofireImage/LICENSE

@@ -0,0 +1,19 @@
+Copyright (c) 2015-2016 Alamofire Software Foundation (http://alamofire.org/)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.

File diff suppressed because it is too large
+ 540 - 0
Pods/AlamofireImage/README.md


+ 31 - 0
Pods/AlamofireImage/Source/Image.swift

@@ -0,0 +1,31 @@
+// Image.swift
+//
+// Copyright (c) 2015-2016 Alamofire Software Foundation (http://alamofire.org/)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+import Foundation
+
+#if os(iOS) || os(tvOS) || os(watchOS)
+import UIKit
+public typealias Image = UIImage
+#elseif os(OSX)
+import Cocoa
+public typealias Image = NSImage
+#endif

+ 330 - 0
Pods/AlamofireImage/Source/ImageCache.swift

@@ -0,0 +1,330 @@
+// ImageCache.swift
+//
+// Copyright (c) 2015-2016 Alamofire Software Foundation (http://alamofire.org/)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+import Alamofire
+import Foundation
+
+#if os(iOS) || os(tvOS) || os(watchOS)
+import UIKit
+#elseif os(OSX)
+import Cocoa
+#endif
+
+// MARK: ImageCache
+
+/// The `ImageCache` protocol defines a set of APIs for adding, removing and fetching images from a cache.
+public protocol ImageCache {
+    /// Adds the image to the cache with the given identifier.
+    func addImage(image: Image, withIdentifier identifier: String)
+
+    /// Removes the image from the cache matching the given identifier.
+    func removeImageWithIdentifier(identifier: String) -> Bool
+
+    /// Removes all images stored in the cache.
+    func removeAllImages() -> Bool
+
+    /// Returns the image in the cache associated with the given identifier.
+    func imageWithIdentifier(identifier: String) -> Image?
+}
+
+/// The `ImageRequestCache` protocol extends the `ImageCache` protocol by adding methods for adding, removing and
+/// fetching images from a cache given an `NSURLRequest` and additional identifier.
+public protocol ImageRequestCache: ImageCache {
+    /// Adds the image to the cache using an identifier created from the request and additional identifier.
+    func addImage(image: Image, forRequest request: NSURLRequest, withAdditionalIdentifier identifier: String?)
+
+    /// Removes the image from the cache using an identifier created from the request and additional identifier.
+    func removeImageForRequest(request: NSURLRequest, withAdditionalIdentifier identifier: String?) -> Bool
+
+    /// Returns the image from the cache associated with an identifier created from the request and additional identifier.
+    func imageForRequest(request: NSURLRequest, withAdditionalIdentifier identifier: String?) -> Image?
+}
+
+// MARK: -
+
+/// The `AutoPurgingImageCache` in an in-memory image cache used to store images up to a given memory capacity. When 
+/// the memory capacity is reached, the image cache is sorted by last access date, then the oldest image is continuously 
+/// purged until the preferred memory usage after purge is met. Each time an image is accessed through the cache, the 
+/// internal access date of the image is updated.
+public class AutoPurgingImageCache: ImageRequestCache {
+    private class CachedImage {
+        let image: Image
+        let identifier: String
+        let totalBytes: UInt64
+        var lastAccessDate: NSDate
+
+        init(_ image: Image, identifier: String) {
+            self.image = image
+            self.identifier = identifier
+            self.lastAccessDate = NSDate()
+
+            self.totalBytes = {
+                #if os(iOS) || os(tvOS) || os(watchOS)
+                    let size = CGSize(width: image.size.width * image.scale, height: image.size.height * image.scale)
+                #elseif os(OSX)
+                    let size = CGSize(width: image.size.width, height: image.size.height)
+                #endif
+
+                let bytesPerPixel: CGFloat = 4.0
+                let bytesPerRow = size.width * bytesPerPixel
+                let totalBytes = UInt64(bytesPerRow) * UInt64(size.height)
+
+                return totalBytes
+            }()
+        }
+
+        func accessImage() -> Image {
+            lastAccessDate = NSDate()
+            return image
+        }
+    }
+
+    // MARK: Properties
+
+    /// The current total memory usage in bytes of all images stored within the cache.
+    public var memoryUsage: UInt64 {
+        var memoryUsage: UInt64 = 0
+        dispatch_sync(synchronizationQueue) { memoryUsage = self.currentMemoryUsage }
+
+        return memoryUsage
+    }
+
+    /// The total memory capacity of the cache in bytes.
+    public let memoryCapacity: UInt64
+
+    /// The preferred memory usage after purge in bytes. During a purge, images will be purged until the memory 
+    /// capacity drops below this limit.
+    public let preferredMemoryUsageAfterPurge: UInt64
+
+    private let synchronizationQueue: dispatch_queue_t
+    private var cachedImages: [String: CachedImage]
+    private var currentMemoryUsage: UInt64
+
+    // MARK: Initialization
+
+    /**
+        Initialies the `AutoPurgingImageCache` instance with the given memory capacity and preferred memory usage 
+        after purge limit.
+
+        Please note, the memory capacity must always be greater than or equal to the preferred memory usage after purge.
+
+        - parameter memoryCapacity:                 The total memory capacity of the cache in bytes. `100 MB` by default.
+        - parameter preferredMemoryUsageAfterPurge: The preferred memory usage after purge in bytes. `60 MB` by default.
+
+        - returns: The new `AutoPurgingImageCache` instance.
+    */
+    public init(memoryCapacity: UInt64 = 100_000_000, preferredMemoryUsageAfterPurge: UInt64 = 60_000_000) {
+        self.memoryCapacity = memoryCapacity
+        self.preferredMemoryUsageAfterPurge = preferredMemoryUsageAfterPurge
+
+        precondition(
+            memoryCapacity >= preferredMemoryUsageAfterPurge,
+            "The `memoryCapacity` must be greater than or equal to `preferredMemoryUsageAfterPurge`"
+        )
+
+        self.cachedImages = [:]
+        self.currentMemoryUsage = 0
+
+        self.synchronizationQueue = {
+            let name = String(format: "com.alamofire.autopurgingimagecache-%08%08", arc4random(), arc4random())
+            return dispatch_queue_create(name, DISPATCH_QUEUE_CONCURRENT)
+        }()
+
+        #if os(iOS)
+            NSNotificationCenter.defaultCenter().addObserver(
+                self,
+                selector: "removeAllImages",
+                name: UIApplicationDidReceiveMemoryWarningNotification,
+                object: nil
+            )
+        #endif
+    }
+
+    deinit {
+        NSNotificationCenter.defaultCenter().removeObserver(self)
+    }
+
+    // MARK: Add Image to Cache
+
+    /**
+        Adds the image to the cache using an identifier created from the request and optional identifier.
+
+        - parameter image:      The image to add to the cache.
+        - parameter request:    The request used to generate the image's unique identifier.
+        - parameter identifier: The additional identifier to append to the image's unique identifier.
+    */
+    public func addImage(image: Image, forRequest request: NSURLRequest, withAdditionalIdentifier identifier: String? = nil) {
+        let requestIdentifier = imageCacheKeyFromURLRequest(request, withAdditionalIdentifier: identifier)
+        addImage(image, withIdentifier: requestIdentifier)
+    }
+
+    /**
+        Adds the image to the cache with the given identifier.
+
+        - parameter image:      The image to add to the cache.
+        - parameter identifier: The identifier to use to uniquely identify the image.
+    */
+    public func addImage(image: Image, withIdentifier identifier: String) {
+        dispatch_barrier_async(synchronizationQueue) {
+            let cachedImage = CachedImage(image, identifier: identifier)
+
+            if let previousCachedImage = self.cachedImages[identifier] {
+                self.currentMemoryUsage -= previousCachedImage.totalBytes
+            }
+
+            self.cachedImages[identifier] = cachedImage
+            self.currentMemoryUsage += cachedImage.totalBytes
+        }
+
+        dispatch_barrier_async(synchronizationQueue) {
+            if self.currentMemoryUsage > self.memoryCapacity {
+                let bytesToPurge = self.currentMemoryUsage - self.preferredMemoryUsageAfterPurge
+
+                var sortedImages = [CachedImage](self.cachedImages.values)
+                sortedImages.sortInPlace {
+                    let date1 = $0.lastAccessDate
+                    let date2 = $1.lastAccessDate
+
+                    return date1.timeIntervalSinceDate(date2) < 0.0
+                }
+
+                var bytesPurged = UInt64(0)
+
+                for cachedImage in sortedImages {
+                    self.cachedImages.removeValueForKey(cachedImage.identifier)
+                    bytesPurged += cachedImage.totalBytes
+
+                    if bytesPurged >= bytesToPurge {
+                        break
+                    }
+                }
+
+                self.currentMemoryUsage -= bytesPurged
+            }
+        }
+    }
+
+    // MARK: Remove Image from Cache
+
+    /**
+        Removes the image from the cache using an identifier created from the request and optional identifier.
+
+        - parameter request:    The request used to generate the image's unique identifier.
+        - parameter identifier: The additional identifier to append to the image's unique identifier.
+
+        - returns: `true` if the image was removed, `false` otherwise.
+    */
+    public func removeImageForRequest(request: NSURLRequest, withAdditionalIdentifier identifier: String?) -> Bool {
+        let requestIdentifier = imageCacheKeyFromURLRequest(request, withAdditionalIdentifier: identifier)
+        return removeImageWithIdentifier(requestIdentifier)
+    }
+
+    /**
+        Removes the image from the cache matching the given identifier.
+
+        - parameter identifier: The unique identifier for the image.
+
+        - returns: `true` if the image was removed, `false` otherwise.
+    */
+    public func removeImageWithIdentifier(identifier: String) -> Bool {
+        var removed = false
+
+        dispatch_barrier_async(synchronizationQueue) {
+            if let cachedImage = self.cachedImages.removeValueForKey(identifier) {
+                self.currentMemoryUsage -= cachedImage.totalBytes
+                removed = true
+            }
+        }
+
+        return removed
+    }
+
+    /**
+        Removes all images stored in the cache.
+
+        - returns: `true` if images were removed from the cache, `false` otherwise.
+    */
+    @objc public func removeAllImages() -> Bool {
+        var removed = false
+
+        dispatch_sync(synchronizationQueue) {
+            if !self.cachedImages.isEmpty {
+                self.cachedImages.removeAll()
+                self.currentMemoryUsage = 0
+
+                removed = true
+            }
+        }
+
+        return removed
+    }
+
+    // MARK: Fetch Image from Cache
+
+    /**
+        Returns the image from the cache associated with an identifier created from the request and optional identifier.
+
+        - parameter request:    The request used to generate the image's unique identifier.
+        - parameter identifier: The additional identifier to append to the image's unique identifier.
+
+        - returns: The image if it is stored in the cache, `nil` otherwise.
+    */
+    public func imageForRequest(request: NSURLRequest, withAdditionalIdentifier identifier: String? = nil) -> Image? {
+        let requestIdentifier = imageCacheKeyFromURLRequest(request, withAdditionalIdentifier: identifier)
+        return imageWithIdentifier(requestIdentifier)
+    }
+
+    /**
+        Returns the image in the cache associated with the given identifier.
+
+        - parameter identifier: The unique identifier for the image.
+
+        - returns: The image if it is stored in the cache, `nil` otherwise.
+    */
+    public func imageWithIdentifier(identifier: String) -> Image? {
+        var image: Image?
+
+        dispatch_sync(synchronizationQueue) {
+            if let cachedImage = self.cachedImages[identifier] {
+                image = cachedImage.accessImage()
+            }
+        }
+
+        return image
+    }
+
+    // MARK: Private - Helper Methods
+
+    private func imageCacheKeyFromURLRequest(
+        request: NSURLRequest,
+        withAdditionalIdentifier identifier: String?)
+        -> String
+    {
+        var key = request.URLString
+
+        if let identifier = identifier {
+            key += "-\(identifier)"
+        }
+
+        return key
+    }
+}

+ 530 - 0
Pods/AlamofireImage/Source/ImageDownloader.swift

@@ -0,0 +1,530 @@
+// ImageDownloader.swift
+//
+// Copyright (c) 2015-2016 Alamofire Software Foundation (http://alamofire.org/)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+import Alamofire
+import Foundation
+
+#if os(iOS) || os(tvOS) || os(watchOS)
+import UIKit
+#elseif os(OSX)
+import Cocoa
+#endif
+
+/// The `RequestReceipt` is an object vended by the `ImageDownloader` when starting a download request. It can be used 
+/// to cancel active requests running on the `ImageDownloader` session. As a general rule, image download requests 
+/// should be cancelled using the `RequestReceipt` instead of calling `cancel` directly on the `request` itself. The 
+/// `ImageDownloader` is optimized to handle duplicate request scenarios as well as pending versus active downloads.
+public class RequestReceipt {
+    /// The download request created by the `ImageDownloader`.
+    public let request: Request
+
+    /// The unique identifier for the image filters and completion handlers when duplicate requests are made.
+    public let receiptID: String
+
+    init(request: Request, receiptID: String) {
+        self.request = request
+        self.receiptID = receiptID
+    }
+}
+
+/// The `ImageDownloader` class is responsible for downloading images in parallel on a prioritized queue. Incoming
+/// downloads are added to the front or back of the queue depending on the download prioritization. Each downloaded 
+/// image is cached in the underlying `NSURLCache` as well as the in-memory image cache that supports image filters. 
+/// By default, any download request with a cached image equivalent in the image cache will automatically be served the
+/// cached image representation. Additional advanced features include supporting multiple image filters and completion 
+/// handlers for a single request.
+public class ImageDownloader {
+    /// The completion handler closure used when an image download completes.
+    public typealias CompletionHandler = Response<Image, NSError> -> Void
+
+    /**
+        Defines the order prioritization of incoming download requests being inserted into the queue.
+
+        - FIFO: All incoming downloads are added to the back of the queue.
+        - LIFO: All incoming downloads are added to the front of the queue.
+    */
+    public enum DownloadPrioritization {
+        case FIFO, LIFO
+    }
+
+    class ResponseHandler {
+        let identifier: String
+        let request: Request
+        var operations: [(id: String, filter: ImageFilter?, completion: CompletionHandler?)]
+
+        init(request: Request, id: String, filter: ImageFilter?, completion: CompletionHandler?) {
+            self.request = request
+            self.identifier = ImageDownloader.identifierForURLRequest(request.request!)
+            self.operations = [(id: id, filter: filter, completion: completion)]
+        }
+    }
+
+    // MARK: - Properties
+
+    /// The image cache used to store all downloaded images in.
+    public let imageCache: ImageRequestCache?
+
+    /// The credential used for authenticating each download request.
+    public private(set) var credential: NSURLCredential?
+
+    /// The underlying Alamofire `Manager` instance used to handle all download requests.
+    public let sessionManager: Alamofire.Manager
+
+    let downloadPrioritization: DownloadPrioritization
+    let maximumActiveDownloads: Int
+
+    var activeRequestCount = 0
+    var queuedRequests: [Request] = []
+    var responseHandlers: [String: ResponseHandler] = [:]
+
+    private let synchronizationQueue: dispatch_queue_t = {
+        let name = String(format: "com.alamofire.imagedownloader.synchronizationqueue-%08%08", arc4random(), arc4random())
+        return dispatch_queue_create(name, DISPATCH_QUEUE_SERIAL)
+    }()
+
+    private let responseQueue: dispatch_queue_t = {
+        let name = String(format: "com.alamofire.imagedownloader.responsequeue-%08%08", arc4random(), arc4random())
+        return dispatch_queue_create(name, DISPATCH_QUEUE_CONCURRENT)
+    }()
+
+    // MARK: - Initialization
+
+    /// The default instance of `ImageDownloader` initialized with default values.
+    public static let defaultInstance = ImageDownloader()
+
+    /**
+        Creates a default `NSURLSessionConfiguration` with common usage parameter values.
+    
+        - returns: The default `NSURLSessionConfiguration` instance.
+    */
+    public class func defaultURLSessionConfiguration() -> NSURLSessionConfiguration {
+        let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
+
+        configuration.HTTPAdditionalHeaders = Manager.defaultHTTPHeaders
+        configuration.HTTPShouldSetCookies = true
+        configuration.HTTPShouldUsePipelining = false
+
+        configuration.requestCachePolicy = .UseProtocolCachePolicy
+        configuration.allowsCellularAccess = true
+        configuration.timeoutIntervalForRequest = 60
+
+        configuration.URLCache = ImageDownloader.defaultURLCache()
+
+        return configuration
+    }
+
+    /**
+        Creates a default `NSURLCache` with common usage parameter values.
+
+        - returns: The default `NSURLCache` instance.
+    */
+    public class func defaultURLCache() -> NSURLCache {
+        return NSURLCache(
+            memoryCapacity: 20 * 1024 * 1024, // 20 MB
+            diskCapacity: 150 * 1024 * 1024,  // 150 MB
+            diskPath: "com.alamofire.imagedownloader"
+        )
+    }
+
+    /**
+        Initializes the `ImageDownloader` instance with the given configuration, download prioritization, maximum active 
+        download count and image cache.
+
+        - parameter configuration:          The `NSURLSessionConfiguration` to use to create the underlying Alamofire 
+                                            `Manager` instance.
+        - parameter downloadPrioritization: The download prioritization of the download queue. `.FIFO` by default.
+        - parameter maximumActiveDownloads: The maximum number of active downloads allowed at any given time.
+        - parameter imageCache:             The image cache used to store all downloaded images in.
+
+        - returns: The new `ImageDownloader` instance.
+    */
+    public init(
+        configuration: NSURLSessionConfiguration = ImageDownloader.defaultURLSessionConfiguration(),
+        downloadPrioritization: DownloadPrioritization = .FIFO,
+        maximumActiveDownloads: Int = 4,
+        imageCache: ImageRequestCache? = AutoPurgingImageCache())
+    {
+        self.sessionManager = Alamofire.Manager(configuration: configuration)
+        self.sessionManager.startRequestsImmediately = false
+
+        self.downloadPrioritization = downloadPrioritization
+        self.maximumActiveDownloads = maximumActiveDownloads
+        self.imageCache = imageCache
+    }
+
+    /**
+        Initializes the `ImageDownloader` instance with the given sesion manager, download prioritization, maximum
+        active download count and image cache.
+
+        - parameter sessionManager:         The Alamofire `Manager` instance to handle all download requests.
+        - parameter downloadPrioritization: The download prioritization of the download queue. `.FIFO` by default.
+        - parameter maximumActiveDownloads: The maximum number of active downloads allowed at any given time.
+        - parameter imageCache:             The image cache used to store all downloaded images in.
+
+        - returns: The new `ImageDownloader` instance.
+    */
+    public init(
+        sessionManager: Manager,
+        downloadPrioritization: DownloadPrioritization = .FIFO,
+        maximumActiveDownloads: Int = 4,
+        imageCache: ImageRequestCache? = AutoPurgingImageCache())
+    {
+        self.sessionManager = sessionManager
+        self.sessionManager.startRequestsImmediately = false
+
+        self.downloadPrioritization = downloadPrioritization
+        self.maximumActiveDownloads = maximumActiveDownloads
+        self.imageCache = imageCache
+    }
+
+    // MARK: - Authentication
+
+    /**
+        Associates an HTTP Basic Auth credential with all future download requests.
+
+        - parameter user:        The user.
+        - parameter password:    The password.
+        - parameter persistence: The URL credential persistence. `.ForSession` by default.
+    */
+    public func addAuthentication(
+        user user: String,
+        password: String,
+        persistence: NSURLCredentialPersistence = .ForSession)
+    {
+        let credential = NSURLCredential(user: user, password: password, persistence: persistence)
+        addAuthentication(usingCredential: credential)
+    }
+
+    /**
+        Associates the specified credential with all future download requests.
+
+        - parameter credential: The credential.
+    */
+    public func addAuthentication(usingCredential credential: NSURLCredential) {
+        dispatch_sync(synchronizationQueue) {
+            self.credential = credential
+        }
+    }
+
+    // MARK: - Download
+
+    /**
+        Creates a download request using the internal Alamofire `Manager` instance for the specified URL request.
+    
+        If the same download request is already in the queue or currently being downloaded, the filter and completion
+        handler are appended to the already existing request. Once the request completes, all filters and completion
+        handlers attached to the request are executed in the order they were added. Additionally, any filters attached
+        to the request with the same identifiers are only executed once. The resulting image is then passed into each
+        completion handler paired with the filter.
+    
+        You should not attempt to directly cancel the `request` inside the request receipt since other callers may be
+        relying on the completion of that request. Instead, you should call `cancelRequestForRequestReceipt` with the
+        returned request receipt to allow the `ImageDownloader` to optimize the cancellation on behalf of all active
+        callers.
+
+        - parameter URLRequest: The URL request.
+        - parameter filter      The image filter to apply to the image after the download is complete. Defaults to `nil`.
+        - parameter completion: The closure called when the download request is complete.
+
+        - returns: The request receipt for the download request if available. `nil` if the image is stored in the image
+                   cache and the URL request cache policy allows the cache to be used.
+    */
+    public func downloadImage(
+        URLRequest URLRequest: URLRequestConvertible,
+        filter: ImageFilter? = nil,
+        completion: CompletionHandler? = nil)
+        -> RequestReceipt?
+    {
+        return downloadImage(
+            URLRequest: URLRequest,
+            receiptID: NSUUID().UUIDString,
+            filter: filter,
+            completion: completion
+        )
+    }
+
+    func downloadImage(
+        URLRequest URLRequest: URLRequestConvertible,
+        receiptID: String,
+        filter: ImageFilter?,
+        completion: CompletionHandler?)
+        -> RequestReceipt?
+    {
+        var request: Request!
+
+        dispatch_sync(synchronizationQueue) {
+            // 1) Append the filter and completion handler to a pre-existing request if it already exists
+            let identifier = ImageDownloader.identifierForURLRequest(URLRequest)
+
+            if let responseHandler = self.responseHandlers[identifier] {
+                responseHandler.operations.append(id: receiptID, filter: filter, completion: completion)
+                request = responseHandler.request
+                return
+            }
+
+            // 2) Attempt to load the image from the image cache if the cache policy allows it
+            switch URLRequest.URLRequest.cachePolicy {
+            case .UseProtocolCachePolicy, .ReturnCacheDataElseLoad, .ReturnCacheDataDontLoad:
+                if let image = self.imageCache?.imageForRequest(
+                    URLRequest.URLRequest,
+                    withAdditionalIdentifier: filter?.identifier)
+                {
+                    dispatch_async(dispatch_get_main_queue()) {
+                        let response = Response<Image, NSError>(
+                            request: URLRequest.URLRequest,
+                            response: nil,
+                            data: nil,
+                            result: .Success(image)
+                        )
+
+                        completion?(response)
+                    }
+
+                    return
+                }
+            default:
+                break
+            }
+
+            // 3) Create the request and set up authentication, validation and response serialization
+            request = self.sessionManager.request(URLRequest)
+
+            if let credential = self.credential {
+                request.authenticate(usingCredential: credential)
+            }
+
+            request.validate()
+            request.response(
+                queue: self.responseQueue,
+                responseSerializer: Request.imageResponseSerializer(),
+                completionHandler: { [weak self] response in
+                    guard let strongSelf = self, let request = response.request else { return }
+
+                    let responseHandler = strongSelf.safelyRemoveResponseHandlerWithIdentifier(identifier)
+
+                    switch response.result {
+                    case .Success(let image):
+                        var filteredImages: [String: Image] = [:]
+
+                        for (_, filter, completion) in responseHandler.operations {
+                            var filteredImage: Image
+
+                            if let filter = filter {
+                                if let alreadyFilteredImage = filteredImages[filter.identifier] {
+                                    filteredImage = alreadyFilteredImage
+                                } else {
+                                    filteredImage = filter.filter(image)
+                                    filteredImages[filter.identifier] = filteredImage
+                                }
+                            } else {
+                                filteredImage = image
+                            }
+
+                            strongSelf.imageCache?.addImage(
+                                filteredImage,
+                                forRequest: request,
+                                withAdditionalIdentifier: filter?.identifier
+                            )
+
+                            dispatch_async(dispatch_get_main_queue()) {
+                                let response = Response<Image, NSError>(
+                                    request: response.request,
+                                    response: response.response,
+                                    data: response.data,
+                                    result: .Success(filteredImage),
+                                    timeline: response.timeline
+                                )
+
+                                completion?(response)
+                            }
+                        }
+                    case .Failure:
+                        for (_, _, completion) in responseHandler.operations {
+                            dispatch_async(dispatch_get_main_queue()) { completion?(response) }
+                        }
+                    }
+
+                    strongSelf.safelyDecrementActiveRequestCount()
+                    strongSelf.safelyStartNextRequestIfNecessary()
+                }
+            )
+
+            // 4) Store the response handler for use when the request completes
+            let responseHandler = ResponseHandler(
+                request: request,
+                id: receiptID,
+                filter: filter,
+                completion: completion
+            )
+
+            self.responseHandlers[identifier] = responseHandler
+
+            // 5) Either start the request or enqueue it depending on the current active request count
+            if self.isActiveRequestCountBelowMaximumLimit() {
+                self.startRequest(request)
+            } else {
+                self.enqueueRequest(request)
+            }
+        }
+
+        if let request = request {
+            return RequestReceipt(request: request, receiptID: receiptID)
+        }
+
+        return nil
+    }
+
+    /**
+        Creates a download request using the internal Alamofire `Manager` instance for each specified URL request.
+
+        For each request, if the same download request is already in the queue or currently being downloaded, the
+        filter and completion handler are appended to the already existing request. Once the request completes, all
+        filters and completion handlers attached to the request are executed in the order they were added.
+        Additionally, any filters attached to the request with the same identifiers are only executed once. The
+        resulting image is then passed into each completion handler paired with the filter.
+
+        You should not attempt to directly cancel any of the `request`s inside the request receipts array since other
+        callers may be relying on the completion of that request. Instead, you should call
+        `cancelRequestForRequestReceipt` with the returned request receipt to allow the `ImageDownloader` to optimize
+        the cancellation on behalf of all active callers.
+
+        - parameter URLRequests: The URL requests.
+        - parameter filter       The image filter to apply to the image after each download is complete.
+        - parameter completion:  The closure called when each download request is complete.
+
+        - returns: The request receipts for the download requests if available. If an image is stored in the image
+                   cache and the URL request cache policy allows the cache to be used, a receipt will not be returned
+                   for that request.
+    */
+    public func downloadImages(
+        URLRequests URLRequests: [URLRequestConvertible],
+        filter: ImageFilter? = nil,
+        completion: CompletionHandler? = nil)
+        -> [RequestReceipt]
+    {
+        return URLRequests.flatMap { downloadImage(URLRequest: $0, filter: filter, completion: completion) }
+    }
+
+    /**
+        Cancels the request in the receipt by removing the response handler and cancelling the request if necessary.
+
+        If the request is pending in the queue, it will be cancelled if no other response handlers are registered with
+        the request. If the request is currently executing or is already completed, the response handler is removed and
+        will not be called.
+
+        - parameter requestReceipt: The request receipt to cancel.
+    */
+    public func cancelRequestForRequestReceipt(requestReceipt: RequestReceipt) {
+        dispatch_sync(synchronizationQueue) {
+            let identifier = ImageDownloader.identifierForURLRequest(requestReceipt.request.request!)
+            guard let responseHandler = self.responseHandlers[identifier] else { return }
+
+            if let index = responseHandler.operations.indexOf({ $0.id == requestReceipt.receiptID }) {
+                let operation = responseHandler.operations.removeAtIndex(index)
+
+                let response: Response<Image, NSError> = {
+                    let URLRequest = requestReceipt.request.request!
+                    let error: NSError = {
+                        let failureReason = "ImageDownloader cancelled URL request: \(URLRequest.URLString)"
+                        let userInfo = [NSLocalizedFailureReasonErrorKey: failureReason]
+                        return NSError(domain: Error.Domain, code: NSURLErrorCancelled, userInfo: userInfo)
+                    }()
+
+                    return Response(request: URLRequest, response: nil, data: nil, result: .Failure(error))
+                }()
+
+                dispatch_async(dispatch_get_main_queue()) { operation.completion?(response) }
+            }
+
+            if responseHandler.operations.isEmpty && requestReceipt.request.task.state == .Suspended {
+                requestReceipt.request.cancel()
+            }
+        }
+    }
+
+    // MARK: - Internal - Thread-Safe Request Methods
+
+    func safelyRemoveResponseHandlerWithIdentifier(identifier: String) -> ResponseHandler {
+        var responseHandler: ResponseHandler!
+
+        dispatch_sync(synchronizationQueue) {
+            responseHandler = self.responseHandlers.removeValueForKey(identifier)
+        }
+
+        return responseHandler
+    }
+
+    func safelyStartNextRequestIfNecessary() {
+        dispatch_sync(synchronizationQueue) {
+            guard self.isActiveRequestCountBelowMaximumLimit() else { return }
+
+            while (!self.queuedRequests.isEmpty) {
+                if let request = self.dequeueRequest() where request.task.state == .Suspended {
+                    self.startRequest(request)
+                    break
+                }
+            }
+        }
+    }
+
+    func safelyDecrementActiveRequestCount() {
+        dispatch_sync(self.synchronizationQueue) {
+            if self.activeRequestCount > 0 {
+                self.activeRequestCount -= 1
+            }
+        }
+    }
+
+    // MARK: - Internal - Non Thread-Safe Request Methods
+
+    func startRequest(request: Request) {
+        request.resume()
+        activeRequestCount += 1
+    }
+
+    func enqueueRequest(request: Request) {
+        switch downloadPrioritization {
+        case .FIFO:
+            queuedRequests.append(request)
+        case .LIFO:
+            queuedRequests.insert(request, atIndex: 0)
+        }
+    }
+
+    func dequeueRequest() -> Request? {
+        var request: Request?
+
+        if !queuedRequests.isEmpty {
+            request = queuedRequests.removeFirst()
+        }
+
+        return request
+    }
+
+    func isActiveRequestCountBelowMaximumLimit() -> Bool {
+        return activeRequestCount < maximumActiveDownloads
+    }
+
+    static func identifierForURLRequest(URLRequest: URLRequestConvertible) -> String {
+        return URLRequest.URLRequest.URLString
+    }
+}

+ 428 - 0
Pods/AlamofireImage/Source/ImageFilter.swift

@@ -0,0 +1,428 @@
+// ImageFilter.swift
+//
+// Copyright (c) 2015-2016 Alamofire Software Foundation (http://alamofire.org/)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+import Foundation
+
+#if os(iOS) || os(tvOS) || os(watchOS)
+import UIKit
+#elseif os(OSX)
+import Cocoa
+#endif
+
+// MARK: ImageFilter
+
+/// The `ImageFilter` protocol defines properties for filtering an image as well as identification of the filter.
+public protocol ImageFilter {
+    /// A closure used to create an alternative representation of the given image.
+    var filter: Image -> Image { get }
+
+    /// The string used to uniquely identify the filter operation.
+    var identifier: String { get }
+}
+
+extension ImageFilter {
+    /// The unique identifier for any `ImageFilter` type.
+    public var identifier: String { return "\(self.dynamicType)" }
+}
+
+// MARK: - Sizable
+
+/// The `Sizable` protocol defines a size property intended for use with `ImageFilter` types.
+public protocol Sizable {
+    /// The size of the type.
+    var size: CGSize { get }
+}
+
+extension ImageFilter where Self: Sizable {
+    /// The unique idenitifier for an `ImageFilter` conforming to the `Sizable` protocol.
+    public var identifier: String {
+        let width = Int64(round(size.width))
+        let height = Int64(round(size.height))
+
+        return "\(self.dynamicType)-size:(\(width)x\(height))"
+    }
+}
+
+// MARK: - Roundable
+
+/// The `Roundable` protocol defines a radius property intended for use with `ImageFilter` types.
+public protocol Roundable {
+    /// The radius of the type.
+    var radius: CGFloat { get }
+}
+
+extension ImageFilter where Self: Roundable {
+    /// The unique idenitifier for an `ImageFilter` conforming to the `Roundable` protocol.
+    public var identifier: String {
+        let radius = Int64(round(self.radius))
+        return "\(self.dynamicType)-radius:(\(radius))"
+    }
+}
+
+// MARK: - DynamicImageFilter
+
+/// The `DynamicImageFilter` class simplifies custom image filter creation by using a trailing closure initializer.
+public struct DynamicImageFilter: ImageFilter {
+    /// The string used to uniquely identify the image filter operation.
+    public let identifier: String
+
+    /// A closure used to create an alternative representation of the given image.
+    public let filter: Image -> Image
+
+    /**
+        Initializes the `DynamicImageFilter` instance with the specified identifier and filter closure.
+
+        - parameter identifier: The unique identifier of the filter.
+        - parameter filter:     A closure used to create an alternative representation of the given image.
+
+        - returns: The new `DynamicImageFilter` instance.
+    */
+    public init(_ identifier: String, filter: Image -> Image) {
+        self.identifier = identifier
+        self.filter = filter
+    }
+}
+
+// MARK: - CompositeImageFilter
+
+/// The `CompositeImageFilter` protocol defines an additional `filters` property to support multiple composite filters.
+public protocol CompositeImageFilter: ImageFilter {
+    /// The image filters to apply to the image in sequential order.
+    var filters: [ImageFilter] { get }
+}
+
+public extension CompositeImageFilter {
+    /// The unique idenitifier for any `CompositeImageFilter` type.
+    var identifier: String {
+        return filters.map { $0.identifier }.joinWithSeparator("_")
+    }
+
+    /// The filter closure for any `CompositeImageFilter` type.
+    var filter: Image -> Image {
+        return { image in
+            return self.filters.reduce(image) { $1.filter($0) }
+        }
+    }
+}
+
+// MARK: - DynamicCompositeImageFilter
+
+/// The `DynamicCompositeImageFilter` class is a composite image filter based on a specified array of filters.
+public struct DynamicCompositeImageFilter: CompositeImageFilter {
+    /// The image filters to apply to the image in sequential order.
+    public let filters: [ImageFilter]
+
+    /**
+        Initializes the `DynamicCompositeImageFilter` instance with the given filters.
+
+        - parameter filters: The filters taking part in the composite image filter.
+
+        - returns: The new `DynamicCompositeImageFilter` instance.
+    */
+    public init(_ filters: [ImageFilter]) {
+        self.filters = filters
+    }
+
+    /**
+        Initializes the `DynamicCompositeImageFilter` instance with the given filters.
+
+        - parameter filters: The filters taking part in the composite image filter.
+
+        - returns: The new `DynamicCompositeImageFilter` instance.
+    */
+    public init(_ filters: ImageFilter...) {
+        self.init(filters)
+    }
+}
+
+#if os(iOS) || os(tvOS) || os(watchOS)
+
+// MARK: - Single Pass Image Filters (iOS, tvOS and watchOS only) -
+
+/// Scales an image to a specified size.
+public struct ScaledToSizeFilter: ImageFilter, Sizable {
+    /// The size of the filter.
+    public let size: CGSize
+
+    /**
+        Initializes the `ScaledToSizeFilter` instance with the given size.
+
+        - parameter size: The size.
+
+        - returns: The new `ScaledToSizeFilter` instance.
+    */
+    public init(size: CGSize) {
+        self.size = size
+    }
+
+    /// The filter closure used to create the modified representation of the given image.
+    public var filter: Image -> Image {
+        return { image in
+            return image.af_imageScaledToSize(self.size)
+        }
+    }
+}
+
+// MARK: -
+
+/// Scales an image from the center while maintaining the aspect ratio to fit within a specified size.
+public struct AspectScaledToFitSizeFilter: ImageFilter, Sizable {
+    /// The size of the filter.
+    public let size: CGSize
+
+    /**
+        Initializes the `AspectScaledToFitSizeFilter` instance with the given size.
+
+        - parameter size: The size.
+
+        - returns: The new `AspectScaledToFitSizeFilter` instance.
+    */
+    public init(size: CGSize) {
+        self.size = size
+    }
+
+    /// The filter closure used to create the modified representation of the given image.
+    public var filter: Image -> Image {
+        return { image in
+            return image.af_imageAspectScaledToFitSize(self.size)
+        }
+    }
+}
+
+// MARK: -
+
+/// Scales an image from the center while maintaining the aspect ratio to fill a specified size. Any pixels that fall
+/// outside the specified size are clipped.
+public struct AspectScaledToFillSizeFilter: ImageFilter, Sizable {
+    /// The size of the filter.
+    public let size: CGSize
+
+    /**
+        Initializes the `AspectScaledToFillSizeFilter` instance with the given size.
+
+        - parameter size: The size.
+
+        - returns: The new `AspectScaledToFillSizeFilter` instance.
+    */
+    public init(size: CGSize) {
+        self.size = size
+    }
+
+    /// The filter closure used to create the modified representation of the given image.
+    public var filter: Image -> Image {
+        return { image in
+            return image.af_imageAspectScaledToFillSize(self.size)
+        }
+    }
+}
+
+// MARK: -
+
+/// Rounds the corners of an image to the specified radius.
+public struct RoundedCornersFilter: ImageFilter, Roundable {
+    /// The radius of the filter.
+    public let radius: CGFloat
+
+    /// Whether to divide the radius by the image scale.
+    public let divideRadiusByImageScale: Bool
+
+    /**
+        Initializes the `RoundedCornersFilter` instance with the given radius.
+
+        - parameter radius:                   The radius.
+        - parameter divideRadiusByImageScale: Whether to divide the radius by the image scale. Set to `true` when the
+                                              image has the same resolution for all screen scales such as @1x, @2x and
+                                              @3x (i.e. single image from web server). Set to `false` for images loaded
+                                              from an asset catalog with varying resolutions for each screen scale.
+                                              `false` by default.
+
+        - returns: The new `RoundedCornersFilter` instance.
+    */
+    public init(radius: CGFloat, divideRadiusByImageScale: Bool = false) {
+        self.radius = radius
+        self.divideRadiusByImageScale = divideRadiusByImageScale
+    }
+
+    /// The filter closure used to create the modified representation of the given image.
+    public var filter: Image -> Image {
+        return { image in
+            return image.af_imageWithRoundedCornerRadius(
+                self.radius,
+                divideRadiusByImageScale: self.divideRadiusByImageScale
+            )
+        }
+    }
+
+    /// The unique idenitifier for an `ImageFilter` conforming to the `Roundable` protocol.
+    public var identifier: String {
+        let radius = Int64(round(self.radius))
+        return "\(self.dynamicType)-radius:(\(radius))-divided:(\(divideRadiusByImageScale))"
+    }
+}
+
+// MARK: -
+
+/// Rounds the corners of an image into a circle.
+public struct CircleFilter: ImageFilter {
+    /**
+        Initializes the `CircleFilter` instance.
+
+        - returns: The new `CircleFilter` instance.
+    */
+    public init() {}
+
+    /// The filter closure used to create the modified representation of the given image.
+    public var filter: Image -> Image {
+        return { image in
+            return image.af_imageRoundedIntoCircle()
+        }
+    }
+}
+
+// MARK: -
+
+#if os(iOS) || os(tvOS)
+
+/// Blurs an image using a `CIGaussianBlur` filter with the specified blur radius.
+public struct BlurFilter: ImageFilter {
+    /// The blur radius of the filter.
+    let blurRadius: UInt
+
+    /**
+        Initializes the `BlurFilter` instance with the given blur radius.
+
+        - parameter blurRadius: The blur radius.
+
+        - returns: The new `BlurFilter` instance.
+    */
+    public init(blurRadius: UInt = 10) {
+        self.blurRadius = blurRadius
+    }
+
+    /// The filter closure used to create the modified representation of the given image.
+    public var filter: Image -> Image {
+        return { image in
+            let parameters = ["inputRadius": self.blurRadius]
+            return image.af_imageWithAppliedCoreImageFilter("CIGaussianBlur", filterParameters: parameters) ?? image
+        }
+    }
+}
+
+#endif
+
+// MARK: - Composite Image Filters (iOS, tvOS and watchOS only) -
+
+/// Scales an image to a specified size, then rounds the corners to the specified radius.
+public struct ScaledToSizeWithRoundedCornersFilter: CompositeImageFilter {
+    /**
+        Initializes the `ScaledToSizeWithRoundedCornersFilter` instance with the given size and radius.
+
+        - parameter size:                     The size.
+        - parameter radius:                   The radius.
+        - parameter divideRadiusByImageScale: Whether to divide the radius by the image scale. Set to `true` when the
+                                              image has the same resolution for all screen scales such as @1x, @2x and
+                                              @3x (i.e. single image from web server). Set to `false` for images loaded
+                                              from an asset catalog with varying resolutions for each screen scale.
+                                              `false` by default.
+
+        - returns: The new `ScaledToSizeWithRoundedCornersFilter` instance.
+    */
+    public init(size: CGSize, radius: CGFloat, divideRadiusByImageScale: Bool = false) {
+        self.filters = [
+            ScaledToSizeFilter(size: size),
+            RoundedCornersFilter(radius: radius, divideRadiusByImageScale: divideRadiusByImageScale)
+        ]
+    }
+
+    /// The image filters to apply to the image in sequential order.
+    public let filters: [ImageFilter]
+}
+
+// MARK: -
+
+/// Scales an image from the center while maintaining the aspect ratio to fit within a specified size, then rounds the 
+/// corners to the specified radius.
+public struct AspectScaledToFillSizeWithRoundedCornersFilter: CompositeImageFilter {
+    /**
+        Initializes the `AspectScaledToFillSizeWithRoundedCornersFilter` instance with the given size and radius.
+
+        - parameter size:                     The size.
+        - parameter radius:                   The radius.
+        - parameter divideRadiusByImageScale: Whether to divide the radius by the image scale. Set to `true` when the
+                                              image has the same resolution for all screen scales such as @1x, @2x and
+                                              @3x (i.e. single image from web server). Set to `false` for images loaded
+                                              from an asset catalog with varying resolutions for each screen scale.
+                                              `false` by default.
+
+        - returns: The new `AspectScaledToFillSizeWithRoundedCornersFilter` instance.
+    */
+    public init(size: CGSize, radius: CGFloat, divideRadiusByImageScale: Bool = false) {
+        self.filters = [
+            AspectScaledToFillSizeFilter(size: size),
+            RoundedCornersFilter(radius: radius, divideRadiusByImageScale: divideRadiusByImageScale)
+        ]
+    }
+
+    /// The image filters to apply to the image in sequential order.
+    public let filters: [ImageFilter]
+}
+
+// MARK: -
+
+/// Scales an image to a specified size, then rounds the corners into a circle.
+public struct ScaledToSizeCircleFilter: CompositeImageFilter {
+    /**
+        Initializes the `ScaledToSizeCircleFilter` instance with the given size.
+
+        - parameter size: The size.
+
+        - returns: The new `ScaledToSizeCircleFilter` instance.
+    */
+    public init(size: CGSize) {
+        self.filters = [ScaledToSizeFilter(size: size), CircleFilter()]
+    }
+
+    /// The image filters to apply to the image in sequential order.
+    public let filters: [ImageFilter]
+}
+
+// MARK: -
+
+/// Scales an image from the center while maintaining the aspect ratio to fit within a specified size, then rounds the
+/// corners into a circle.
+public struct AspectScaledToFillSizeCircleFilter: CompositeImageFilter {
+    /**
+        Initializes the `AspectScaledToFillSizeCircleFilter` instance with the given size.
+
+        - parameter size: The size.
+
+        - returns: The new `AspectScaledToFillSizeCircleFilter` instance.
+    */
+    public init(size: CGSize) {
+        self.filters = [AspectScaledToFillSizeFilter(size: size), CircleFilter()]
+    }
+
+    /// The image filters to apply to the image in sequential order.
+    public let filters: [ImageFilter]
+}
+
+#endif

+ 235 - 0
Pods/AlamofireImage/Source/Request+AlamofireImage.swift

@@ -0,0 +1,235 @@
+// Request+AlamofireImage.swift
+//
+// Copyright (c) 2015-2016 Alamofire Software Foundation (http://alamofire.org/)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+import Alamofire
+import Foundation
+
+#if os(iOS) || os(tvOS)
+import UIKit
+#elseif os(watchOS)
+import UIKit
+import WatchKit
+#elseif os(OSX)
+import Cocoa
+#endif
+
+extension Request {
+    static var acceptableImageContentTypes: Set<String> = [
+        "image/tiff",
+        "image/jpeg",
+        "image/gif",
+        "image/png",
+        "image/ico",
+        "image/x-icon",
+        "image/bmp",
+        "image/x-bmp",
+        "image/x-xbitmap",
+        "image/x-win-bitmap"
+    ]
+
+    /**
+        Adds the content types specified to the list of acceptable images content types for validation.
+
+        - parameter contentTypes: The additional content types.
+    */
+    public class func addAcceptableImageContentTypes(contentTypes: Set<String>) {
+        Request.acceptableImageContentTypes.unionInPlace(contentTypes)
+    }
+
+    // MARK: - iOS, tvOS and watchOS
+
+#if os(iOS) || os(tvOS) || os(watchOS)
+
+    /**
+        Creates a response serializer that returns an image initialized from the response data using the specified
+        image options.
+
+        - parameter imageScale:           The scale factor used when interpreting the image data to construct 
+                                          `responseImage`. Specifying a scale factor of 1.0 results in an image whose 
+                                          size matches the pixel-based dimensions of the image. Applying a different 
+                                          scale factor changes the size of the image as reported by the size property.
+                                          `Screen.scale` by default.
+        - parameter inflateResponseImage: Whether to automatically inflate response image data for compressed formats 
+                                          (such as PNG or JPEG). Enabling this can significantly improve drawing 
+                                          performance as it allows a bitmap representation to be constructed in the 
+                                          background rather than on the main thread. `true` by default.
+
+        - returns: An image response serializer.
+    */
+    public class func imageResponseSerializer(
+        imageScale imageScale: CGFloat = Request.imageScale,
+        inflateResponseImage: Bool = true)
+        -> ResponseSerializer<UIImage, NSError>
+    {
+        return ResponseSerializer { request, response, data, error in
+            guard error == nil else { return .Failure(error!) }
+
+            guard let validData = data where validData.length > 0 else {
+                return .Failure(Request.imageDataError())
+            }
+
+            guard Request.validateContentTypeForRequest(request, response: response) else {
+                return .Failure(Request.contentTypeValidationError())
+            }
+
+            do {
+                let image = try Request.imageFromResponseData(validData, imageScale: imageScale)
+                if inflateResponseImage { image.af_inflate() }
+
+                return .Success(image)
+            } catch {
+                return .Failure(error as NSError)
+            }
+        }
+    }
+
+    /**
+        Adds a handler to be called once the request has finished.
+
+        - parameter imageScale:           The scale factor used when interpreting the image data to construct 
+                                          `responseImage`. Specifying a scale factor of 1.0 results in an image whose 
+                                          size matches the pixel-based dimensions of the image. Applying a different 
+                                          scale factor changes the size of the image as reported by the size property.
+                                          This is set to the value of scale of the main screen by default, which 
+                                          automatically scales images for retina displays, for instance. 
+                                          `Screen.scale` by default.
+        - parameter inflateResponseImage: Whether to automatically inflate response image data for compressed formats 
+                                          (such as PNG or JPEG). Enabling this can significantly improve drawing 
+                                          performance as it allows a bitmap representation to be constructed in the 
+                                          background rather than on the main thread. `true` by default.
+        - parameter completionHandler:    A closure to be executed once the request has finished. The closure takes 4
+                                          arguments: the URL request, the URL response, if one was received, the image, 
+                                          if one could be created from the URL response and data, and any error produced 
+                                          while creating the image.
+
+        - returns: The request.
+    */
+    public func responseImage(
+        imageScale: CGFloat = Request.imageScale,
+        inflateResponseImage: Bool = true,
+        completionHandler: Response<Image, NSError> -> Void)
+        -> Self
+    {
+        return response(
+            responseSerializer: Request.imageResponseSerializer(
+                imageScale: imageScale,
+                inflateResponseImage: inflateResponseImage
+            ),
+            completionHandler: completionHandler
+        )
+    }
+
+    private class func imageFromResponseData(data: NSData, imageScale: CGFloat) throws -> UIImage {
+        if let image = UIImage.af_threadSafeImageWithData(data, scale: imageScale) {
+            return image
+        }
+
+        throw imageDataError()
+    }
+
+    private class var imageScale: CGFloat {
+        #if os(iOS) || os(tvOS)
+            return UIScreen.mainScreen().scale
+        #elseif os(watchOS)
+            return WKInterfaceDevice.currentDevice().screenScale
+        #endif
+    }
+
+#elseif os(OSX)
+
+    // MARK: - OSX
+
+    /**
+        Creates a response serializer that returns an image initialized from the response data.
+
+        - returns: An image response serializer.
+    */
+    public class func imageResponseSerializer() -> ResponseSerializer<NSImage, NSError> {
+        return ResponseSerializer { request, response, data, error in
+            guard error == nil else { return .Failure(error!) }
+
+            guard let validData = data where validData.length > 0 else {
+                return .Failure(Request.imageDataError())
+            }
+
+            guard Request.validateContentTypeForRequest(request, response: response) else {
+                return .Failure(Request.contentTypeValidationError())
+            }
+
+            guard let bitmapImage = NSBitmapImageRep(data: validData) else {
+                return .Failure(Request.imageDataError())
+            }
+
+            let image = NSImage(size: NSSize(width: bitmapImage.pixelsWide, height: bitmapImage.pixelsHigh))
+            image.addRepresentation(bitmapImage)
+
+            return .Success(image)
+        }
+    }
+
+    /**
+        Adds a handler to be called once the request has finished.
+
+        - parameter completionHandler: A closure to be executed once the request has finished. The closure takes 4
+                                       arguments: the URL request, the URL response, if one was received, the image, if 
+                                       one could be created from the URL response and data, and any error produced while 
+                                       creating the image.
+
+        - returns: The request.
+    */
+    public func responseImage(completionHandler: Response<Image, NSError> -> Void) -> Self {
+        return response(
+            responseSerializer: Request.imageResponseSerializer(),
+            completionHandler: completionHandler
+        )
+    }
+
+#endif
+
+    // MARK: - Private - Shared Helper Methods
+
+    private class func validateContentTypeForRequest(
+        request: NSURLRequest?,
+        response: NSHTTPURLResponse?)
+        -> Bool
+    {
+        if let URL = request?.URL where URL.fileURL {
+            return true
+        }
+
+        if let mimeType = response?.MIMEType where Request.acceptableImageContentTypes.contains(mimeType) {
+            return true
+        }
+
+        return false
+    }
+
+    private class func contentTypeValidationError() -> NSError {
+        let failureReason = "Failed to validate response due to unacceptable content type"
+        return Error.errorWithCode(NSURLErrorCannotDecodeContentData, failureReason: failureReason)
+    }
+
+    private class func imageDataError() -> NSError {
+        let failureReason = "Failed to create a valid Image from the response data"
+        return Error.errorWithCode(NSURLErrorCannotDecodeContentData, failureReason: failureReason)
+    }
+}

+ 405 - 0
Pods/AlamofireImage/Source/UIButton+AlamofireImage.swift

@@ -0,0 +1,405 @@
+// UIButton+AlamofireImage.swift
+//
+// Copyright (c) 2015-2016 Alamofire Software Foundation (http://alamofire.org/)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+import Alamofire
+import Foundation
+import UIKit
+
+extension UIButton {
+
+    // MARK: - Private - AssociatedKeys
+
+    private struct AssociatedKeys {
+        static var ImageDownloaderKey = "af_UIButton.ImageDownloader"
+        static var SharedImageDownloaderKey = "af_UIButton.SharedImageDownloader"
+        static var ImageReceiptsKey = "af_UIButton.ImageReceipts"
+        static var BackgroundImageReceiptsKey = "af_UIButton.BackgroundImageReceipts"
+    }
+
+    // MARK: - Properties
+
+    /// The instance image downloader used to download all images. If this property is `nil`, the `UIButton` will
+    /// fallback on the `af_sharedImageDownloader` for all downloads. The most common use case for needing to use a
+    /// custom instance image downloader is when images are behind different basic auth credentials.
+    public var af_imageDownloader: ImageDownloader? {
+        get {
+            return objc_getAssociatedObject(self, &AssociatedKeys.ImageDownloaderKey) as? ImageDownloader
+        }
+        set {
+            objc_setAssociatedObject(self, &AssociatedKeys.ImageDownloaderKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
+        }
+    }
+
+    /// The shared image downloader used to download all images. By default, this is the default `ImageDownloader`
+    /// instance backed with an `AutoPurgingImageCache` which automatically evicts images from the cache when the memory
+    /// capacity is reached or memory warning notifications occur. The shared image downloader is only used if the
+    /// `af_imageDownloader` is `nil`.
+    public class var af_sharedImageDownloader: ImageDownloader {
+        get {
+            guard let
+                downloader = objc_getAssociatedObject(self, &AssociatedKeys.SharedImageDownloaderKey) as? ImageDownloader
+            else {
+                return ImageDownloader.defaultInstance
+            }
+
+            return downloader
+        }
+        set {
+            objc_setAssociatedObject(self, &AssociatedKeys.SharedImageDownloaderKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
+        }
+    }
+
+    private var imageRequestReceipts: [UInt: RequestReceipt] {
+        get {
+            guard let
+                receipts = objc_getAssociatedObject(self, &AssociatedKeys.ImageReceiptsKey) as? [UInt: RequestReceipt]
+            else {
+                return [:]
+            }
+
+            return receipts
+        }
+        set {
+            objc_setAssociatedObject(self, &AssociatedKeys.ImageReceiptsKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
+        }
+    }
+
+    private var backgroundImageRequestReceipts: [UInt: RequestReceipt] {
+        get {
+            guard let
+                receipts = objc_getAssociatedObject(self, &AssociatedKeys.BackgroundImageReceiptsKey) as? [UInt: RequestReceipt]
+            else {
+                return [:]
+            }
+
+            return receipts
+        }
+        set {
+            objc_setAssociatedObject(self, &AssociatedKeys.BackgroundImageReceiptsKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
+        }
+    }
+
+    // MARK: - Image Downloads
+
+    /**
+        Asynchronously downloads an image from the specified URL and sets it once the request is finished.
+
+        If the image is cached locally, the image is set immediately. Otherwise the specified placehoder image will be
+        set immediately, and then the remote image will be set once the image request is finished.
+    
+        - parameter URL:                The URL used for your image request.
+        - parameter placeholderImage:   The image to be set initially until the image request finished. If `nil`, the
+                                        image will not change its image until the image request finishes.
+                                        Defaults to `nil`.
+        - parameter completion:         A closure to be executed when the image request finishes. The closure
+                                        has no return value and takes three arguments: the original request,
+                                        the response from the server and the result containing either the
+                                        image or the error that occurred. If the image was returned from the
+                                        image cache, the response will be `nil`. Defaults to `nil`.
+    */
+    public func af_setImageForState(
+        state: UIControlState,
+        URL: NSURL,
+        placeHolderImage: UIImage? = nil,
+        completion: (Response<UIImage, NSError> -> Void)? = nil)
+    {
+        af_setImageForState(state,
+            URLRequest: URLRequestWithURL(URL),
+            placeholderImage: placeHolderImage,
+            completion: completion)
+    }
+
+    /**
+        Asynchronously downloads an image from the specified URL request and sets it once the request is finished.
+
+        If the image is cached locally, the image is set immediately. Otherwise the specified placehoder image will be
+        set immediately, and then the remote image will be set once the image request is finished.
+
+        - parameter URLRequest:         The URL request.
+        - parameter placeholderImage:   The image to be set initially until the image request finished. If `nil`, the
+                                        image will not change its image until the image request finishes.
+                                        Defaults to `nil`.
+        - parameter completion:         A closure to be executed when the image request finishes. The closure
+                                        has no return value and takes three arguments: the original request,
+                                        the response from the server and the result containing either the
+                                        image or the error that occurred. If the image was returned from the
+                                        image cache, the response will be `nil`. Defaults to `nil`.
+    */
+    public func af_setImageForState(
+        state: UIControlState,
+        URLRequest: URLRequestConvertible,
+        placeholderImage: UIImage? = nil,
+        completion: (Response<UIImage, NSError> -> Void)? = nil)
+    {
+        guard !isImageURLRequest(URLRequest, equalToActiveRequestURLForState: state) else { return }
+
+        af_cancelImageRequestForState(state)
+
+        let imageDownloader = af_imageDownloader ?? UIButton.af_sharedImageDownloader
+        let imageCache = imageDownloader.imageCache
+
+        // Use the image from the image cache if it exists
+        if let image = imageCache?.imageForRequest(URLRequest.URLRequest, withAdditionalIdentifier: nil) {
+            let response = Response<UIImage, NSError>(
+                request: URLRequest.URLRequest,
+                response: nil,
+                data: nil,
+                result: .Success(image)
+            )
+
+            completion?(response)
+            setImage(image, forState: state)
+
+            return
+        }
+
+        // Set the placeholder since we're going to have to download
+        if let placeholderImage = placeholderImage { self.setImage(placeholderImage, forState: state)  }
+
+        // Generate a unique download id to check whether the active request has changed while downloading
+        let downloadID = NSUUID().UUIDString
+
+        // Download the image, then set the image for the control state
+        let requestReceipt = imageDownloader.downloadImage(
+            URLRequest: URLRequest,
+            receiptID: downloadID,
+            filter: nil,
+            completion: { [weak self] response in
+                guard let strongSelf = self else { return }
+
+                completion?(response)
+
+                guard
+                    strongSelf.isImageURLRequest(response.request, equalToActiveRequestURLForState: state) &&
+                    strongSelf.imageRequestReceiptForState(state)?.receiptID == downloadID
+                else {
+                    return
+                }
+
+                if let image = response.result.value {
+                    strongSelf.setImage(image, forState: state)
+                }
+
+                strongSelf.setImageRequestReceipt(nil, forState: state)
+            }
+        )
+
+        setImageRequestReceipt(requestReceipt, forState: state)
+    }
+
+    /**
+        Cancels the active download request for the image, if one exists.
+    */
+    public func af_cancelImageRequestForState(state: UIControlState) {
+        guard let receipt = imageRequestReceiptForState(state) else { return }
+
+        let imageDownloader = af_imageDownloader ?? UIButton.af_sharedImageDownloader
+        imageDownloader.cancelRequestForRequestReceipt(receipt)
+
+        setImageRequestReceipt(nil, forState: state)
+    }
+
+    // MARK: - Background Image Downloads
+
+    /**
+        Asynchronously downloads an image from the specified URL and sets it once the request is finished.
+
+        If the image is cached locally, the image is set immediately. Otherwise the specified placehoder image will be
+        set immediately, and then the remote image will be set once the image request is finished.
+
+        - parameter URL:                The URL used for the image request.
+        - parameter placeholderImage:   The image to be set initially until the image request finished. If `nil`, the
+                                        background image will not change its image until the image request finishes.
+                                        Defaults to `nil`.
+    */
+    public func af_setBackgroundImageForState(
+        state: UIControlState,
+        URL: NSURL,
+        placeHolderImage: UIImage? = nil,
+        completion: (Response<UIImage, NSError> -> Void)? = nil)
+    {
+        af_setBackgroundImageForState(state,
+            URLRequest: URLRequestWithURL(URL),
+            placeholderImage: placeHolderImage,
+            completion: completion)
+    }
+
+    /**
+        Asynchronously downloads an image from the specified URL request and sets it once the request is finished.
+
+        If the image is cached locally, the image is set immediately. Otherwise the specified placehoder image will be
+        set immediately, and then the remote image will be set once the image request is finished.
+
+        - parameter URLRequest:         The URL request.
+        - parameter placeholderImage:   The image to be set initially until the image request finished. If `nil`, the
+                                        background image will not change its image until the image request finishes.
+                                        Defaults to `nil`.
+        - parameter completion:         A closure to be executed when the image request finishes. The closure
+                                        has no return value and takes three arguments: the original request,
+                                        the response from the server and the result containing either the
+                                        image or the error that occurred. If the image was returned from the
+                                        image cache, the response will be `nil`. Defaults to `nil`.
+    */
+    public func af_setBackgroundImageForState(
+        state: UIControlState,
+        URLRequest: URLRequestConvertible,
+        placeholderImage: UIImage? = nil,
+        completion: (Response<UIImage, NSError> -> Void)? = nil)
+    {
+        guard !isImageURLRequest(URLRequest, equalToActiveRequestURLForState: state) else { return }
+
+        af_cancelBackgroundImageRequestForState(state)
+
+        let imageDownloader = af_imageDownloader ?? UIButton.af_sharedImageDownloader
+        let imageCache = imageDownloader.imageCache
+
+        // Use the image from the image cache if it exists
+        if let image = imageCache?.imageForRequest(URLRequest.URLRequest, withAdditionalIdentifier: nil) {
+            let response = Response<UIImage, NSError>(
+                request: URLRequest.URLRequest,
+                response: nil,
+                data: nil,
+                result: .Success(image)
+            )
+
+            completion?(response)
+            setBackgroundImage(image, forState: state)
+
+            return
+        }
+
+        // Set the placeholder since we're going to have to download
+        if let placeholderImage = placeholderImage { self.setBackgroundImage(placeholderImage, forState: state)  }
+
+        // Generate a unique download id to check whether the active request has changed while downloading
+        let downloadID = NSUUID().UUIDString
+
+        // Download the image, then set the image for the control state
+        let requestReceipt = imageDownloader.downloadImage(
+            URLRequest: URLRequest,
+            receiptID: downloadID,
+            filter: nil,
+            completion: { [weak self] response in
+                guard let strongSelf = self else { return }
+
+                completion?(response)
+
+                guard
+                    strongSelf.isBackgroundImageURLRequest(response.request, equalToActiveRequestURLForState: state) &&
+                    strongSelf.backgroundImageRequestReceiptForState(state)?.receiptID == downloadID
+                else {
+                    return
+                }
+
+                if let image = response.result.value {
+                    strongSelf.setBackgroundImage(image, forState: state)
+                }
+
+                strongSelf.setBackgroundImageRequestReceipt(nil, forState: state)
+            }
+        )
+
+        setBackgroundImageRequestReceipt(requestReceipt, forState: state)
+    }
+
+    /**
+        Cancels the active download request for the background image, if one exists.
+    */
+    public func af_cancelBackgroundImageRequestForState(state: UIControlState) {
+        guard let receipt = backgroundImageRequestReceiptForState(state) else { return }
+
+        let imageDownloader = af_imageDownloader ?? UIButton.af_sharedImageDownloader
+        imageDownloader.cancelRequestForRequestReceipt(receipt)
+
+        setBackgroundImageRequestReceipt(nil, forState: state)
+    }
+
+    // MARK: - Internal - Image Request Receipts
+
+    func imageRequestReceiptForState(state: UIControlState) -> RequestReceipt? {
+        guard let receipt = imageRequestReceipts[state.rawValue] else { return nil }
+        return receipt
+    }
+
+    func setImageRequestReceipt(receipt: RequestReceipt?, forState state: UIControlState) {
+        var receipts = imageRequestReceipts
+        receipts[state.rawValue] = receipt
+
+        imageRequestReceipts = receipts
+    }
+
+    // MARK: - Internal - Background Image Request Receipts
+
+    func backgroundImageRequestReceiptForState(state: UIControlState) -> RequestReceipt? {
+        guard let receipt = backgroundImageRequestReceipts[state.rawValue] else { return nil }
+        return receipt
+    }
+
+    func setBackgroundImageRequestReceipt(receipt: RequestReceipt?, forState state: UIControlState) {
+        var receipts = backgroundImageRequestReceipts
+        receipts[state.rawValue] = receipt
+
+        backgroundImageRequestReceipts = receipts
+    }
+
+    // MARK: - Private - URL Request Helpers
+
+    private func isImageURLRequest(
+        URLRequest: URLRequestConvertible?,
+        equalToActiveRequestURLForState state: UIControlState)
+        -> Bool
+    {
+        if let
+            currentRequest = imageRequestReceiptForState(state)?.request.task.originalRequest
+            where currentRequest.URLString == URLRequest?.URLRequest.URLString
+        {
+            return true
+        }
+
+        return false
+    }
+
+    private func isBackgroundImageURLRequest(
+        URLRequest: URLRequestConvertible?,
+        equalToActiveRequestURLForState state: UIControlState)
+        -> Bool
+    {
+        if let
+            currentRequest = backgroundImageRequestReceiptForState(state)?.request.task.originalRequest
+            where currentRequest.URLString == URLRequest?.URLRequest.URLString
+        {
+            return true
+        }
+
+        return false
+    }
+
+    private func URLRequestWithURL(URL: NSURL) -> NSURLRequest {
+        let mutableURLRequest = NSMutableURLRequest(URL: URL)
+
+        for mimeType in Request.acceptableImageContentTypes {
+            mutableURLRequest.addValue(mimeType, forHTTPHeaderField: "Accept")
+        }
+
+        return mutableURLRequest
+    }
+}

+ 325 - 0
Pods/AlamofireImage/Source/UIImage+AlamofireImage.swift

@@ -0,0 +1,325 @@
+// UIImage+AlamofireImage.swift
+//
+// Copyright (c) 2015-2016 Alamofire Software Foundation (http://alamofire.org/)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+import CoreGraphics
+import Foundation
+import UIKit
+
+#if os(iOS) || os(tvOS)
+import CoreImage
+#endif
+
+// MARK: Initialization
+
+private let lock = NSLock()
+
+extension UIImage {
+    /**
+        Initializes and returns the image object with the specified data in a thread-safe manner.
+
+        It has been reported that there are thread-safety issues when initializing large amounts of images 
+        simultaneously. In the event of these issues occurring, this method can be used in place of 
+        the `init?(data:)` method.
+
+        - parameter data: The data object containing the image data.
+
+        - returns: An initialized `UIImage` object, or `nil` if the method failed.
+    */
+    public static func af_threadSafeImageWithData(data: NSData) -> UIImage? {
+        lock.lock()
+        let image = UIImage(data: data)
+        lock.unlock()
+
+        return image
+    }
+
+    /**
+        Initializes and returns the image object with the specified data and scale in a thread-safe manner.
+
+        It has been reported that there are thread-safety issues when initializing large amounts of images
+        simultaneously. In the event of these issues occurring, this method can be used in place of
+        the `init?(data:scale:)` method.
+
+        - parameter data:  The data object containing the image data.
+        - parameter scale: The scale factor to assume when interpreting the image data. Applying a scale factor of 1.0 
+                           results in an image whose size matches the pixel-based dimensions of the image. Applying a 
+                           different scale factor changes the size of the image as reported by the size property.
+
+        - returns: An initialized `UIImage` object, or `nil` if the method failed.
+    */
+    public static func af_threadSafeImageWithData(data: NSData, scale: CGFloat) -> UIImage? {
+        lock.lock()
+        let image = UIImage(data: data, scale: scale)
+        lock.unlock()
+
+        return image
+    }
+}
+
+// MARK: - Inflation
+
+extension UIImage {
+    private struct AssociatedKeys {
+        static var InflatedKey = "af_UIImage.Inflated"
+    }
+
+    /// Returns whether the image is inflated.
+    public var af_inflated: Bool {
+        get {
+            if let inflated = objc_getAssociatedObject(self, &AssociatedKeys.InflatedKey) as? Bool {
+                return inflated
+            } else {
+                return false
+            }
+        }
+        set(inflated) {
+            objc_setAssociatedObject(self, &AssociatedKeys.InflatedKey, inflated, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
+        }
+    }
+
+    /**
+        Inflates the underlying compressed image data to be backed by an uncompressed bitmap representation.
+
+        Inflating compressed image formats (such as PNG or JPEG) can significantly improve drawing performance as it
+        allows a bitmap representation to be constructed in the background rather than on the main thread.
+    */
+    public func af_inflate() {
+        guard !af_inflated else { return }
+
+        af_inflated = true
+        CGDataProviderCopyData(CGImageGetDataProvider(CGImage))
+    }
+}
+
+// MARK: - Alpha
+
+extension UIImage {
+    /// Returns whether the image contains an alpha component.
+    public var af_containsAlphaComponent: Bool {
+        let alphaInfo = CGImageGetAlphaInfo(CGImage)
+
+        return (
+            alphaInfo == .First ||
+            alphaInfo == .Last ||
+            alphaInfo == .PremultipliedFirst ||
+            alphaInfo == .PremultipliedLast
+        )
+    }
+
+    /// Returns whether the image is opaque.
+    public var af_isOpaque: Bool { return !af_containsAlphaComponent }
+}
+
+// MARK: - Scaling
+
+extension UIImage {
+    /**
+        Returns a new version of the image scaled to the specified size.
+
+        - parameter size: The size to use when scaling the new image.
+
+        - returns: A new image object.
+    */
+    public func af_imageScaledToSize(size: CGSize) -> UIImage {
+        UIGraphicsBeginImageContextWithOptions(size, af_isOpaque, 0.0)
+        drawInRect(CGRect(origin: CGPointZero, size: size))
+
+        let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
+        UIGraphicsEndImageContext()
+
+        return scaledImage
+    }
+
+    /**
+        Returns a new version of the image scaled from the center while maintaining the aspect ratio to fit within 
+        a specified size.
+
+        The resulting image contains an alpha component used to pad the width or height with the necessary transparent
+        pixels to fit the specified size. In high performance critical situations, this may not be the optimal approach.
+        To maintain an opaque image, you could compute the `scaledSize` manually, then use the `af_imageScaledToSize`
+        method in conjunction with a `.Center` content mode to achieve the same visual result.
+
+        - parameter size: The size to use when scaling the new image.
+
+        - returns: A new image object.
+    */
+    public func af_imageAspectScaledToFitSize(size: CGSize) -> UIImage {
+        let imageAspectRatio = self.size.width / self.size.height
+        let canvasAspectRatio = size.width / size.height
+
+        var resizeFactor: CGFloat
+
+        if imageAspectRatio > canvasAspectRatio {
+            resizeFactor = size.width / self.size.width
+        } else {
+            resizeFactor = size.height / self.size.height
+        }
+
+        let scaledSize = CGSize(width: self.size.width * resizeFactor, height: self.size.height * resizeFactor)
+        let origin = CGPoint(x: (size.width - scaledSize.width) / 2.0, y: (size.height - scaledSize.height) / 2.0)
+
+        UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
+        drawInRect(CGRect(origin: origin, size: scaledSize))
+
+        let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
+        UIGraphicsEndImageContext()
+
+        return scaledImage
+    }
+
+    /**
+        Returns a new version of the image scaled from the center while maintaining the aspect ratio to fill a
+        specified size. Any pixels that fall outside the specified size are clipped.
+
+        - parameter size: The size to use when scaling the new image.
+
+        - returns: A new image object.
+    */
+    public func af_imageAspectScaledToFillSize(size: CGSize) -> UIImage {
+        let imageAspectRatio = self.size.width / self.size.height
+        let canvasAspectRatio = size.width / size.height
+
+        var resizeFactor: CGFloat
+
+        if imageAspectRatio > canvasAspectRatio {
+            resizeFactor = size.height / self.size.height
+        } else {
+            resizeFactor = size.width / self.size.width
+        }
+
+        let scaledSize = CGSize(width: self.size.width * resizeFactor, height: self.size.height * resizeFactor)
+        let origin = CGPoint(x: (size.width - scaledSize.width) / 2.0, y: (size.height - scaledSize.height) / 2.0)
+
+        UIGraphicsBeginImageContextWithOptions(size, af_isOpaque, 0.0)
+        drawInRect(CGRect(origin: origin, size: scaledSize))
+
+        let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
+        UIGraphicsEndImageContext()
+
+        return scaledImage
+    }
+}
+
+// MARK: - Rounded Corners
+
+extension UIImage {
+    /**
+        Returns a new version of the image with the corners rounded to the specified radius.
+
+        - parameter radius:                   The radius to use when rounding the new image.
+        - parameter divideRadiusByImageScale: Whether to divide the radius by the image scale. Set to `true` when the 
+                                              image has the same resolution for all screen scales such as @1x, @2x and 
+                                              @3x (i.e. single image from web server). Set to `false` for images loaded 
+                                              from an asset catalog with varying resolutions for each screen scale. 
+                                              `false` by default.
+
+        - returns: A new image object.
+    */
+    public func af_imageWithRoundedCornerRadius(radius: CGFloat, divideRadiusByImageScale: Bool = false) -> UIImage {
+        UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
+
+        let scaledRadius = divideRadiusByImageScale ? radius / scale : radius
+
+        let clippingPath = UIBezierPath(roundedRect: CGRect(origin: CGPointZero, size: size), cornerRadius: scaledRadius)
+        clippingPath.addClip()
+
+        drawInRect(CGRect(origin: CGPointZero, size: size))
+
+        let roundedImage = UIGraphicsGetImageFromCurrentImageContext()
+        UIGraphicsEndImageContext()
+
+        return roundedImage
+    }
+
+    /**
+        Returns a new version of the image rounded into a circle.
+
+        - returns: A new image object.
+    */
+    public func af_imageRoundedIntoCircle() -> UIImage {
+        let radius = min(size.width, size.height) / 2.0
+        var squareImage = self
+
+        if size.width != size.height {
+            let squareDimension = min(size.width, size.height)
+            let squareSize = CGSize(width: squareDimension, height: squareDimension)
+            squareImage = af_imageAspectScaledToFillSize(squareSize)
+        }
+
+        UIGraphicsBeginImageContextWithOptions(squareImage.size, false, 0.0)
+
+        let clippingPath = UIBezierPath(
+            roundedRect: CGRect(origin: CGPointZero, size: squareImage.size),
+            cornerRadius: radius
+        )
+
+        clippingPath.addClip()
+
+        squareImage.drawInRect(CGRect(origin: CGPointZero, size: squareImage.size))
+
+        let roundedImage = UIGraphicsGetImageFromCurrentImageContext()
+        UIGraphicsEndImageContext()
+
+        return roundedImage
+    }
+}
+
+#if os(iOS) || os(tvOS)
+
+// MARK: - Core Image Filters
+
+extension UIImage {
+    /**
+        Returns a new version of the image using a CoreImage filter with the specified name and parameters.
+
+        - parameter filterName:       The name of the CoreImage filter to use on the new image.
+        - parameter filterParameters: The parameters to apply to the CoreImage filter.
+
+        - returns: A new image object, or `nil` if the filter failed for any reason.
+    */
+    public func af_imageWithAppliedCoreImageFilter(
+        filterName: String,
+        filterParameters: [String: AnyObject]? = nil) -> UIImage?
+    {
+        var image: CoreImage.CIImage? = CIImage
+
+        if image == nil, let CGImage = self.CGImage {
+            image = CoreImage.CIImage(CGImage: CGImage)
+        }
+
+        guard let coreImage = image else { return nil }
+
+        let context = CIContext(options: [kCIContextPriorityRequestLow: true])
+
+        var parameters: [String: AnyObject] = filterParameters ?? [:]
+        parameters[kCIInputImageKey] = coreImage
+
+        guard let filter = CIFilter(name: filterName, withInputParameters: parameters) else { return nil }
+        guard let outputImage = filter.outputImage else { return nil }
+
+        let cgImageRef = context.createCGImage(outputImage, fromRect: outputImage.extent)
+
+        return UIImage(CGImage: cgImageRef, scale: scale, orientation: imageOrientation)
+    }
+}
+
+#endif

+ 373 - 0
Pods/AlamofireImage/Source/UIImageView+AlamofireImage.swift

@@ -0,0 +1,373 @@
+// UIImageView+AlamofireImage.swift
+//
+// Copyright (c) 2015-2016 Alamofire Software Foundation (http://alamofire.org/)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+import Alamofire
+import Foundation
+import UIKit
+
+extension UIImageView {
+
+    // MARK: - ImageTransition
+
+    /// Used to wrap all `UIView` animation transition options alongside a duration.
+    public enum ImageTransition {
+        case None
+        case CrossDissolve(NSTimeInterval)
+        case CurlDown(NSTimeInterval)
+        case CurlUp(NSTimeInterval)
+        case FlipFromBottom(NSTimeInterval)
+        case FlipFromLeft(NSTimeInterval)
+        case FlipFromRight(NSTimeInterval)
+        case FlipFromTop(NSTimeInterval)
+        case Custom(
+            duration: NSTimeInterval,
+            animationOptions: UIViewAnimationOptions,
+            animations: (UIImageView, Image) -> Void,
+            completion: (Bool -> Void)?
+        )
+
+        /// The duration of the image transition in seconds.
+        public var duration: NSTimeInterval {
+            switch self {
+            case None:
+                return 0.0
+            case CrossDissolve(let duration):
+                return duration
+            case CurlDown(let duration):
+                return duration
+            case CurlUp(let duration):
+                return duration
+            case FlipFromBottom(let duration):
+                return duration
+            case FlipFromLeft(let duration):
+                return duration
+            case FlipFromRight(let duration):
+                return duration
+            case FlipFromTop(let duration):
+                return duration
+            case Custom(let duration, _, _, _):
+                return duration
+            }
+        }
+
+        /// The animation options of the image transition.
+        public var animationOptions: UIViewAnimationOptions {
+            switch self {
+            case None:
+                return .TransitionNone
+            case CrossDissolve:
+                return .TransitionCrossDissolve
+            case CurlDown:
+                return .TransitionCurlDown
+            case CurlUp:
+                return .TransitionCurlUp
+            case FlipFromBottom:
+                return .TransitionFlipFromBottom
+            case FlipFromLeft:
+                return .TransitionFlipFromLeft
+            case FlipFromRight:
+                return .TransitionFlipFromRight
+            case FlipFromTop:
+                return .TransitionFlipFromTop
+            case Custom(_, let animationOptions, _, _):
+                return animationOptions
+            }
+        }
+
+        /// The animation options of the image transition.
+        public var animations: ((UIImageView, Image) -> Void) {
+            switch self {
+            case Custom(_, _, let animations, _):
+                return animations
+            default:
+                return { $0.image = $1 }
+            }
+        }
+
+        /// The completion closure associated with the image transition.
+        public var completion: (Bool -> Void)? {
+            switch self {
+            case Custom(_, _, _, let completion):
+                return completion
+            default:
+                return nil
+            }
+        }
+    }
+
+    // MARK: - Private - AssociatedKeys
+
+    private struct AssociatedKeys {
+        static var ImageDownloaderKey = "af_UIImageView.ImageDownloader"
+        static var SharedImageDownloaderKey = "af_UIImageView.SharedImageDownloader"
+        static var ActiveRequestReceiptKey = "af_UIImageView.ActiveRequestReceipt"
+    }
+
+    // MARK: - Associated Properties
+
+    /// The instance image downloader used to download all images. If this property is `nil`, the `UIImageView` will
+    /// fallback on the `af_sharedImageDownloader` for all downloads. The most common use case for needing to use a
+    /// custom instance image downloader is when images are behind different basic auth credentials.
+    public var af_imageDownloader: ImageDownloader? {
+        get {
+            return objc_getAssociatedObject(self, &AssociatedKeys.ImageDownloaderKey) as? ImageDownloader
+        }
+        set(downloader) {
+            objc_setAssociatedObject(self, &AssociatedKeys.ImageDownloaderKey, downloader, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
+        }
+    }
+
+    /// The shared image downloader used to download all images. By default, this is the default `ImageDownloader` 
+    /// instance backed with an `AutoPurgingImageCache` which automatically evicts images from the cache when the memory
+    /// capacity is reached or memory warning notifications occur. The shared image downloader is only used if the
+    /// `af_imageDownloader` is `nil`.
+    public class var af_sharedImageDownloader: ImageDownloader {
+        get {
+            if let downloader = objc_getAssociatedObject(self, &AssociatedKeys.SharedImageDownloaderKey) as? ImageDownloader {
+                return downloader
+            } else {
+                return ImageDownloader.defaultInstance
+            }
+        }
+        set {
+            objc_setAssociatedObject(self, &AssociatedKeys.SharedImageDownloaderKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
+        }
+    }
+
+    var af_activeRequestReceipt: RequestReceipt? {
+        get {
+            return objc_getAssociatedObject(self, &AssociatedKeys.ActiveRequestReceiptKey) as? RequestReceipt
+        }
+        set {
+            objc_setAssociatedObject(self, &AssociatedKeys.ActiveRequestReceiptKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
+        }
+    }
+
+    // MARK: - Image Download
+
+    /**
+        Asynchronously downloads an image from the specified URL, applies the specified image filter to the downloaded
+        image and sets it once finished while executing the image transition.
+
+        If the image is cached locally, the image is set immediately. Otherwise the specified placehoder image will be
+        set immediately, and then the remote image will be set once the image request is finished.
+
+        The `completion` closure is called after the image download and filtering are complete, but before the start of
+        the image transition. Please note it is no longer the responsibility of the `completion` closure to set the
+        image. It will be set automatically. If you require a second notification after the image transition completes,
+        use a `.Custom` image transition with a `completion` closure. The `.Custom` `completion` closure is called when
+        the image transition is finished.
+
+        - parameter URL:                        The URL used for the image request.
+        - parameter placeholderImage:           The image to be set initially until the image request finished. If
+                                                `nil`, the image view will not change its image until the image
+                                                request finishes. Defaults to `nil`.
+        - parameter filter:                     The image filter applied to the image after the image request is
+                                                finished. Defaults to `nil`.
+        - parameter imageTransition:            The image transition animation applied to the image when set. 
+                                                Defaults to `.None`.
+        - parameter runImageTransitionIfCached: Whether to run the image transition if the image is cached. Defaults
+                                                to `false`.
+        - parameter completion:                 A closure to be executed when the image request finishes. The closure
+                                                has no return value and takes three arguments: the original request,
+                                                the response from the server and the result containing either the
+                                                image or the error that occurred. If the image was returned from the
+                                                image cache, the response will be `nil`. Defaults to `nil`.
+    */
+    public func af_setImageWithURL(
+        URL: NSURL,
+        placeholderImage: UIImage? = nil,
+        filter: ImageFilter? = nil,
+        imageTransition: ImageTransition = .None,
+        runImageTransitionIfCached: Bool = false,
+        completion: (Response<UIImage, NSError> -> Void)? = nil)
+    {
+        af_setImageWithURLRequest(
+            URLRequestWithURL(URL),
+            placeholderImage: placeholderImage,
+            filter: filter,
+            imageTransition: imageTransition,
+            runImageTransitionIfCached: runImageTransitionIfCached,
+            completion: completion
+        )
+    }
+
+    /**
+        Asynchronously downloads an image from the specified URL Request, applies the specified image filter to the downloaded
+        image and sets it once finished while executing the image transition.
+
+        If the image is cached locally, the image is set immediately. Otherwise the specified placehoder image will be
+        set immediately, and then the remote image will be set once the image request is finished.
+
+        The `completion` closure is called after the image download and filtering are complete, but before the start of 
+        the image transition. Please note it is no longer the responsibility of the `completion` closure to set the 
+        image. It will be set automatically. If you require a second notification after the image transition completes, 
+        use a `.Custom` image transition with a `completion` closure. The `.Custom` `completion` closure is called when 
+        the image transition is finished.
+
+        - parameter URLRequest:                 The URL request.
+        - parameter placeholderImage:           The image to be set initially until the image request finished. If
+                                                `nil`, the image view will not change its image until the image
+                                                request finishes. Defaults to `nil`.
+        - parameter filter:                     The image filter applied to the image after the image request is
+                                                finished. Defaults to `nil`.
+        - parameter imageTransition:            The image transition animation applied to the image when set.
+                                                Defaults to `.None`.
+        - parameter runImageTransitionIfCached: Whether to run the image transition if the image is cached. Defaults
+                                                to `false`.
+        - parameter completion:                 A closure to be executed when the image request finishes. The closure
+                                                has no return value and takes three arguments: the original request,
+                                                the response from the server and the result containing either the
+                                                image or the error that occurred. If the image was returned from the
+                                                image cache, the response will be `nil`. Defaults to `nil`.
+    */
+    public func af_setImageWithURLRequest(
+        URLRequest: URLRequestConvertible,
+        placeholderImage: UIImage? = nil,
+        filter: ImageFilter? = nil,
+        imageTransition: ImageTransition = .None,
+        runImageTransitionIfCached: Bool = false,
+        completion: (Response<UIImage, NSError> -> Void)? = nil)
+    {
+        guard !isURLRequestURLEqualToActiveRequestURL(URLRequest) else { return }
+
+        af_cancelImageRequest()
+
+        let imageDownloader = af_imageDownloader ?? UIImageView.af_sharedImageDownloader
+        let imageCache = imageDownloader.imageCache
+
+        // Use the image from the image cache if it exists
+        if let image = imageCache?.imageForRequest(URLRequest.URLRequest, withAdditionalIdentifier: filter?.identifier) {
+            let response = Response<UIImage, NSError>(
+                request: URLRequest.URLRequest,
+                response: nil,
+                data: nil,
+                result: .Success(image)
+            )
+
+            completion?(response)
+
+            if runImageTransitionIfCached {
+                let tinyDelay = dispatch_time(DISPATCH_TIME_NOW, Int64(0.001 * Float(NSEC_PER_SEC)))
+
+                // Need to let the runloop cycle for the placeholder image to take affect
+                dispatch_after(tinyDelay, dispatch_get_main_queue()) {
+                    self.runImageTransition(imageTransition, withImage: image)
+                }
+            } else {
+                self.image = image
+            }
+
+            return
+        }
+
+        // Set the placeholder since we're going to have to download
+        if let placeholderImage = placeholderImage { self.image = placeholderImage }
+
+        // Generate a unique download id to check whether the active request has changed while downloading
+        let downloadID = NSUUID().UUIDString
+
+        // Download the image, then run the image transition or completion handler
+        let requestReceipt = imageDownloader.downloadImage(
+            URLRequest: URLRequest,
+            receiptID: downloadID,
+            filter: filter,
+            completion: { [weak self] response in
+                guard let strongSelf = self else { return }
+
+                completion?(response)
+
+                guard
+                    strongSelf.isURLRequestURLEqualToActiveRequestURL(response.request) &&
+                    strongSelf.af_activeRequestReceipt?.receiptID == downloadID
+                else {
+                    return
+                }
+
+                if let image = response.result.value {
+                    strongSelf.runImageTransition(imageTransition, withImage: image)
+                }
+
+                strongSelf.af_activeRequestReceipt = nil
+            }
+        )
+
+        af_activeRequestReceipt = requestReceipt
+    }
+
+    // MARK: - Image Download Cancellation
+
+    /**
+        Cancels the active download request, if one exists.
+    */
+    public func af_cancelImageRequest() {
+        guard let activeRequestReceipt = af_activeRequestReceipt else { return }
+
+        let imageDownloader = af_imageDownloader ?? UIImageView.af_sharedImageDownloader
+        imageDownloader.cancelRequestForRequestReceipt(activeRequestReceipt)
+
+        af_activeRequestReceipt = nil
+    }
+
+    // MARK: - Image Transition
+
+    /**
+        Runs the image transition on the image view with the specified image.
+
+        - parameter imageTransition: The image transition to ran on the image view.
+        - parameter image:           The image to use for the image transition.
+    */
+    public func runImageTransition(imageTransition: ImageTransition, withImage image: Image) {
+        UIView.transitionWithView(
+            self,
+            duration: imageTransition.duration,
+            options: imageTransition.animationOptions,
+            animations: {
+                imageTransition.animations(self, image)
+            },
+            completion: imageTransition.completion
+        )
+    }
+
+    // MARK: - Private - URL Request Helper Methods
+
+    private func URLRequestWithURL(URL: NSURL) -> NSURLRequest {
+        let mutableURLRequest = NSMutableURLRequest(URL: URL)
+
+        for mimeType in Request.acceptableImageContentTypes {
+            mutableURLRequest.addValue(mimeType, forHTTPHeaderField: "Accept")
+        }
+
+        return mutableURLRequest
+    }
+
+    private func isURLRequestURLEqualToActiveRequestURL(URLRequest: URLRequestConvertible?) -> Bool {
+        if let
+            currentRequest = af_activeRequestReceipt?.request.task.originalRequest
+            where currentRequest.URLString == URLRequest?.URLRequest.URLString
+        {
+            return true
+        }
+
+        return false
+    }
+}

+ 172 - 0
Pods/AlamofireObjectMapper/AlamofireObjectMapper/AlamofireObjectMapper.swift

@@ -0,0 +1,172 @@
+//
+//  Request.swift
+//  AlamofireObjectMapper
+//
+//  Created by Tristan Himmelman on 2015-04-30.
+//
+//  The MIT License (MIT)
+//
+//  Copyright (c) 2014-2015 Tristan Himmelman
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+import Foundation
+import Alamofire
+import ObjectMapper
+
+extension Request {
+    
+    public static func ObjectMapperSerializer<T: Mappable>(keyPath: String?) -> ResponseSerializer<T, NSError> {
+        return ResponseSerializer { request, response, data, error in
+            guard error == nil else {
+                return .Failure(error!)
+            }
+            
+            guard let _ = data else {
+                let failureReason = "Data could not be serialized. Input data was nil."
+                let error = Error.errorWithCode(.DataSerializationFailed, failureReason: failureReason)
+                return .Failure(error)
+            }
+            
+            let JSONResponseSerializer = Request.JSONResponseSerializer(options: .AllowFragments)
+            let result = JSONResponseSerializer.serializeResponse(request, response, data, error)
+        
+            let JSONToMap: AnyObject?
+            if let keyPath = keyPath where keyPath.isEmpty == false {
+                JSONToMap = result.value?.valueForKeyPath(keyPath)
+            } else {
+                JSONToMap = result.value
+            }
+            
+            if let parsedObject = Mapper<T>().map(JSONToMap){
+                return .Success(parsedObject)
+            }
+
+            let failureReason = "ObjectMapper failed to serialize response."
+            let error = Error.errorWithCode(.DataSerializationFailed, failureReason: failureReason)
+            return .Failure(error)
+        }
+    }
+    
+    /**
+     Adds a handler to be called once the request has finished.
+     
+     - parameter keyPath:           The key path where object mapping should be performed
+     - parameter completionHandler: A closure to be executed once the request has finished and the data has been mapped by ObjectMapper.
+     
+     - returns: The request.
+     */
+    public func responseObject<T: Mappable>(keyPath: String? = nil, completionHandler: Response<T, NSError> -> Void) -> Self {
+        return responseObject(nil, keyPath: keyPath, completionHandler: completionHandler)
+    }
+
+    /**
+     Adds a handler to be called once the request has finished.
+     
+     - parameter queue:             The queue on which the completion handler is dispatched.
+     - parameter completionHandler: A closure to be executed once the request has finished and the data has been mapped by ObjectMapper.
+     
+     - returns: The request.
+     */
+    public func responseObject<T: Mappable>(queue: dispatch_queue_t?, completionHandler: Response<T, NSError> -> Void) -> Self {
+        return responseObject(queue, keyPath: nil, completionHandler: completionHandler)
+    }
+    
+    /**
+     Adds a handler to be called once the request has finished.
+     
+     - parameter queue:             The queue on which the completion handler is dispatched.
+     - parameter keyPath:           The key path where object mapping should be performed
+     - parameter completionHandler: A closure to be executed once the request has finished and the data has been mapped by ObjectMapper.
+     
+     - returns: The request.
+    */
+    public func responseObject<T: Mappable>(queue: dispatch_queue_t?, keyPath: String?, completionHandler: Response<T, NSError> -> Void) -> Self {
+        return response(queue: queue, responseSerializer: Request.ObjectMapperSerializer(keyPath), completionHandler: completionHandler)
+    }
+    
+    public static func ObjectMapperArraySerializer<T: Mappable>(keyPath: String?) -> ResponseSerializer<[T], NSError> {
+        return ResponseSerializer { request, response, data, error in
+            guard error == nil else {
+                return .Failure(error!)
+            }
+            
+            guard let _ = data else {
+                let failureReason = "Data could not be serialized. Input data was nil."
+                let error = Error.errorWithCode(.DataSerializationFailed, failureReason: failureReason)
+                return .Failure(error)
+            }
+            
+            let JSONResponseSerializer = Request.JSONResponseSerializer(options: .AllowFragments)
+            let result = JSONResponseSerializer.serializeResponse(request, response, data, error)
+            
+            let JSONToMap: AnyObject?
+            if let keyPath = keyPath where keyPath.isEmpty == false {
+                JSONToMap = result.value?.valueForKeyPath(keyPath)
+            } else {
+                JSONToMap = result.value
+            }
+            
+            if let parsedObject = Mapper<T>().mapArray(JSONToMap){
+                return .Success(parsedObject)
+            }
+            
+            let failureReason = "ObjectMapper failed to serialize response."
+            let error = Error.errorWithCode(.DataSerializationFailed, failureReason: failureReason)
+            return .Failure(error)
+        }
+    }
+
+    /**
+     Adds a handler to be called once the request has finished.
+     
+     - parameter keyPath: The key path where object mapping should be performed
+     - parameter completionHandler: A closure to be executed once the request has finished and the data has been mapped by ObjectMapper.
+     
+     - returns: The request.
+    */
+    public func responseArray<T: Mappable>(keyPath: String? = nil, completionHandler: Response<[T], NSError> -> Void) -> Self {
+        return responseArray(nil, keyPath: keyPath, completionHandler: completionHandler)
+    }
+
+    /**
+     Adds a handler to be called once the request has finished.
+     
+     - parameter queue: The queue on which the completion handler is dispatched.
+     - parameter completionHandler: A closure to be executed once the request has finished and the data has been mapped by ObjectMapper.
+     
+     - returns: The request.
+    */
+    public func responseArray<T: Mappable>(queue: dispatch_queue_t?, completionHandler: Response<[T], NSError> -> Void) -> Self {
+        return responseArray(queue, keyPath: nil, completionHandler: completionHandler)
+    }
+    
+    /**
+     Adds a handler to be called once the request has finished.
+     
+     - parameter queue: The queue on which the completion handler is dispatched.
+     - parameter keyPath: The key path where object mapping should be performed
+     - parameter completionHandler: A closure to be executed once the request has finished and the data has been mapped by ObjectMapper.
+     
+     - returns: The request.
+    */
+    public func responseArray<T: Mappable>(queue: dispatch_queue_t?, keyPath: String?, completionHandler: Response<[T], NSError> -> Void) -> Self {
+        return response(queue: queue, responseSerializer: Request.ObjectMapperArraySerializer(keyPath), completionHandler: completionHandler)
+    }
+}

+ 22 - 0
Pods/AlamofireObjectMapper/LICENSE

@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Tristan Himmelman
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+

+ 172 - 0
Pods/AlamofireObjectMapper/README.md

@@ -0,0 +1,172 @@
+AlamofireObjectMapper
+============
+[![Build Status](https://travis-ci.org/tristanhimmelman/AlamofireObjectMapper.svg?branch=master)](https://travis-ci.org/tristanhimmelman/AlamofireObjectMapper)
+[![CocoaPods](https://img.shields.io/cocoapods/v/AlamofireObjectMapper.svg)](https://github.com/tristanhimmelman/AlamofireObjectMapper)
+[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)
+
+
+An extension to [Alamofire](https://github.com/Alamofire/Alamofire) which automatically converts JSON response data into swift objects using [ObjectMapper](https://github.com/Hearst-DD/ObjectMapper/). 
+
+#Usage
+
+Given a URL which returns weather data in the following form:
+```
+{
+    "location": "Toronto, Canada",    
+    "three_day_forecast": [
+        { 
+            "conditions": "Partly cloudy",
+            "day" : "Monday",
+            "temperature": 20 
+        },
+        { 
+            "conditions": "Showers",
+            "day" : "Tuesday",
+            "temperature": 22 
+        },
+        { 
+            "conditions": "Sunny",
+            "day" : "Wednesday",
+            "temperature": 28 
+        }
+    ]
+}
+```
+
+You can use this extension as the follows:
+```swift
+let URL = "https://raw.githubusercontent.com/tristanhimmelman/AlamofireObjectMapper/2ee8f34d21e8febfdefb2b3a403f18a43818d70a/sample_keypath_json"
+Alamofire.request(.GET, URL).responseObject("data") { (response: Response<WeatherResponse, NSError>) in
+
+    let weatherResponse = response.result.value
+    print(weatherResponse?.location)
+    
+    if let threeDayForecast = weatherResponse?.threeDayForecast {
+        for forecast in threeDayForecast {
+            print(forecast.day)
+            print(forecast.temperature)           
+        }
+    }
+}
+```
+
+The `WeatherResponse` object in the completion handler is a custom object which you define. The only requirement is that the object must conform to [ObjectMapper's](https://github.com/Hearst-DD/ObjectMapper/) `Mappable` protocol. In the above example, the `WeatherResponse` object looks like the following:
+
+```swift
+class WeatherResponse: Mappable {
+    var location: String?
+    var threeDayForecast: [Forecast]?
+    
+	required init?(_ map: Map){
+
+	}
+    
+    func mapping(map: Map) {
+        location <- map["location"]
+        threeDayForecast <- map["three_day_forecast"]
+    }
+}
+
+class Forecast: Mappable {
+    var day: String?
+    var temperature: Int?
+    var conditions: String?
+    
+	required init?(_ map: Map){
+
+	}
+    
+    func mapping(map: Map) {
+        day <- map["day"]
+        temperature <- map["temperature"]
+        conditions <- map["conditions"]
+    }
+}
+```
+
+The extension uses Generics to allow you to create your own custom response objects. Below are four functions which you can use to have your responses mapped to objects. Just replace `T` with your custom response object and the extension handles the rest: 
+```swift
+public func responseObject<T: Mappable>(completionHandler: Response<T, NSError> -> Void) -> Self
+```
+
+```swift
+public func responseObject<T: Mappable>(keyPath: String, completionHandler: Response<T, NSError> -> Void) -> Self
+```
+
+```swift
+public func responseObject<T: Mappable>(queue: dispatch_queue_t?, completionHandler: Response<T, NSError> -> Void) -> Self
+```
+
+```swift
+public func responseObject<T: Mappable>(queue: dispatch_queue_t?, keyPath: String?, completionHandler: Response<T, NSError> -> Void) -> Self
+```
+
+###KeyPath
+
+The `keyPath` variable in the functions above is used to drill down in a JSON response and only map the data at that `keyPath`. It also supports nested values such as `data.weather` to drill down several levels in a JSON response.
+
+#Array Responses
+If you have an endpoint that returns data in `Array` form you can map it with the following functions:
+```swift
+public func responseArray<T: Mappable>(completionHandler: Response<[T], NSError> -> Void) -> Self
+```
+
+```swift
+public func responseArray<T: Mappable>(keyPath: String, completionHandler: Response<[T], NSError> -> Void) -> Self
+```
+
+```swift
+public func responseArray<T: Mappable>(queue: dispatch_queue_t?, completionHandler: Response<[T], NSError> -> Void) -> Self
+```
+
+```swift
+public func responseArray<T: Mappable>(queue: dispatch_queue_t?, keyPath: String?, completionHandler: Response<[T], NSError> -> Void) -> Self
+```
+
+For example, if your endpoint returns the following:
+```
+[
+    { 
+        "conditions": "Partly cloudy",
+        "day" : "Monday",
+        "temperature": 20 
+    },
+    { 
+        "conditions": "Showers",
+        "day" : "Tuesday",
+        "temperature": 22 
+    },
+    { 
+        "conditions": "Sunny",
+        "day" : "Wednesday",
+        "temperature": 28 
+    }
+]
+```
+You can request and map it as follows:
+```swift
+let URL = "https://raw.githubusercontent.com/tristanhimmelman/AlamofireObjectMapper/f583be1121dbc5e9b0381b3017718a70c31054f7/sample_array_json"
+Alamofire.request(.GET, URL).responseArray { (response: Response<[Forecast], NSError>) in
+
+    let forecastArray = response.result.value
+    
+    if let forecastArray = forecastArray {
+        for forecast in forecastArray {
+            print(forecast.day)
+            print(forecast.temperature)           
+        }
+    }
+}
+
+```
+
+#Installation
+AlamofireObjectMapper can be added to your project using [CocoaPods](https://cocoapods.org/) by adding the following line to your Podfile:
+```
+pod 'AlamofireObjectMapper', '~> 2.1'
+```
+
+If your using [Carthage](https://github.com/Carthage/Carthage) you can add a dependency on AlamofireObjectMapper by adding it to your Cartfile:
+```
+github "tristanhimmelman/AlamofireObjectMapper" ~> 2.1
+```

+ 21 - 0
Pods/Manifest.lock

@@ -0,0 +1,21 @@
+PODS:
+  - Alamofire (3.2.1)
+  - AlamofireImage (2.3.1):
+    - Alamofire (~> 3.2)
+  - AlamofireObjectMapper (2.1.2):
+    - Alamofire (~> 3.2)
+    - ObjectMapper (~> 1.0)
+  - ObjectMapper (1.1.5)
+
+DEPENDENCIES:
+  - Alamofire (~> 3.0)
+  - AlamofireImage (~> 2.0)
+  - AlamofireObjectMapper (~> 2.1)
+
+SPEC CHECKSUMS:
+  Alamofire: f11d8624a05f5d39e0c99309b3e600a3ba64298a
+  AlamofireImage: e52336282757bbe1644f075d6cb85f19c891f939
+  AlamofireObjectMapper: 82391c31f23e37bdb2660da174bcf81b202da39d
+  ObjectMapper: 528b1a6677a6acac7747edd508576983e76a9148
+
+COCOAPODS: 0.39.0

+ 8 - 0
Pods/ObjectMapper/LICENSE

@@ -0,0 +1,8 @@
+The MIT License (MIT)
+Copyright (c) 2014 Hearst
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 181 - 0
Pods/ObjectMapper/ObjectMapper/Core/FromJSON.swift

@@ -0,0 +1,181 @@
+//
+//  FromJSON.swift
+//  ObjectMapper
+//
+//  Created by Tristan Himmelman on 2014-10-09.
+//
+//  The MIT License (MIT)
+//
+//  Copyright (c) 2014-2015 Hearst
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+internal final class FromJSON {
+	
+	/// Basic type
+	class func basicType<FieldType>(inout field: FieldType, object: FieldType?) {
+		if let value = object {
+			field = value
+		}
+	}
+
+	/// optional basic type
+	class func optionalBasicType<FieldType>(inout field: FieldType?, object: FieldType?) {
+		if let value = object {
+			field = value
+		}
+	}
+
+	/// Implicitly unwrapped optional basic type
+	class func optionalBasicType<FieldType>(inout field: FieldType!, object: FieldType?) {
+		if let value = object {
+			field = value
+		}
+	}
+
+	/// Mappable object
+	class func object<N: Mappable>(inout field: N, map: Map) {
+		if map.toObject {
+			Mapper().map(map.currentValue, toObject: field)
+		} else if let value: N = Mapper().map(map.currentValue) {
+			field = value
+		}
+	}
+
+	/// Optional Mappable Object
+	class func optionalObject<N: Mappable>(inout field: N?, map: Map) {
+		if let field = field where map.toObject {
+			Mapper().map(map.currentValue, toObject: field)
+		} else {
+			field = Mapper().map(map.currentValue)
+		}
+	}
+
+	/// Implicitly unwrapped Optional Mappable Object
+	class func optionalObject<N: Mappable>(inout field: N!, map: Map) {
+		if let field = field where map.toObject {
+			Mapper().map(map.currentValue, toObject: field)
+		} else {
+			field = Mapper().map(map.currentValue)
+		}
+	}
+
+	/// mappable object array
+	class func objectArray<N: Mappable>(inout field: Array<N>, map: Map) {
+		if let objects = Mapper<N>().mapArray(map.currentValue) {
+			field = objects
+		}
+	}
+
+	/// optional mappable object array
+	class func optionalObjectArray<N: Mappable>(inout field: Array<N>?, map: Map) {
+		if let objects: Array<N> = Mapper().mapArray(map.currentValue) {
+			field = objects
+		}
+	}
+
+	/// Implicitly unwrapped optional mappable object array
+	class func optionalObjectArray<N: Mappable>(inout field: Array<N>!, map: Map) {
+		if let objects: Array<N> = Mapper().mapArray(map.currentValue) {
+			field = objects
+		}
+	}
+	
+	/// mappable object array
+	class func twoDimensionalObjectArray<N: Mappable>(inout field: Array<Array<N>>, map: Map) {
+		if let objects = Mapper<N>().mapArrayOfArrays(map.currentValue) {
+			field = objects
+		}
+	}
+	
+	/// optional mappable 2 dimentional object array
+	class func optionalTwoDimensionalObjectArray<N: Mappable>(inout field: Array<Array<N>>?, map: Map) {
+		field = Mapper().mapArrayOfArrays(map.currentValue)
+	}
+	
+	/// Implicitly unwrapped optional 2 dimentional mappable object array
+	class func optionalTwoDimensionalObjectArray<N: Mappable>(inout field: Array<Array<N>>!, map: Map) {
+		field = Mapper().mapArrayOfArrays(map.currentValue)
+	}
+	
+	/// Dctionary containing Mappable objects
+	class func objectDictionary<N: Mappable>(inout field: Dictionary<String, N>, map: Map) {
+		if map.toObject {
+			Mapper<N>().mapDictionary(map.currentValue, toDictionary: field)
+		} else {
+			if let objects = Mapper<N>().mapDictionary(map.currentValue) {
+				field = objects
+			}	
+		}
+	}
+
+	/// Optional dictionary containing Mappable objects
+	class func optionalObjectDictionary<N: Mappable>(inout field: Dictionary<String, N>?, map: Map) {
+		if let field = field where map.toObject {
+			Mapper().mapDictionary(map.currentValue, toDictionary: field)
+		} else {
+			field = Mapper().mapDictionary(map.currentValue)
+		}
+	}
+
+	/// Implicitly unwrapped Dictionary containing Mappable objects
+	class func optionalObjectDictionary<N: Mappable>(inout field: Dictionary<String, N>!, map: Map) {
+		if let field = field where map.toObject {
+			Mapper().mapDictionary(map.currentValue, toDictionary: field)
+		} else {
+			field = Mapper().mapDictionary(map.currentValue)
+		}
+	}
+	
+	/// Dictionary containing Array of Mappable objects
+	class func objectDictionaryOfArrays<N: Mappable>(inout field: Dictionary<String, [N]>, map: Map) {
+		if let objects = Mapper<N>().mapDictionaryOfArrays(map.currentValue) {
+			field = objects
+		}
+	}
+	
+	/// Optional Dictionary containing Array of Mappable objects
+	class func optionalObjectDictionaryOfArrays<N: Mappable>(inout field: Dictionary<String, [N]>?, map: Map) {
+		field = Mapper<N>().mapDictionaryOfArrays(map.currentValue)
+	}
+	
+	/// Implicitly unwrapped Dictionary containing Array of Mappable objects
+	class func optionalObjectDictionaryOfArrays<N: Mappable>(inout field: Dictionary<String, [N]>!, map: Map) {
+		field = Mapper<N>().mapDictionaryOfArrays(map.currentValue)
+	}
+
+	
+	/// mappable object Set
+	class func objectSet<N: Mappable>(inout field: Set<N>, map: Map) {
+		if let objects = Mapper<N>().mapSet(map.currentValue) {
+			field = objects
+		}
+	}
+	
+	/// optional mappable object array
+	class func optionalObjectSet<N: Mappable>(inout field: Set<N>?, map: Map) {
+		field = Mapper().mapSet(map.currentValue)
+	}
+	
+	/// Implicitly unwrapped optional mappable object array
+	class func optionalObjectSet<N: Mappable>(inout field: Set<N>!, map: Map) {
+		field = Mapper().mapSet(map.currentValue)
+	}
+	
+}

+ 161 - 0
Pods/ObjectMapper/ObjectMapper/Core/Map.swift

@@ -0,0 +1,161 @@
+//
+//  Map.swift
+//  ObjectMapper
+//
+//  Created by Tristan Himmelman on 2015-10-09.
+//
+//  The MIT License (MIT)
+//
+//  Copyright (c) 2014-2015 Hearst
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+
+import Foundation
+
+/// A class used for holding mapping data
+public final class Map {
+	public let mappingType: MappingType
+	
+	public internal(set) var JSONDictionary: [String : AnyObject] = [:]
+	public var currentValue: AnyObject?
+	var currentKey: String?
+	var keyIsNested = false
+
+	let toObject: Bool // indicates whether the mapping is being applied to an existing object
+	
+	/// Counter for failing cases of deserializing values to `let` properties.
+	private var failedCount: Int = 0
+	
+	public init(mappingType: MappingType, JSONDictionary: [String : AnyObject], toObject: Bool = false) {
+		self.mappingType = mappingType
+		self.JSONDictionary = JSONDictionary
+		self.toObject = toObject
+	}
+	
+	/// Sets the current mapper value and key.
+	/// The Key paramater can be a period separated string (ex. "distance.value") to access sub objects.
+	public subscript(key: String) -> Map {
+		// save key and value associated to it
+		let nested = key.containsString(".")
+		return self[key, nested: nested]
+	}
+	
+	public subscript(key: String, nested nested: Bool) -> Map {
+		// save key and value associated to it
+		currentKey = key
+		keyIsNested = nested
+		
+		// check if a value exists for the current key
+		if nested == false {
+			currentValue = JSONDictionary[key]
+		} else {
+			// break down the components of the key that are separated by .
+			currentValue = valueFor(ArraySlice(key.componentsSeparatedByString(".")), dictionary: JSONDictionary)
+		}
+		
+		return self
+	}
+	
+	// MARK: Immutable Mapping
+	
+	public func value<T>() -> T? {
+		return currentValue as? T
+	}
+	
+	public func valueOr<T>(@autoclosure defaultValue: () -> T) -> T {
+		return value() ?? defaultValue()
+	}
+	
+	/// Returns current JSON value of type `T` if it is existing, or returns a
+	/// unusable proxy value for `T` and collects failed count.
+	public func valueOrFail<T>() -> T {
+		if let value: T = value() {
+			return value
+		} else {
+			// Collects failed count
+			failedCount++
+			
+			// Returns dummy memory as a proxy for type `T`
+			let pointer = UnsafeMutablePointer<T>.alloc(0)
+			pointer.dealloc(0)
+			return pointer.memory
+		}
+	}
+	
+	/// Returns whether the receiver is success or failure.
+	public var isValid: Bool {
+		return failedCount == 0
+	}
+}
+
+/// Fetch value from JSON dictionary, loop through keyPathComponents until we reach the desired object
+private func valueFor(keyPathComponents: ArraySlice<String>, dictionary: [String: AnyObject]) -> AnyObject? {
+	// Implement it as a tail recursive function.
+	if keyPathComponents.isEmpty {
+		return nil
+	}
+	
+	if let keyPath = keyPathComponents.first {
+		let object = dictionary[keyPath]
+		if object is NSNull {
+			return nil
+		} else if let dict = object as? [String : AnyObject] where keyPathComponents.count > 1 {
+			let tail = keyPathComponents.dropFirst()
+			return valueFor(tail, dictionary: dict)
+		} else if let array = object as? [AnyObject] where keyPathComponents.count > 1 {
+			let tail = keyPathComponents.dropFirst()
+			return valueFor(tail, dictionary: array)
+		} else {
+			return object
+		}
+	}
+	
+	return nil
+}
+
+/// Fetch value from JSON Array, loop through keyPathComponents them until we reach the desired object
+private func valueFor(keyPathComponents: ArraySlice<String>, dictionary: [AnyObject]) -> AnyObject? {
+	// Implement it as a tail recursive function.
+	
+	if keyPathComponents.isEmpty {
+		return nil
+	}
+	
+	//Try to convert keypath to Int as index
+	if let keyPath = keyPathComponents.first,
+		let index = Int(keyPath) where index >= 0 && index < dictionary.count {
+
+		let object = dictionary[index]
+		
+		if object is NSNull {
+			return nil
+		} else if let array = object as? [AnyObject] where keyPathComponents.count > 1 {
+			let tail = keyPathComponents.dropFirst()
+			return valueFor(tail, dictionary: array)
+		} else if let dict = object as? [String : AnyObject] where keyPathComponents.count > 1 {
+			let tail = keyPathComponents.dropFirst()
+			return valueFor(tail, dictionary: dict)
+		} else {
+			return object
+		}
+	}
+	
+	return nil
+}

+ 111 - 0
Pods/ObjectMapper/ObjectMapper/Core/Mappable.swift

@@ -0,0 +1,111 @@
+//
+//  Mappable.swift
+//  ObjectMapper
+//
+//  Created by Scott Hoyt on 10/25/15.
+//  Copyright © 2015 hearst. All rights reserved.
+//
+
+import Foundation
+
+public protocol Mappable {
+	init?(_ map: Map)
+	mutating func mapping(map: Map)
+}
+
+public protocol MappableCluster: Mappable {
+	static func objectForMapping(map: Map) -> Mappable?
+}
+
+public extension Mappable {
+	
+	/// Initializes object from a JSON String
+	public init?(JSONString: String) {
+		if let obj: Self = Mapper().map(JSONString) {
+			self = obj
+		} else {
+			return nil
+		}
+	}
+	
+	/// Initializes object from a JSON Dictionary
+	public init?(JSON: [String : AnyObject]) {
+		if let obj: Self = Mapper().map(JSON) {
+			self = obj
+		} else {
+			return nil
+		}
+	}
+	
+	/// Returns the JSON Dictionary for the object
+	public func toJSON() -> [String: AnyObject] {
+		return Mapper().toJSON(self)
+	}
+	
+	/// Returns the JSON String for the object
+	public func toJSONString(prettyPrint: Bool = false) -> String? {
+		return Mapper().toJSONString(self, prettyPrint: prettyPrint)
+	}
+}
+
+public extension Array where Element: Mappable {
+	
+	/// Initialize Array from a JSON String
+	public init?(JSONString: String) {
+		if let obj: [Element] = Mapper().mapArray(JSONString) {
+			self = obj
+		} else {
+			return nil
+		}
+	}
+	
+	/// Initialize Array from a JSON Array
+	public init?(JSONArray: [[String : AnyObject]]) {
+		if let obj: [Element] = Mapper().mapArray(JSONArray) {
+			self = obj
+		} else {
+			return nil
+		}
+	}
+	
+	/// Returns the JSON Array
+	public func toJSON() -> [[String : AnyObject]] {
+		return Mapper().toJSONArray(self)
+	}
+	
+	/// Returns the JSON String for the object
+	public func toJSONString(prettyPrint: Bool = false) -> String? {
+		return Mapper().toJSONString(self, prettyPrint: prettyPrint)
+	}
+}
+
+public extension Set where Element: Mappable {
+	
+	/// Initializes a set from a JSON String
+	public init?(JSONString: String) {
+		if let obj: Set<Element> = Mapper().mapSet(JSONString) {
+			self = obj
+		} else {
+			return nil
+		}
+	}
+	
+	/// Initializes a set from JSON
+	public init?(JSONArray: [[String : AnyObject]]) {
+		if let obj: Set<Element> = Mapper().mapSet(JSONArray) {
+			self = obj
+		} else {
+			return nil
+		}
+	}
+	
+	/// Returns the JSON Set
+	public func toJSON() -> [[String : AnyObject]] {
+		return Mapper().toJSONSet(self)
+	}
+	
+	/// Returns the JSON String for the object
+	public func toJSONString(prettyPrint: Bool = false) -> String? {
+		return Mapper().toJSONString(self, prettyPrint: prettyPrint)
+	}
+}

+ 442 - 0
Pods/ObjectMapper/ObjectMapper/Core/Mapper.swift

@@ -0,0 +1,442 @@
+//
+//  Mapper.swift
+//  ObjectMapper
+//
+//  Created by Tristan Himmelman on 2014-10-09.
+//
+//  The MIT License (MIT)
+//
+//  Copyright (c) 2014-2015 Hearst
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+import Foundation
+
+public enum MappingType {
+	case FromJSON
+	case ToJSON
+}
+
+/// The Mapper class provides methods for converting Model objects to JSON and methods for converting JSON to Model objects
+public final class Mapper<N: Mappable> {
+	
+	public init(){}
+	
+	// MARK: Mapping functions that map to an existing object toObject
+	
+	/// Maps a JSON object to an existing Mappable object if it is a JSON dictionary, or returns the passed object as is
+	public func map(JSON: AnyObject?, toObject object: N) -> N {
+		if let JSON = JSON as? [String : AnyObject] {
+			return map(JSON, toObject: object)
+		}
+		
+		return object
+	}
+	
+	/// Map a JSON string onto an existing object
+	public func map(JSONString: String, toObject object: N) -> N {
+		if let JSON = Mapper.parseJSONDictionary(JSONString) {
+			return map(JSON, toObject: object)
+		}
+		return object
+	}
+	
+	/// Maps a JSON dictionary to an existing object that conforms to Mappable.
+	/// Usefull for those pesky objects that have crappy designated initializers like NSManagedObject
+	public func map(JSONDictionary: [String : AnyObject], var toObject object: N) -> N {
+		let map = Map(mappingType: .FromJSON, JSONDictionary: JSONDictionary, toObject: true)
+		object.mapping(map)
+		return object
+	}
+
+	//MARK: Mapping functions that create an object
+	
+	/// Map an optional JSON string to an object that conforms to Mappable
+	public func map(JSONString: String?) -> N? {
+		if let JSONString = JSONString {
+			return map(JSONString)
+		}
+		
+		return nil
+	}
+	
+	/// Map a JSON string to an object that conforms to Mappable
+	public func map(JSONString: String) -> N? {
+		if let JSON = Mapper.parseJSONDictionary(JSONString) {
+			return map(JSON)
+		}
+		
+		return nil
+	}
+	
+	/// Map a JSON NSString to an object that conforms to Mappable
+	public func map(JSONString: NSString) -> N? {
+		return map(JSONString as String)
+	}
+	
+	/// Maps a JSON object to a Mappable object if it is a JSON dictionary or NSString, or returns nil.
+	public func map(JSON: AnyObject?) -> N? {
+		if let JSON = JSON as? [String : AnyObject] {
+			return map(JSON)
+		}
+
+		return nil
+	}
+
+	/// Maps a JSON dictionary to an object that conforms to Mappable
+	public func map(JSONDictionary: [String : AnyObject]) -> N? {
+		let map = Map(mappingType: .FromJSON, JSONDictionary: JSONDictionary)
+		
+		// check if N is of type MappableCluster
+		if let klass = N.self as? MappableCluster.Type {
+			if var object = klass.objectForMapping(map) as? N {
+				object.mapping(map)
+				return object
+			}
+		}
+		
+		if var object = N(map) {
+			object.mapping(map)
+			return object
+		}
+		return nil
+	}
+
+	// MARK: Mapping functions for Arrays and Dictionaries
+	
+	/// Maps a JSON array to an object that conforms to Mappable
+	public func mapArray(JSONString: String) -> [N]? {
+		let parsedJSON: AnyObject? = Mapper.parseJSONString(JSONString)
+
+		if let objectArray = mapArray(parsedJSON) {
+			return objectArray
+		}
+
+		// failed to parse JSON into array form
+		// try to parse it into a dictionary and then wrap it in an array
+		if let object = map(parsedJSON) {
+			return [object]
+		}
+
+		return nil
+	}
+	
+	/// Maps a optional JSON String into an array of objects that conforms to Mappable
+	public func mapArray(JSONString: String?) -> [N]? {
+		if let JSONString = JSONString {
+			return mapArray(JSONString)
+		}
+		
+		return nil
+	}
+	
+	/// Maps a JSON object to an array of Mappable objects if it is an array of JSON dictionary, or returns nil.
+	public func mapArray(JSON: AnyObject?) -> [N]? {
+		if let JSONArray = JSON as? [[String : AnyObject]] {
+			return mapArray(JSONArray)
+		}
+
+		return nil
+	}
+	
+	/// Maps an array of JSON dictionary to an array of Mappable objects
+	public func mapArray(JSONArray: [[String : AnyObject]]) -> [N]? {
+		// map every element in JSON array to type N
+		let result = JSONArray.flatMap(map)
+		return result
+	}
+	
+	/// Maps a JSON object to a dictionary of Mappable objects if it is a JSON dictionary of dictionaries, or returns nil.
+	public func mapDictionary(JSONString: String) -> [String : N]? {
+		let parsedJSON: AnyObject? = Mapper.parseJSONString(JSONString)
+		return mapDictionary(parsedJSON)
+	}
+	
+	/// Maps a JSON object to a dictionary of Mappable objects if it is a JSON dictionary of dictionaries, or returns nil.
+	public func mapDictionary(JSON: AnyObject?) -> [String : N]? {
+		if let JSONDictionary = JSON as? [String : [String : AnyObject]] {
+			return mapDictionary(JSONDictionary)
+		}
+
+		return nil
+	}
+
+	/// Maps a JSON dictionary of dictionaries to a dictionary of Mappble objects
+	public func mapDictionary(JSONDictionary: [String : [String : AnyObject]]) -> [String : N]? {
+		// map every value in dictionary to type N
+		let result = JSONDictionary.filterMap(map)
+		if result.isEmpty == false {
+			return result
+		}
+		
+		return nil
+	}
+	
+	/// Maps a JSON object to a dictionary of Mappable objects if it is a JSON dictionary of dictionaries, or returns nil.
+	public func mapDictionary(JSON: AnyObject?, toDictionary dictionary: [String : N]) -> [String : N] {
+		if let JSONDictionary = JSON as? [String : [String : AnyObject]] {
+			return mapDictionary(JSONDictionary, toDictionary: dictionary)
+		}
+		
+		return dictionary
+	}
+	
+    /// Maps a JSON dictionary of dictionaries to an existing dictionary of Mappble objects
+    public func mapDictionary(JSONDictionary: [String : [String : AnyObject]], var toDictionary dictionary: [String : N]) -> [String : N] {
+        for (key, value) in JSONDictionary {
+            if let object = dictionary[key] {
+                Mapper().map(value, toObject: object)
+            } else {
+                dictionary[key] = Mapper().map(value)
+            }
+        }
+        
+        return dictionary
+    }
+	
+	/// Maps a JSON object to a dictionary of arrays of Mappable objects
+	public func mapDictionaryOfArrays(JSON: AnyObject?) -> [String : [N]]? {
+		if let JSONDictionary = JSON as? [String : [[String : AnyObject]]] {
+			return mapDictionaryOfArrays(JSONDictionary)
+		}
+		
+		return nil
+	}
+	
+	///Maps a JSON dictionary of arrays to a dictionary of arrays of Mappable objects
+	public func mapDictionaryOfArrays(JSONDictionary: [String : [[String : AnyObject]]]) -> [String : [N]]? {
+		// map every value in dictionary to type N
+		let result = JSONDictionary.filterMap {
+            mapArray($0)
+        }
+        
+		if result.isEmpty == false {
+			return result
+		}
+        
+		return nil
+	}
+	
+	/// Maps an 2 dimentional array of JSON dictionaries to a 2 dimentional array of Mappable objects
+	public func mapArrayOfArrays(JSON: AnyObject?) -> [[N]]? {
+		if let JSONArray = JSON as? [[[String : AnyObject]]] {
+			var objectArray = [[N]]()
+			for innerJSONArray in JSONArray {
+				if let array = mapArray(innerJSONArray){
+					objectArray.append(array)
+				}
+			}
+			
+			if objectArray.isEmpty == false {
+				return objectArray
+			}
+		}
+		
+		return nil
+	}
+
+	// MARK: Utility functions for converting strings to JSON objects
+	
+	/// Convert a JSON String into a Dictionary<String, AnyObject> using NSJSONSerialization
+	public static func parseJSONDictionary(JSON: String) -> [String : AnyObject]? {
+		let parsedJSON: AnyObject? = Mapper.parseJSONString(JSON)
+		return Mapper.parseJSONDictionary(parsedJSON)
+	}
+	
+	/// Convert a JSON Object into a Dictionary<String, AnyObject> using NSJSONSerialization
+	public static func parseJSONDictionary(JSON: AnyObject?) -> [String : AnyObject]? {
+		if let JSONDict = JSON as? [String : AnyObject] {
+			return JSONDict
+		}
+
+		return nil
+	}
+
+	/// Convert a JSON String into an Object using NSJSONSerialization
+	public static func parseJSONString(JSON: String) -> AnyObject? {
+		let data = JSON.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)
+		if let data = data {
+			let parsedJSON: AnyObject?
+			do {
+				parsedJSON = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments)
+			} catch let error {
+				print(error)
+				parsedJSON = nil
+			}
+			return parsedJSON
+		}
+
+		return nil
+	}
+}
+
+extension Mapper {
+    
+	// MARK: Functions that create JSON from objects	
+	
+	///Maps an object that conforms to Mappable to a JSON dictionary <String : AnyObject>
+	public func toJSON(var object: N) -> [String : AnyObject] {
+		let map = Map(mappingType: .ToJSON, JSONDictionary: [:])
+		object.mapping(map)
+		return map.JSONDictionary
+	}
+	
+	///Maps an array of Objects to an array of JSON dictionaries [[String : AnyObject]]
+	public func toJSONArray(array: [N]) -> [[String : AnyObject]] {
+		return array.map {
+			// convert every element in array to JSON dictionary equivalent
+			self.toJSON($0)
+		}
+	}
+	
+	///Maps a dictionary of Objects that conform to Mappable to a JSON dictionary of dictionaries.
+	public func toJSONDictionary(dictionary: [String : N]) -> [String : [String : AnyObject]] {
+		return dictionary.map { k, v in
+			// convert every value in dictionary to its JSON dictionary equivalent
+			return (k, self.toJSON(v))
+		}
+	}
+	
+	///Maps a dictionary of Objects that conform to Mappable to a JSON dictionary of dictionaries.
+	public func toJSONDictionaryOfArrays(dictionary: [String : [N]]) -> [String : [[String : AnyObject]]] {
+		return dictionary.map { k, v in
+			// convert every value (array) in dictionary to its JSON dictionary equivalent
+			return (k, self.toJSONArray(v))
+		}
+	}
+	
+	/// Maps an Object to a JSON string with option of pretty formatting
+	public func toJSONString(object: N, prettyPrint: Bool = false) -> String? {
+		let JSONDict = toJSON(object)
+		
+        return Mapper.toJSONString(JSONDict, prettyPrint: prettyPrint)
+	}
+
+    /// Maps an array of Objects to a JSON string with option of pretty formatting	
+    public func toJSONString(array: [N], prettyPrint: Bool = false) -> String? {
+        let JSONDict = toJSONArray(array)
+        
+        return Mapper.toJSONString(JSONDict, prettyPrint: prettyPrint)
+    }
+	
+    public static func toJSONString(JSONObject: AnyObject, prettyPrint: Bool) -> String? {
+        if NSJSONSerialization.isValidJSONObject(JSONObject) {
+            let JSONData: NSData?
+            do {
+				let options: NSJSONWritingOptions = prettyPrint ? .PrettyPrinted : []
+                JSONData = try NSJSONSerialization.dataWithJSONObject(JSONObject, options: options)
+            } catch let error {
+                print(error)
+                JSONData = nil
+            }
+            
+            if let JSON = JSONData {
+                return String(data: JSON, encoding: NSUTF8StringEncoding)
+            }
+        }
+        return nil
+    }
+}
+
+extension Mapper where N: Hashable {
+	
+	/// Maps a JSON array to an object that conforms to Mappable
+	public func mapSet(JSONString: String) -> Set<N>? {
+		let parsedJSON: AnyObject? = Mapper.parseJSONString(JSONString)
+		
+		if let objectArray = mapArray(parsedJSON){
+			return Set(objectArray)
+		}
+		
+		// failed to parse JSON into array form
+		// try to parse it into a dictionary and then wrap it in an array
+		if let object = map(parsedJSON) {
+			return Set([object])
+		}
+		
+		return nil
+	}
+	
+	/// Maps a JSON object to an Set of Mappable objects if it is an array of JSON dictionary, or returns nil.
+	public func mapSet(JSON: AnyObject?) -> Set<N>? {
+		if let JSONArray = JSON as? [[String : AnyObject]] {
+			return mapSet(JSONArray)
+		}
+		
+		return nil
+	}
+	
+	/// Maps an Set of JSON dictionary to an array of Mappable objects
+	public func mapSet(JSONArray: [[String : AnyObject]]) -> Set<N> {
+		// map every element in JSON array to type N
+		return Set(JSONArray.flatMap(map))
+	}
+
+	///Maps a Set of Objects to a Set of JSON dictionaries [[String : AnyObject]]
+	public func toJSONSet(set: Set<N>) -> [[String : AnyObject]] {
+		return set.map {
+			// convert every element in set to JSON dictionary equivalent
+			self.toJSON($0)
+		}
+	}
+	
+	/// Maps a set of Objects to a JSON string with option of pretty formatting
+	public func toJSONString(set: Set<N>, prettyPrint: Bool = false) -> String? {
+		let JSONDict = toJSONSet(set)
+		
+		return Mapper.toJSONString(JSONDict, prettyPrint: prettyPrint)
+	}
+}
+
+extension Dictionary {
+	internal func map<K: Hashable, V>(@noescape f: Element -> (K, V)) -> [K : V] {
+		var mapped = [K : V]()
+
+		for element in self {
+			let newElement = f(element)
+			mapped[newElement.0] = newElement.1
+		}
+
+		return mapped
+	}
+
+	internal func map<K: Hashable, V>(@noescape f: Element -> (K, [V])) -> [K : [V]] {
+		var mapped = [K : [V]]()
+		
+		for element in self {
+			let newElement = f(element)
+			mapped[newElement.0] = newElement.1
+		}
+		
+		return mapped
+	}
+
+	
+	internal func filterMap<U>(@noescape f: Value -> U?) -> [Key : U] {
+		var mapped = [Key : U]()
+
+		for (key, value) in self {
+			if let newValue = f(value){
+				mapped[key] = newValue
+			}
+		}
+
+		return mapped
+	}
+}

+ 732 - 0
Pods/ObjectMapper/ObjectMapper/Core/Operators.swift

@@ -0,0 +1,732 @@
+//
+//  Operators.swift
+//  ObjectMapper
+//
+//  Created by Tristan Himmelman on 2014-10-09.
+//
+//  The MIT License (MIT)
+//
+//  Copyright (c) 2014-2015 Hearst
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+/**
+* This file defines a new operator which is used to create a mapping between an object and a JSON key value.
+* There is an overloaded operator definition for each type of object that is supported in ObjectMapper.
+* This provides a way to add custom logic to handle specific types of objects
+*/
+
+infix operator <- {}
+
+// MARK:- Objects with Basic types
+
+/// Object of Basic type
+public func <- <T>(inout left: T, right: Map) {
+	switch right.mappingType {
+	case .FromJSON:
+		FromJSON.basicType(&left, object: right.value())
+	case .ToJSON:
+		ToJSON.basicType(left, map: right)
+    }
+}
+
+/// Optional object of basic type
+public func <- <T>(inout left: T?, right: Map) {
+	switch right.mappingType {
+	case .FromJSON:
+        FromJSON.optionalBasicType(&left, object: right.value())
+	case .ToJSON:
+        ToJSON.optionalBasicType(left, map: right)
+    }
+}
+
+/// Implicitly unwrapped optional object of basic type
+public func <- <T>(inout left: T!, right: Map) {
+	switch right.mappingType {
+	case .FromJSON:
+		FromJSON.optionalBasicType(&left, object: right.value())
+	case .ToJSON:
+		ToJSON.optionalBasicType(left, map: right)
+	}
+}
+
+// MARK:- Raw Representable types
+
+/// Object of Raw Representable type
+public func <- <T: RawRepresentable>(inout left: T, right: Map) {
+	left <- (right, EnumTransform())
+}
+
+/// Optional Object of Raw Representable type
+public func <- <T: RawRepresentable>(inout left: T?, right: Map) {
+	left <- (right, EnumTransform())
+}
+
+/// Implicitly Unwrapped Optional Object of Raw Representable type
+public func <- <T: RawRepresentable>(inout left: T!, right: Map) {
+	left <- (right, EnumTransform())
+}
+
+// MARK:- Arrays of Raw Representable type
+
+/// Array of Raw Representable object
+public func <- <T: RawRepresentable>(inout left: [T], right: Map) {
+	left <- (right, EnumTransform())
+}
+
+/// Array of Raw Representable object
+public func <- <T: RawRepresentable>(inout left: [T]?, right: Map) {
+	left <- (right, EnumTransform())
+}
+
+/// Array of Raw Representable object
+public func <- <T: RawRepresentable>(inout left: [T]!, right: Map) {
+	left <- (right, EnumTransform())
+}
+
+// MARK:- Dictionaries of Raw Representable type
+
+/// Dictionary of Raw Representable object
+public func <- <T: RawRepresentable>(inout left: [String: T], right: Map) {
+	left <- (right, EnumTransform())
+}
+
+/// Dictionary of Raw Representable object
+public func <- <T: RawRepresentable>(inout left: [String: T]?, right: Map) {
+	left <- (right, EnumTransform())
+}
+
+/// Dictionary of Raw Representable object
+public func <- <T: RawRepresentable>(inout left: [String: T]!, right: Map) {
+	left <- (right, EnumTransform())
+}
+
+// MARK:- Transforms
+
+/// Object of Basic type with Transform
+public func <- <Transform: TransformType>(inout left: Transform.Object, right: (Map, Transform)) {
+	let (map, transform) = right
+	switch map.mappingType {
+	case .FromJSON:
+        let value = transform.transformFromJSON(map.currentValue)
+        FromJSON.basicType(&left, object: value)
+	case .ToJSON:
+        let value: Transform.JSON? = transform.transformToJSON(left)
+		ToJSON.optionalBasicType(value, map: map)
+    }
+}
+
+/// Optional object of basic type with Transform
+public func <- <Transform: TransformType>(inout left: Transform.Object?, right: (Map, Transform)) {
+	let (map, transform) = right
+	switch map.mappingType {
+	case .FromJSON:
+        let value = transform.transformFromJSON(map.currentValue)
+        FromJSON.optionalBasicType(&left, object: value)
+	case .ToJSON:
+        let value: Transform.JSON? = transform.transformToJSON(left)
+        ToJSON.optionalBasicType(value, map: map)
+    }
+}
+
+/// Implicitly unwrapped optional object of basic type with Transform
+public func <- <Transform: TransformType>(inout left: Transform.Object!, right: (Map, Transform)) {
+	let (map, transform) = right
+	switch map.mappingType {
+	case .FromJSON:
+		let value = transform.transformFromJSON(map.currentValue)
+		FromJSON.optionalBasicType(&left, object: value)
+	case .ToJSON:
+		let value: Transform.JSON? = transform.transformToJSON(left)
+		ToJSON.optionalBasicType(value, map: map)
+	}
+}
+
+/// Array of Basic type with Transform
+public func <- <Transform: TransformType>(inout left: [Transform.Object], right: (Map, Transform)) {
+	let (map, transform) = right
+	switch map.mappingType {
+	case .FromJSON:
+		let values = fromJSONArrayWithTransform(map.currentValue, transform: transform)
+		FromJSON.basicType(&left, object: values)
+	case .ToJSON:
+		let values = toJSONArrayWithTransform(left, transform: transform)
+		ToJSON.optionalBasicType(values, map: map)
+	}
+}
+
+/// Optional array of Basic type with Transform
+public func <- <Transform: TransformType>(inout left: [Transform.Object]?, right: (Map, Transform)) {
+	let (map, transform) = right
+	switch map.mappingType {
+	case .FromJSON:
+		let values = fromJSONArrayWithTransform(map.currentValue, transform: transform)
+		FromJSON.optionalBasicType(&left, object: values)
+	case .ToJSON:
+		let values = toJSONArrayWithTransform(left, transform: transform)
+		ToJSON.optionalBasicType(values, map: map)
+	}
+}
+
+/// Implicitly unwrapped optional array of Basic type with Transform
+public func <- <Transform: TransformType>(inout left: [Transform.Object]!, right: (Map, Transform)) {
+	let (map, transform) = right
+	switch map.mappingType {
+	case .FromJSON:
+		let values = fromJSONArrayWithTransform(map.currentValue, transform: transform)
+		FromJSON.optionalBasicType(&left, object: values)
+	case .ToJSON:
+		let values = toJSONArrayWithTransform(left, transform: transform)
+		ToJSON.optionalBasicType(values, map: map)
+	}
+}
+
+/// Dictionary of Basic type with Transform
+public func <- <Transform: TransformType>(inout left: [String: Transform.Object], right: (Map, Transform)) {
+	let (map, transform) = right
+	switch map.mappingType {
+	case .FromJSON:
+		let values = fromJSONDictionaryWithTransform(map.currentValue, transform: transform)
+		FromJSON.basicType(&left, object: values)
+	case .ToJSON:
+		let values = toJSONDictionaryWithTransform(left, transform: transform)
+		ToJSON.optionalBasicType(values, map: map)
+	}
+}
+
+/// Optional dictionary of Basic type with Transform
+public func <- <Transform: TransformType>(inout left: [String: Transform.Object]?, right: (Map, Transform)) {
+	let (map, transform) = right
+	switch map.mappingType {
+	case .FromJSON:
+		let values = fromJSONDictionaryWithTransform(map.currentValue, transform: transform)
+		FromJSON.optionalBasicType(&left, object: values)
+	case .ToJSON:
+		let values = toJSONDictionaryWithTransform(left, transform: transform)
+		ToJSON.optionalBasicType(values, map: map)
+	}
+}
+
+/// Implicitly unwrapped optional dictionary of Basic type with Transform
+public func <- <Transform: TransformType>(inout left: [String: Transform.Object]!, right: (Map, Transform)) {
+	let (map, transform) = right
+	switch map.mappingType {
+	case .FromJSON:
+		let values = fromJSONDictionaryWithTransform(map.currentValue, transform: transform)
+		FromJSON.optionalBasicType(&left, object: values)
+	case .ToJSON:
+		let values = toJSONDictionaryWithTransform(left, transform: transform)
+		ToJSON.optionalBasicType(values, map: map)
+	}
+}
+
+private func fromJSONArrayWithTransform<Transform: TransformType>(input: AnyObject?, transform: Transform) -> [Transform.Object]? {
+	if let values = input as? [AnyObject] {
+		return values.flatMap { value in
+			return transform.transformFromJSON(value)
+		}
+	} else {
+		return nil
+	}
+}
+
+private func fromJSONDictionaryWithTransform<Transform: TransformType>(input: AnyObject?, transform: Transform) -> [String: Transform.Object]? {
+	if let values = input as? [String: AnyObject] {
+		return values.filterMap { value in
+			return transform.transformFromJSON(value)
+		}
+	} else {
+		return nil
+	}
+}
+
+private func toJSONArrayWithTransform<Transform: TransformType>(input: [Transform.Object]?, transform: Transform) -> [Transform.JSON]? {
+	return input?.flatMap { value in
+		return transform.transformToJSON(value)
+	}
+}
+
+private func toJSONDictionaryWithTransform<Transform: TransformType>(input: [String: Transform.Object]?, transform: Transform) -> [String: Transform.JSON]? {
+	return input?.filterMap { value in
+		return transform.transformToJSON(value)
+	}
+}
+
+// MARK:- Mappable Objects - <T: Mappable>
+
+/// Object conforming to Mappable
+public func <- <T: Mappable>(inout left: T, right: Map) {
+	switch right.mappingType {
+	case .FromJSON:
+        FromJSON.object(&left, map: right)
+	case .ToJSON:
+		ToJSON.object(left, map: right)
+    }
+}
+
+/// Optional Mappable objects
+public func <- <T: Mappable>(inout left: T?, right: Map) {
+	switch right.mappingType {
+	case .FromJSON:
+        FromJSON.optionalObject(&left, map: right)
+	case .ToJSON:
+		ToJSON.optionalObject(left, map: right)
+    }
+}
+
+/// Implicitly unwrapped optional Mappable objects
+public func <- <T: Mappable>(inout left: T!, right: Map) {
+	switch right.mappingType {
+	case .FromJSON:
+		FromJSON.optionalObject(&left, map: right)
+	case .ToJSON:
+		ToJSON.optionalObject(left, map: right)
+	}
+}
+
+// MARK:- Transforms of Mappable Objects - <T: Mappable>
+
+/// Object conforming to Mappable that have transforms
+public func <- <Transform: TransformType where Transform.Object: Mappable>(inout left: Transform.Object, right: (Map, Transform)) {
+	let (map, transform) = right
+	switch map.mappingType {
+	case .FromJSON:
+		let value: Transform.Object? = transform.transformFromJSON(map.currentValue)
+		FromJSON.basicType(&left, object: value)
+	case .ToJSON:
+		let value: Transform.JSON? = transform.transformToJSON(left)
+		ToJSON.optionalBasicType(value, map: map)
+	}
+}
+
+/// Optional Mappable objects that have transforms
+public func <- <Transform: TransformType where Transform.Object: Mappable>(inout left: Transform.Object?, right: (Map, Transform)) {
+	let (map, transform) = right
+	switch map.mappingType {
+	case .FromJSON:
+		let value: Transform.Object? = transform.transformFromJSON(map.currentValue)
+		FromJSON.optionalBasicType(&left, object: value)
+	case .ToJSON:
+		let value: Transform.JSON? = transform.transformToJSON(left)
+		ToJSON.optionalBasicType(value, map: map)
+	}
+}
+
+/// Implicitly unwrapped optional Mappable objects that have transforms
+public func <- <Transform: TransformType where Transform.Object: Mappable>(inout left: Transform.Object!, right: (Map, Transform)) {
+	let (map, transform) = right
+	switch map.mappingType {
+	case .FromJSON:
+		let value: Transform.Object? = transform.transformFromJSON(map.currentValue)
+		FromJSON.optionalBasicType(&left, object: value)
+	case .ToJSON:
+		let value: Transform.JSON? = transform.transformToJSON(left)
+		ToJSON.optionalBasicType(value, map: map)
+	}
+}
+
+// MARK:- Dictionary of Mappable objects - Dictionary<String, T: Mappable>
+
+/// Dictionary of Mappable objects <String, T: Mappable>
+public func <- <T: Mappable>(inout left: Dictionary<String, T>, right: Map) {
+	switch right.mappingType {
+	case .FromJSON:
+        FromJSON.objectDictionary(&left, map: right)
+	case .ToJSON:
+        ToJSON.objectDictionary(left, map: right)
+    }
+}
+
+/// Optional Dictionary of Mappable object <String, T: Mappable>
+public func <- <T: Mappable>(inout left: Dictionary<String, T>?, right: Map) {
+	switch right.mappingType {
+	case .FromJSON:
+        FromJSON.optionalObjectDictionary(&left, map: right)
+	case .ToJSON:
+        ToJSON.optionalObjectDictionary(left, map: right)
+    }
+}
+
+/// Implicitly unwrapped Optional Dictionary of Mappable object <String, T: Mappable>
+public func <- <T: Mappable>(inout left: Dictionary<String, T>!, right: Map) {
+	switch right.mappingType {
+	case .FromJSON:
+		FromJSON.optionalObjectDictionary(&left, map: right)
+	case .ToJSON:
+		ToJSON.optionalObjectDictionary(left, map: right)
+	}
+}
+
+/// Dictionary of Mappable objects <String, T: Mappable>
+public func <- <T: Mappable>(inout left: Dictionary<String, [T]>, right: Map) {
+	switch right.mappingType {
+	case .FromJSON:
+		FromJSON.objectDictionaryOfArrays(&left, map: right)
+	case .ToJSON:
+		ToJSON.objectDictionaryOfArrays(left, map: right)
+	}
+}
+
+/// Optional Dictionary of Mappable object <String, T: Mappable>
+public func <- <T: Mappable>(inout left: Dictionary<String, [T]>?, right: Map) {
+	switch right.mappingType {
+	case .FromJSON:
+		FromJSON.optionalObjectDictionaryOfArrays(&left, map: right)
+	case .ToJSON:
+		ToJSON.optionalObjectDictionaryOfArrays(left, map: right)
+	}
+}
+
+/// Implicitly unwrapped Optional Dictionary of Mappable object <String, T: Mappable>
+public func <- <T: Mappable>(inout left: Dictionary<String, [T]>!, right: Map) {
+	switch right.mappingType {
+	case .FromJSON:
+		FromJSON.optionalObjectDictionaryOfArrays(&left, map: right)
+	case .ToJSON:
+		ToJSON.optionalObjectDictionaryOfArrays(left, map: right)
+	}
+}
+
+// MARK:- Dictionary of Mappable objects with a transform - Dictionary<String, T: Mappable>
+
+/// Dictionary of Mappable objects <String, T: Mappable> with a transform
+public func <- <Transform: TransformType where Transform.Object: Mappable>(inout left: Dictionary<String, Transform.Object>, right: (Map, Transform)) {
+	let (map, transform) = right
+	if let object = map.currentValue as? [String : AnyObject] where map.mappingType == .FromJSON {
+		let value = fromJSONDictionaryWithTransform(object, transform: transform) ?? left
+		FromJSON.basicType(&left, object: value)
+	} else if map.mappingType == .ToJSON {
+		let value = toJSONDictionaryWithTransform(left, transform: transform)
+		ToJSON.basicType(value, map: map)
+	}
+}
+
+/// Optional Dictionary of Mappable object <String, T: Mappable> with a transform
+public func <- <Transform: TransformType where Transform.Object: Mappable>(inout left: Dictionary<String, Transform.Object>?, right: (Map, Transform)) {
+	let (map, transform) = right
+	if let object = map.currentValue as? [String : AnyObject] where map.mappingType == .FromJSON {
+		let value = fromJSONDictionaryWithTransform(object, transform: transform) ?? left
+		FromJSON.optionalBasicType(&left, object: value)
+	} else if map.mappingType == .ToJSON {
+		let value = toJSONDictionaryWithTransform(left, transform: transform)
+		ToJSON.optionalBasicType(value, map: map)
+	}
+}
+
+/// Implicitly unwrapped Optional Dictionary of Mappable object <String, T: Mappable> with a transform
+public func <- <Transform: TransformType where Transform.Object: Mappable>(inout left: Dictionary<String, Transform.Object>!, right: (Map, Transform)) {
+	let (map, transform) = right
+	if let dictionary = map.currentValue as? [String : AnyObject] where map.mappingType == .FromJSON {
+		let transformedDictionary = fromJSONDictionaryWithTransform(dictionary, transform: transform) ?? left
+		FromJSON.optionalBasicType(&left, object: transformedDictionary)
+	} else if map.mappingType == .ToJSON {
+		let value = toJSONDictionaryWithTransform(left, transform: transform)
+		ToJSON.optionalBasicType(value, map: map)
+	}
+}
+
+/// Dictionary of Mappable objects <String, T: Mappable> with a transform
+public func <- <Transform: TransformType where Transform.Object: Mappable>(inout left: Dictionary<String, [Transform.Object]>, right: (Map, Transform)) {
+	let (map, transform) = right
+	if let dictionary = map.currentValue as? [String : [AnyObject]] where map.mappingType == .FromJSON {
+		let transformedDictionary = dictionary.map { (key, values) in
+			return (key, fromJSONArrayWithTransform(values, transform: transform) ?? left[key] ?? [])
+		}
+		FromJSON.basicType(&left, object: transformedDictionary)
+	} else if map.mappingType == .ToJSON {
+		let transformedDictionary = left.map { (key, values) in
+			return (key, toJSONArrayWithTransform(values, transform: transform) ?? [])
+		}
+
+		ToJSON.basicType(transformedDictionary, map: map)
+	}
+}
+
+/// Optional Dictionary of Mappable object <String, T: Mappable> with a transform
+public func <- <Transform: TransformType where Transform.Object: Mappable>(inout left: Dictionary<String, [Transform.Object]>?, right: (Map, Transform)) {
+	let (map, transform) = right
+	if let dictionary = map.currentValue as? [String : [AnyObject]] where map.mappingType == .FromJSON {
+		let transformedDictionary = dictionary.map { (key, values) in
+			return (key, fromJSONArrayWithTransform(values, transform: transform) ?? left?[key] ?? [])
+		}
+		FromJSON.optionalBasicType(&left, object: transformedDictionary)
+	} else if map.mappingType == .ToJSON {
+		let transformedDictionary = left?.map { (key, values) in
+			return (key, toJSONArrayWithTransform(values, transform: transform) ?? [])
+		}
+		
+		ToJSON.optionalBasicType(transformedDictionary, map: map)
+	}
+}
+
+/// Implicitly unwrapped Optional Dictionary of Mappable object <String, T: Mappable> with a transform
+public func <- <Transform: TransformType where Transform.Object: Mappable>(inout left: Dictionary<String, [Transform.Object]>!, right: (Map, Transform)) {
+	let (map, transform) = right
+	if let dictionary = map.currentValue as? [String : [AnyObject]] where map.mappingType == .FromJSON {
+		let transformedDictionary = dictionary.map { (key, values) in
+			return (key, fromJSONArrayWithTransform(values, transform: transform) ?? left?[key] ?? [])
+		}
+		FromJSON.optionalBasicType(&left, object: transformedDictionary)
+	} else if map.mappingType == .ToJSON {
+		let transformedDictionary = left?.map { (key, values) in
+			return (key, toJSONArrayWithTransform(values, transform: transform) ?? [])
+		}
+		
+		ToJSON.optionalBasicType(transformedDictionary, map: map)
+	}
+}
+
+// MARK:- Array of Mappable objects - Array<T: Mappable>
+
+/// Array of Mappable objects
+public func <- <T: Mappable>(inout left: Array<T>, right: Map) {
+	switch right.mappingType {
+	case .FromJSON:
+        FromJSON.objectArray(&left, map: right)
+	case .ToJSON:
+		ToJSON.objectArray(left, map: right)
+    }
+}
+
+/// Optional array of Mappable objects
+public func <- <T: Mappable>(inout left: Array<T>?, right: Map) {
+	switch right.mappingType {
+	case .FromJSON:
+        FromJSON.optionalObjectArray(&left, map: right)
+	case .ToJSON:
+		ToJSON.optionalObjectArray(left, map: right)
+    }
+}
+
+/// Implicitly unwrapped Optional array of Mappable objects
+public func <- <T: Mappable>(inout left: Array<T>!, right: Map) {
+	switch right.mappingType {
+	case .FromJSON:
+		FromJSON.optionalObjectArray(&left, map: right)
+	case .ToJSON:
+		ToJSON.optionalObjectArray(left, map: right)
+	}
+}
+
+// MARK:- Array of Mappable objects with transforms - Array<T: Mappable>
+
+/// Array of Mappable objects
+public func <- <Transform: TransformType where Transform.Object: Mappable>(inout left: Array<Transform.Object>, right: (Map, Transform)) {
+	let (map, transform) = right
+	switch map.mappingType {
+	case .FromJSON:
+		if let transformedValues = fromJSONArrayWithTransform(map.currentValue, transform: transform) {
+			FromJSON.basicType(&left, object: transformedValues)
+		}
+	case .ToJSON:
+		let transformedValues = toJSONArrayWithTransform(left, transform: transform)
+		ToJSON.optionalBasicType(transformedValues, map: map)
+	}
+}
+
+/// Optional array of Mappable objects
+public func <- <Transform: TransformType where Transform.Object: Mappable>(inout left: Array<Transform.Object>?, right: (Map, Transform)) {
+	let (map, transform) = right
+	switch map.mappingType {
+	case .FromJSON:
+		let transformedValues = fromJSONArrayWithTransform(map.currentValue, transform: transform)
+		FromJSON.optionalBasicType(&left, object: transformedValues)
+	case .ToJSON:
+		let transformedValues = toJSONArrayWithTransform(left, transform: transform)
+		ToJSON.optionalBasicType(transformedValues, map: map)
+	}
+}
+
+/// Implicitly unwrapped Optional array of Mappable objects
+public func <- <Transform: TransformType where Transform.Object: Mappable>(inout left: Array<Transform.Object>!, right: (Map, Transform)) {
+	let (map, transform) = right
+	switch map.mappingType {
+	case .FromJSON:
+		let transformedValues = fromJSONArrayWithTransform(map.currentValue, transform: transform)
+		FromJSON.optionalBasicType(&left, object: transformedValues)
+	case .ToJSON:
+		let transformedValues = toJSONArrayWithTransform(left, transform: transform)
+		ToJSON.optionalBasicType(transformedValues, map: map)
+	}
+}
+
+// MARK:- Array of Array of Mappable objects - Array<Array<T: Mappable>>
+
+/// Array of Array Mappable objects
+public func <- <T: Mappable>(inout left: Array<Array<T>>, right: Map) {
+	switch right.mappingType {
+	case .FromJSON:
+		FromJSON.twoDimensionalObjectArray(&left, map: right)
+	case .ToJSON:
+		ToJSON.twoDimensionalObjectArray(left, map: right)
+	}
+}
+
+/// Optional array of Mappable objects
+public func <- <T: Mappable>(inout left:Array<Array<T>>?, right: Map) {
+	switch right.mappingType {
+	case .FromJSON:
+		FromJSON.optionalTwoDimensionalObjectArray(&left, map: right)
+	case .ToJSON:
+		ToJSON.optionalTwoDimensionalObjectArray(left, map: right)
+	}
+}
+
+/// Implicitly unwrapped Optional array of Mappable objects
+public func <- <T: Mappable>(inout left: Array<Array<T>>!, right: Map) {
+	switch right.mappingType {
+	case .FromJSON:
+		FromJSON.optionalTwoDimensionalObjectArray(&left, map: right)
+	case .ToJSON:
+		ToJSON.optionalTwoDimensionalObjectArray(left, map: right)
+	}
+}
+
+// MARK:- Array of Array of Mappable objects - Array<Array<T: Mappable>> with transforms
+
+/// Array of Array Mappable objects with transform
+public func <- <Transform: TransformType where Transform.Object: Mappable>(inout left: Array<Array<Transform.Object>>, right: (Map, Transform)) {
+	let (map, transform) = right
+	if let original2DArray = map.currentValue as? [[AnyObject]] where map.mappingType == .FromJSON {
+		let transformed2DArray = original2DArray.flatMap { values in
+			fromJSONArrayWithTransform(values, transform: transform)
+		}
+		FromJSON.basicType(&left, object: transformed2DArray)
+	} else if map.mappingType == .ToJSON {
+		let transformed2DArray = left.flatMap { values in
+			toJSONArrayWithTransform(values, transform: transform)
+		}
+		ToJSON.basicType(transformed2DArray, map: map)
+	}
+}
+
+/// Optional array of Mappable objects with transform
+public func <- <Transform: TransformType where Transform.Object: Mappable>(inout left:Array<Array<Transform.Object>>?, right: (Map, Transform)) {
+	let (map, transform) = right
+	if let original2DArray = map.currentValue as? [[AnyObject]] where map.mappingType == .FromJSON {
+		let transformed2DArray = original2DArray.flatMap { values in
+			fromJSONArrayWithTransform(values, transform: transform)
+		}
+		FromJSON.optionalBasicType(&left, object: transformed2DArray)
+	} else if map.mappingType == .ToJSON {
+		let transformed2DArray = left?.flatMap { values in
+			toJSONArrayWithTransform(values, transform: transform)
+		}
+		ToJSON.optionalBasicType(transformed2DArray, map: map)
+	}
+}
+
+/// Implicitly unwrapped Optional array of Mappable objects with transform
+public func <- <Transform: TransformType where Transform.Object: Mappable>(inout left: Array<Array<Transform.Object>>!, right: (Map, Transform)) {
+	let (map, transform) = right
+	if let original2DArray = map.currentValue as? [[AnyObject]] where map.mappingType == .FromJSON {
+		let transformed2DArray = original2DArray.flatMap { values in
+			fromJSONArrayWithTransform(values, transform: transform)
+		}
+		FromJSON.optionalBasicType(&left, object: transformed2DArray)
+	} else if map.mappingType == .ToJSON {
+		let transformed2DArray = left?.flatMap { values in
+			toJSONArrayWithTransform(values, transform: transform)
+		}
+		ToJSON.optionalBasicType(transformed2DArray, map: map)
+	}
+}
+
+// MARK:- Set of Mappable objects - Set<T: Mappable where T: Hashable>
+
+/// Set of Mappable objects
+public func <- <T: Mappable where T: Hashable>(inout left: Set<T>, right: Map) {
+	switch right.mappingType {
+	case .FromJSON:
+		FromJSON.objectSet(&left, map: right)
+	case .ToJSON:
+		ToJSON.objectSet(left, map: right)
+	}
+}
+
+
+/// Optional Set of Mappable objects
+public func <- <T: Mappable where T: Hashable>(inout left: Set<T>?, right: Map) {
+	switch right.mappingType {
+	case .FromJSON:
+		FromJSON.optionalObjectSet(&left, map: right)
+	case .ToJSON:
+		ToJSON.optionalObjectSet(left, map: right)
+	}
+}
+
+/// Implicitly unwrapped Optional Set of Mappable objects
+public func <- <T: Mappable where T: Hashable>(inout left: Set<T>!, right: Map) {
+	switch right.mappingType {
+	case .FromJSON:
+		FromJSON.optionalObjectSet(&left, map: right)
+	case .ToJSON:
+		ToJSON.optionalObjectSet(left, map: right)
+	}
+}
+
+
+// MARK:- Set of Mappable objects with a transform - Set<T: Mappable where T: Hashable>
+
+/// Set of Mappable objects with transform
+public func <- <Transform: TransformType where Transform.Object: protocol<Hashable, Mappable>>(inout left: Set<Transform.Object>, right: (Map, Transform)) {
+	let (map, transform) = right
+	switch map.mappingType {
+	case .FromJSON:
+		if let transformedValues = fromJSONArrayWithTransform(map.currentValue, transform: transform) {
+			FromJSON.basicType(&left, object: Set(transformedValues))
+		}
+	case .ToJSON:
+		let transformedValues = toJSONArrayWithTransform(Array(left), transform: transform)
+		ToJSON.optionalBasicType(transformedValues, map: map)
+	}
+}
+
+
+/// Optional Set of Mappable objects with transform
+public func <- <Transform: TransformType where Transform.Object: protocol<Hashable, Mappable>>(inout left: Set<Transform.Object>?, right: (Map, Transform)) {
+	let (map, transform) = right
+	switch map.mappingType {
+	case .FromJSON:
+		if let transformedValues = fromJSONArrayWithTransform(map.currentValue, transform: transform) {
+			FromJSON.basicType(&left, object: Set(transformedValues))
+		}
+	case .ToJSON:
+		if let values = left {
+			let transformedValues = toJSONArrayWithTransform(Array(values), transform: transform)
+			ToJSON.optionalBasicType(transformedValues, map: map)
+		}
+	}
+}
+
+/// Implicitly unwrapped Optional set of Mappable objects with transform
+public func <- <Transform: TransformType where Transform.Object: protocol<Hashable, Mappable>>(inout left: Set<Transform.Object>!, right: (Map, Transform)) {
+	let (map, transform) = right
+	switch map.mappingType {
+	case .FromJSON:
+		if let transformedValues = fromJSONArrayWithTransform(map.currentValue, transform: transform) {
+			FromJSON.basicType(&left, object: Set(transformedValues))
+		}
+	case .ToJSON:
+		if let values = left {
+			let transformedValues = toJSONArrayWithTransform(Array(values), transform: transform)
+			ToJSON.optionalBasicType(transformedValues, map: map)
+		}
+	}
+}

+ 174 - 0
Pods/ObjectMapper/ObjectMapper/Core/ToJSON.swift

@@ -0,0 +1,174 @@
+//
+//  ToJSON.swift
+//  ObjectMapper
+//
+//  Created by Tristan Himmelman on 2014-10-13.
+//
+//  The MIT License (MIT)
+//
+//  Copyright (c) 2014-2015 Hearst
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+import class Foundation.NSNumber
+
+private func setValue(value: AnyObject, map: Map) {
+	setValue(value, key: map.currentKey!, checkForNestedKeys: map.keyIsNested, dictionary: &map.JSONDictionary)
+}
+
+private func setValue(value: AnyObject, key: String, checkForNestedKeys: Bool, inout dictionary: [String : AnyObject]) {
+	if checkForNestedKeys {
+		let keyComponents = ArraySlice(key.characters.split { $0 == "." })
+		setValue(value, forKeyPathComponents: keyComponents, dictionary: &dictionary)
+	} else {
+		dictionary[key] = value
+	}
+}
+
+private func setValue(value: AnyObject, forKeyPathComponents components: ArraySlice<String.CharacterView.SubSequence>, inout dictionary: [String : AnyObject]) {
+	if components.isEmpty {
+		return
+	}
+
+	let head = components.first!
+
+	if components.count == 1 {
+		dictionary[String(head)] = value
+	} else {
+		var child = dictionary[String(head)] as? [String : AnyObject]
+		if child == nil {
+			child = [:]
+		}
+
+		let tail = components.dropFirst()
+		setValue(value, forKeyPathComponents: tail, dictionary: &child!)
+
+		dictionary[String(head)] = child
+	}
+}
+
+internal final class ToJSON {
+	
+	class func basicType<N>(field: N, map: Map) {
+		if let x = field as? AnyObject where false
+			|| x is NSNumber // Basic types
+			|| x is Bool
+			|| x is Int
+			|| x is Double
+			|| x is Float
+			|| x is String
+			|| x is Array<NSNumber> // Arrays
+			|| x is Array<Bool>
+			|| x is Array<Int>
+			|| x is Array<Double>
+			|| x is Array<Float>
+			|| x is Array<String>
+			|| x is Array<AnyObject>
+			|| x is Array<Dictionary<String, AnyObject>>
+			|| x is Dictionary<String, NSNumber> // Dictionaries
+			|| x is Dictionary<String, Bool>
+			|| x is Dictionary<String, Int>
+			|| x is Dictionary<String, Double>
+			|| x is Dictionary<String, Float>
+			|| x is Dictionary<String, String>
+			|| x is Dictionary<String, AnyObject>
+		{
+			setValue(x, map: map)
+		}
+	}
+
+	class func optionalBasicType<N>(field: N?, map: Map) {
+		if let field = field {
+			basicType(field, map: map)
+		}
+	}
+
+	class func object<N: Mappable>(field: N, map: Map) {
+		setValue(Mapper().toJSON(field), map: map)
+	}
+	
+	class func optionalObject<N: Mappable>(field: N?, map: Map) {
+		if let field = field {
+			object(field, map: map)
+		}
+	}
+
+	class func objectArray<N: Mappable>(field: Array<N>, map: Map) {
+		let JSONObjects = Mapper().toJSONArray(field)
+		
+		setValue(JSONObjects, map: map)
+	}
+	
+	class func optionalObjectArray<N: Mappable>(field: Array<N>?, map: Map) {
+		if let field = field {
+			objectArray(field, map: map)
+		}
+	}
+	
+	class func twoDimensionalObjectArray<N: Mappable>(field: Array<Array<N>>, map: Map) {
+		var array = [[[String : AnyObject]]]()
+		for innerArray in field {
+			let JSONObjects = Mapper().toJSONArray(innerArray)
+			array.append(JSONObjects)
+		}
+		setValue(array, map: map)
+	}
+	
+	class func optionalTwoDimensionalObjectArray<N: Mappable>(field: Array<Array<N>>?, map: Map) {
+		if let field = field {
+			twoDimensionalObjectArray(field, map: map)
+		}
+	}
+	
+	class func objectSet<N: Mappable where N: Hashable>(field: Set<N>, map: Map) {
+		let JSONObjects = Mapper().toJSONSet(field)
+		
+		setValue(JSONObjects, map: map)
+	}
+	
+	class func optionalObjectSet<N: Mappable where N: Hashable>(field: Set<N>?, map: Map) {
+		if let field = field {
+			objectSet(field, map: map)
+		}
+	}
+	
+	class func objectDictionary<N: Mappable>(field: Dictionary<String, N>, map: Map) {
+		let JSONObjects = Mapper().toJSONDictionary(field)
+		
+		setValue(JSONObjects, map: map)
+	}
+	
+	class func optionalObjectDictionary<N: Mappable>(field: Dictionary<String, N>?, map: Map) {
+        if let field = field {
+			objectDictionary(field, map: map)
+        }
+    }
+	
+	class func objectDictionaryOfArrays<N: Mappable>(field: Dictionary<String, [N]>, map: Map) {
+		let JSONObjects = Mapper().toJSONDictionaryOfArrays(field)
+
+		setValue(JSONObjects, map: map)
+	}
+	
+	class func optionalObjectDictionaryOfArrays<N: Mappable>(field: Dictionary<String, [N]>?, map: Map) {
+		if let field = field {
+			objectDictionaryOfArrays(field, map: map)
+		}
+	}
+}

+ 40 - 0
Pods/ObjectMapper/ObjectMapper/Transforms/CustomDateFormatTransform.swift

@@ -0,0 +1,40 @@
+//
+//  CustomDateFormatTransform.swift
+//  ObjectMapper
+//
+//  Created by Dan McCracken on 3/8/15.
+//
+//  The MIT License (MIT)
+//
+//  Copyright (c) 2014-2015 Hearst
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+import Foundation
+
+public class CustomDateFormatTransform: DateFormatterTransform {
+	
+    public init(formatString: String) {
+		let formatter = NSDateFormatter()
+		formatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
+		formatter.dateFormat = formatString
+		
+		super.init(dateFormatter: formatter)
+    }
+}

+ 54 - 0
Pods/ObjectMapper/ObjectMapper/Transforms/DateFormatterTransform.swift

@@ -0,0 +1,54 @@
+//
+//  DateFormatterTransform.swift
+//  ObjectMapper
+//
+//  Created by Tristan Himmelman on 2015-03-09.
+//
+//  The MIT License (MIT)
+//
+//  Copyright (c) 2014-2015 Hearst
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+import Foundation
+
+public class DateFormatterTransform: TransformType {
+	public typealias Object = NSDate
+	public typealias JSON = String
+	
+	let dateFormatter: NSDateFormatter
+	
+	public init(dateFormatter: NSDateFormatter) {
+		self.dateFormatter = dateFormatter
+	}
+	
+	public func transformFromJSON(value: AnyObject?) -> NSDate? {
+		if let dateString = value as? String {
+			return dateFormatter.dateFromString(dateString)
+		}
+		return nil
+	}
+	
+	public func transformToJSON(value: NSDate?) -> String? {
+		if let date = value {
+			return dateFormatter.stringFromDate(date)
+		}
+		return nil
+	}
+}

+ 55 - 0
Pods/ObjectMapper/ObjectMapper/Transforms/DateTransform.swift

@@ -0,0 +1,55 @@
+//
+//  DateTransform.swift
+//  ObjectMapper
+//
+//  Created by Tristan Himmelman on 2014-10-13.
+//
+//  The MIT License (MIT)
+//
+//  Copyright (c) 2014-2015 Hearst
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+import Foundation
+
+public class DateTransform: TransformType {
+	public typealias Object = NSDate
+	public typealias JSON = Double
+
+	public init() {}
+
+	public func transformFromJSON(value: AnyObject?) -> NSDate? {
+		if let timeInt = value as? Double {
+			return NSDate(timeIntervalSince1970: NSTimeInterval(timeInt))
+		}
+		
+		if let timeStr = value as? String {
+			return NSDate(timeIntervalSince1970: NSTimeInterval(atof(timeStr)))
+		}
+		
+		return nil
+	}
+
+	public func transformToJSON(value: NSDate?) -> Double? {
+		if let date = value {
+			return Double(date.timeIntervalSince1970)
+		}
+		return nil
+	}
+}

+ 50 - 0
Pods/ObjectMapper/ObjectMapper/Transforms/EnumTransform.swift

@@ -0,0 +1,50 @@
+//
+//  EnumTransform.swift
+//  ObjectMapper
+//
+//  Created by Kaan Dedeoglu on 3/20/15.
+//
+//  The MIT License (MIT)
+//
+//  Copyright (c) 2014-2015 Hearst
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+import Foundation
+
+public class EnumTransform<T: RawRepresentable>: TransformType {
+	public typealias Object = T
+	public typealias JSON = T.RawValue
+	
+	public init() {}
+	
+	public func transformFromJSON(value: AnyObject?) -> T? {
+		if let raw = value as? T.RawValue {
+			return T(rawValue: raw)
+		}
+		return nil
+	}
+	
+	public func transformToJSON(value: T?) -> T.RawValue? {
+		if let obj = value {
+			return obj.rawValue
+		}
+		return nil
+	}
+}

+ 41 - 0
Pods/ObjectMapper/ObjectMapper/Transforms/ISO8601DateTransform.swift

@@ -0,0 +1,41 @@
+//
+//  ISO8601DateTransform.swift
+//  ObjectMapper
+//
+//  Created by Jean-Pierre Mouilleseaux on 21 Nov 2014.
+//
+//  The MIT License (MIT)
+//
+//  Copyright (c) 2014-2015 Hearst
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+import Foundation
+
+public class ISO8601DateTransform: DateFormatterTransform {
+
+	public init() {
+		let formatter = NSDateFormatter()
+		formatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
+		formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
+		
+		super.init(dateFormatter: formatter)
+	}
+	
+}

+ 48 - 0
Pods/ObjectMapper/ObjectMapper/Transforms/TransformOf.swift

@@ -0,0 +1,48 @@
+//
+//  TransformOf.swift
+//  ObjectMapper
+//
+//  Created by Syo Ikeda on 1/23/15.
+//
+//  The MIT License (MIT)
+//
+//  Copyright (c) 2014-2015 Hearst
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+public class TransformOf<ObjectType, JSONType>: TransformType {
+	public typealias Object = ObjectType
+	public typealias JSON = JSONType
+
+	private let fromJSON: JSONType? -> ObjectType?
+	private let toJSON: ObjectType? -> JSONType?
+
+	public init(fromJSON: JSONType? -> ObjectType?, toJSON: ObjectType? -> JSONType?) {
+		self.fromJSON = fromJSON
+		self.toJSON = toJSON
+	}
+
+	public func transformFromJSON(value: AnyObject?) -> ObjectType? {
+		return fromJSON(value as? JSONType)
+	}
+
+	public func transformToJSON(value: ObjectType?) -> JSONType? {
+		return toJSON(value)
+	}
+}

+ 35 - 0
Pods/ObjectMapper/ObjectMapper/Transforms/TransformType.swift

@@ -0,0 +1,35 @@
+//
+//  TransformType.swift
+//  ObjectMapper
+//
+//  Created by Syo Ikeda on 2/4/15.
+//
+//  The MIT License (MIT)
+//
+//  Copyright (c) 2014-2015 Hearst
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+public protocol TransformType {
+	typealias Object
+	typealias JSON
+
+	func transformFromJSON(value: AnyObject?) -> Object?
+	func transformToJSON(value: Object?) -> JSON?
+}

+ 50 - 0
Pods/ObjectMapper/ObjectMapper/Transforms/URLTransform.swift

@@ -0,0 +1,50 @@
+//
+//  URLTransform.swift
+//  ObjectMapper
+//
+//  Created by Tristan Himmelman on 2014-10-27.
+//
+//  The MIT License (MIT)
+//
+//  Copyright (c) 2014-2015 Hearst
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+import Foundation
+
+public class URLTransform: TransformType {
+	public typealias Object = NSURL
+	public typealias JSON = String
+
+	public init() {}
+
+	public func transformFromJSON(value: AnyObject?) -> NSURL? {
+		if let URLString = value as? String {
+			return NSURL(string: URLString)
+		}
+		return nil
+	}
+
+	public func transformToJSON(value: NSURL?) -> String? {
+		if let URL = value {
+			return URL.absoluteString
+		}
+		return nil
+	}
+}

+ 316 - 0
Pods/ObjectMapper/README.md

@@ -0,0 +1,316 @@
+ObjectMapper
+============
+[![CocoaPods](https://img.shields.io/cocoapods/v/ObjectMapper.svg)](https://github.com/Hearst-DD/ObjectMapper)
+[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)
+[![Build Status](https://travis-ci.org/Hearst-DD/ObjectMapper.svg?branch=master)](https://travis-ci.org/Hearst-DD/ObjectMapper)
+
+ObjectMapper is a framework written in Swift that makes it easy for you to convert your model objects (classes and structs) to and from JSON. 
+
+- [Features](#features)
+- [The Basics](#the-basics)
+- [Mapping Nested Objects](#easy-mapping-of-nested-objects)
+- [Custom Transformations](#custom-transfoms)
+- [Subclassing](#subclasses)
+- [Generic Objects](#generic-objects)
+- [ObjectMapper + Alamofire](#objectmapper--alamofire) 
+- [ObjectMapper + Realm](#objectmapper--realm)
+- [To Do](#to-do)
+- [Contributing](#contributing)
+- [Installation](#installation)
+
+# Features:
+- Mapping JSON to objects
+- Mapping objects to JSON
+- Nested Objects (stand alone, in arrays or in dictionaries)
+- Custom transformations during mapping
+- Struct support
+
+# The Basics
+To support mapping, a class or struct just needs to implement the ```Mappable``` protocol.
+```swift
+public protocol Mappable {
+	init?(_ map: Map)
+    mutating func mapping(map: Map)
+}
+```
+ObjectMapper uses the ```<-``` operator to define how each member variable maps to and from JSON.
+
+```swift
+class User: Mappable {
+    var username: String?
+    var age: Int?
+    var weight: Double!
+    var array: [AnyObject]?
+    var dictionary: [String : AnyObject] = [:]
+    var bestFriend: User?                       // Nested User object
+    var friends: [User]?                        // Array of Users
+    var birthday: NSDate?
+
+	required init?(_ map: Map) {
+
+	}
+
+    // Mappable
+    func mapping(map: Map) {
+        username    <- map["username"]
+        age         <- map["age"]
+        weight      <- map["weight"]
+        array       <- map["arr"]
+        dictionary  <- map["dict"]
+        bestFriend  <- map["best_friend"]
+        friends     <- map["friends"]
+        birthday    <- (map["birthday"], DateTransform())
+    }
+}
+
+struct Temperature: Mappable {
+    var celsius: Double?
+    var fahrenheit: Double?
+
+    init?(_ map: Map) {
+
+    }
+
+    mutating func mapping(map: Map) {
+        celsius 	<- map["celsius"]
+        fahrenheit 	<- map["fahrenheit"]
+    }
+}
+```
+
+Once your class implements `Mappable`, the Mapper class handles everything else for you:
+
+Convert a JSON string to a model object:
+```swift
+let user = Mapper<User>().map(JSONString)
+```
+
+Convert a model object to a JSON string:
+```swift
+let JSONString = Mapper().toJSONString(user, prettyPrint: true)
+```
+
+ObjectMapper can map classes composed of the following types:
+- Int
+- Bool
+- Double
+- Float
+- String
+- RawRepresentable (Enums)
+- Array\<AnyObject\>
+- Dictionary\<String, AnyObject\>
+- Object\<T: Mappable\>
+- Array\<T: Mappable\>
+- Array\<Array\<T: Mappable\>\>
+- Set\<T: Mappable\> 
+- Dictionary\<String, T: Mappable\>
+- Dictionary\<String, Array\<T: Mappable\>\>
+- Optionals of all the above
+- Implicitly Unwrapped Optionals of the above
+
+# Easy Mapping of Nested Objects
+ObjectMapper supports dot notation within keys for easy mapping of nested objects. Given the following JSON String:
+```json
+"distance" : {
+     "text" : "102 ft",
+     "value" : 31
+}
+```
+You can access the nested objects as follows:
+```swift
+func mapping(map: Map) {
+    distance <- map["distance.value"]
+}
+```
+Nested keys also support accessing values from an array. Given a JSON response with an array of distances, the value could be accessed as follows:
+```
+distance <- map["distances.0.value"]
+```
+If you have a key that contains `.`, you can individually disable the above feature as follows:
+```swift
+func mapping(map: Map) {
+    identifier <- map["app.identifier", nested: false]
+}
+```
+
+# Custom Transforms
+ObjectMapper also supports custom transforms that convert values during the mapping process. To use a transform, simply create a tuple with ```map["field_name"]``` and the transform of your choice on the right side of the ```<-``` operator:
+```swift
+birthday <- (map["birthday"], DateTransform())
+```
+The above transform will convert the JSON Int value to an NSDate when reading JSON and will convert the NSDate to an Int when converting objects to JSON.
+
+You can easily create your own custom transforms by adopting and implementing the methods in the ```TransformType``` protocol:
+```swift
+public protocol TransformType {
+    typealias Object
+    typealias JSON
+
+    func transformFromJSON(value: AnyObject?) -> Object?
+    func transformToJSON(value: Object?) -> JSON?
+}
+```
+
+### TransformOf
+In a lot of situations you can use the built-in transform class ```TransformOf``` to quickly perform a desired transformation. ```TransformOf``` is initialized with two types and two closures. The types define what the transform is converting to and from and the closures perform the actual transformation. 
+
+For example, if you want to transform a JSON String value to an Int you could use ```TransformOf``` as follows:
+```swift
+let transform = TransformOf<Int, String>(fromJSON: { (value: String?) -> Int? in 
+    // transform value from String? to Int?
+    return Int(value!)
+}, toJSON: { (value: Int?) -> String? in
+    // transform value from Int? to String?
+    if let value = value {
+        return String(value)
+    }
+    return nil
+})
+
+id <- (map["id"], transform)
+```
+Here is a more condensed version of the above:
+```swift
+id <- (map["id"], TransformOf<Int, String>(fromJSON: { Int($0!) }, toJSON: { $0.map { String($0) } }))
+```
+
+# Subclasses
+
+Classes that implement the ```Mappable``` protocol can easily be subclassed. When subclassing mappable classes, follow the structure below:
+
+```swift
+class Base: Mappable {
+	var base: String?
+	
+	required init?(_ map: Map) {
+
+	}
+
+	func mapping(map: Map) {
+		base <- map["base"]
+	}
+}
+
+class Subclass: Base {
+	var sub: String?
+
+	required init?(_ map: Map) {
+		super.init(map)
+	}
+
+	override func mapping(map: Map) {
+		super.mapping(map)
+		
+		sub <- map["sub"]
+	}
+}
+```
+
+Make sure your subclass implemenation calls the right initializers and mapping functions to also apply the mappings from your superclass.
+
+# Generic Objects
+
+ObjectMapper can handle classes with generic types as long as the generic type also conforms to `Mappable`. See the following example:
+```swift
+class Result<T: Mappable>: Mappable {
+    var result: T?
+
+    required init?(_ map: Map){
+
+    }
+
+    func mapping(map: Map) {
+        result <- map["result"]
+    }
+}
+
+let result = Mapper<Result<User>>().map(JSON)
+```
+<!-- # Mapping Immutable Properties
+
+Note: This is an experimental feature. Not all ObjectMapper functionality is guaranteed to work for immutable mappings.
+
+If you have a class or struct whose properties are immutable (`let`) and want to map it using ObjectMapper, you can use the following approach.
+
+In the failable initializer, assign values to your properties using the `valueOrFail()` function on the `map` object. Once all properties are set, check `isValid` to determine if the mapping succeeded for all properties. If `isValid` returns false, return `nil` to indicate that initialization failed.
+
+```swift
+class Model: Mappable {
+    let name: String // Non-optional property
+
+    required init?(_ map: Map) {
+        name = map["name"].valueOrFail()
+
+        if !map.isValid {
+            return nil
+        }
+    }
+
+    func mapping(map: Map) {
+    }
+}
+
+if let model = Mapper<Model>().map(JSONString) {
+    // Now we have valid model.
+} else {
+    // Something wrong...
+}
+``` -->
+
+#ObjectMapper + Alamofire
+
+If you are using [Alamofire](https://github.com/Alamofire/Alamofire) for networking and you want to convert your responses to Swift objects, you can use [AlamofireObjectMapper](https://github.com/tristanhimmelman/AlamofireObjectMapper). It is a simple Alamofire extension that uses ObjectMapper to automatically map JSON response data to Swift objects.
+
+
+#ObjectMapper + Realm
+
+ObjectMapper and Realm can be used together. Simply follow the class structure below and you will be able to use ObjectMapper to generate your Realm models:
+
+```swift
+class Model: Object, Mappable {
+	dynamic var name = ""
+
+	required convenience init?(_ map: Map) {
+		self.init()
+	}
+
+	func mapping(map: Map) {
+		name <- map["name"]
+	}
+}
+```
+
+Note: Generating a JSON string of a Realm Object using ObjectMappers' `toJSON` function only works within a Realm write transaction. This is caused because ObjectMapper uses the `inout` flag in its mapping functions (`<-`) which are used both for serializing and deserializing. Realm detects the flag and forces the `toJSON` function to be called within a write block even though the objects are not being modified.
+
+# To Do
+- Improve error handling. Perhaps using `throws`
+- Class cluster documentation
+- Realm List Transform
+
+# Contributing
+
+Contributions are very welcome 👍😃. 
+
+Before submitting any pull request, please ensure you have run the included tests and they have passed. If you are including new functionality, please write test cases for it as well.
+
+# Installation
+ObjectMapper can be added to your project using [CocoaPods 0.36 or later](http://blog.cocoapods.org/Pod-Authors-Guide-to-CocoaPods-Frameworks/) by adding the following line to your `Podfile`:
+
+```ruby
+pod 'ObjectMapper', '~> 1.1'
+```
+
+If you're using [Carthage](https://github.com/Carthage/Carthage) you can add a dependency on ObjectMapper by adding it to your `Cartfile`:
+```
+github "Hearst-DD/ObjectMapper" ~> 1.1
+```
+
+Otherwise, ObjectMapper can be added as a submodule:
+
+1. Add ObjectMapper as a [submodule](http://git-scm.com/docs/git-submodule) by opening the terminal, `cd`-ing into your top-level project directory, and entering the command `git submodule add https://github.com/Hearst-DD/ObjectMapper.git`
+2. Open the `ObjectMapper` folder, and drag `ObjectMapper.xcodeproj` into the file navigator of your app project.
+3. In Xcode, navigate to the target configuration window by clicking on the blue project icon, and selecting the application target under the "Targets" heading in the sidebar.
+4. Ensure that the deployment target of `ObjectMapper.framework` matches that of the application target.
+5. In the tab bar at the top of that window, open the "Build Phases" panel.
+6. Expand the "Target Dependencies" group, and add `ObjectMapper.framework`.
+7. Click on the `+` button at the top left of the panel and select "New Copy Files Phase". Rename this new phase to "Copy Frameworks", set the "Destination" to "Frameworks", and add `ObjectMapper.framework`.

File diff suppressed because it is too large
+ 3379 - 0
Pods/Pods.xcodeproj/project.pbxproj


+ 60 - 0
Pods/Pods.xcodeproj/xcuserdata/zhangjidong.xcuserdatad/xcschemes/Alamofire.xcscheme

@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0700"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForAnalyzing = "YES"
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES">
+            <BuildableReference
+               BuildableIdentifier = 'primary'
+               BlueprintIdentifier = 'F7D9C64E987B302DC2683A42'
+               BlueprintName = 'Alamofire'
+               ReferencedContainer = 'container:Pods.xcodeproj'
+               BuildableName = 'Alamofire.framework'>
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      buildConfiguration = "Debug">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </TestAction>
+   <LaunchAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      buildConfiguration = "Debug"
+      allowLocationSimulation = "YES">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES"
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>

+ 60 - 0
Pods/Pods.xcodeproj/xcuserdata/zhangjidong.xcuserdatad/xcschemes/AlamofireImage.xcscheme

@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0700"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForAnalyzing = "YES"
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES">
+            <BuildableReference
+               BuildableIdentifier = 'primary'
+               BlueprintIdentifier = 'C6F25320D51B1625516646F4'
+               BlueprintName = 'AlamofireImage'
+               ReferencedContainer = 'container:Pods.xcodeproj'
+               BuildableName = 'AlamofireImage.framework'>
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      buildConfiguration = "Debug">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </TestAction>
+   <LaunchAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      buildConfiguration = "Debug"
+      allowLocationSimulation = "YES">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES"
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>

+ 60 - 0
Pods/Pods.xcodeproj/xcuserdata/zhangjidong.xcuserdatad/xcschemes/AlamofireObjectMapper.xcscheme

@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0700"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForAnalyzing = "YES"
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES">
+            <BuildableReference
+               BuildableIdentifier = 'primary'
+               BlueprintIdentifier = '4CD2DA5584E697E8F81B1157'
+               BlueprintName = 'AlamofireObjectMapper'
+               ReferencedContainer = 'container:Pods.xcodeproj'
+               BuildableName = 'AlamofireObjectMapper.framework'>
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      buildConfiguration = "Debug">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </TestAction>
+   <LaunchAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      buildConfiguration = "Debug"
+      allowLocationSimulation = "YES">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES"
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>

+ 60 - 0
Pods/Pods.xcodeproj/xcuserdata/zhangjidong.xcuserdatad/xcschemes/ObjectMapper.xcscheme

@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0700"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForAnalyzing = "YES"
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES">
+            <BuildableReference
+               BuildableIdentifier = 'primary'
+               BlueprintIdentifier = 'A9EE48CF9339F8D462722C81'
+               BlueprintName = 'ObjectMapper'
+               ReferencedContainer = 'container:Pods.xcodeproj'
+               BuildableName = 'ObjectMapper.framework'>
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      buildConfiguration = "Debug">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </TestAction>
+   <LaunchAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      buildConfiguration = "Debug"
+      allowLocationSimulation = "YES">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES"
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>

+ 60 - 0
Pods/Pods.xcodeproj/xcuserdata/zhangjidong.xcuserdatad/xcschemes/Pods-BingHaoBang.xcscheme

@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0700"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForAnalyzing = "YES"
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES">
+            <BuildableReference
+               BuildableIdentifier = 'primary'
+               BlueprintIdentifier = '56D154C15296C7800B3A5E1E'
+               BlueprintName = 'Pods-BingHaoBang'
+               ReferencedContainer = 'container:Pods.xcodeproj'
+               BuildableName = 'Pods_BingHaoBang.framework'>
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      buildConfiguration = "Debug">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </TestAction>
+   <LaunchAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      buildConfiguration = "Debug"
+      allowLocationSimulation = "YES">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES"
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>

+ 62 - 0
Pods/Pods.xcodeproj/xcuserdata/zhangjidong.xcuserdatad/xcschemes/xcschememanagement.plist

@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>SchemeUserState</key>
+	<dict>
+		<key>Alamofire.xcscheme</key>
+		<dict>
+			<key>isShown</key>
+			<false/>
+		</dict>
+		<key>AlamofireImage.xcscheme</key>
+		<dict>
+			<key>isShown</key>
+			<false/>
+		</dict>
+		<key>AlamofireObjectMapper.xcscheme</key>
+		<dict>
+			<key>isShown</key>
+			<false/>
+		</dict>
+		<key>ObjectMapper.xcscheme</key>
+		<dict>
+			<key>isShown</key>
+			<false/>
+		</dict>
+		<key>Pods-BingHaoBang.xcscheme</key>
+		<dict>
+			<key>isShown</key>
+			<false/>
+		</dict>
+	</dict>
+	<key>SuppressBuildableAutocreation</key>
+	<dict>
+		<key>05094CC4A047119F7ADC14EE74C4881C</key>
+		<dict>
+			<key>primary</key>
+			<true/>
+		</dict>
+		<key>79C040AFDDCE1BCBF6D8B5EB0B85887F</key>
+		<dict>
+			<key>primary</key>
+			<true/>
+		</dict>
+		<key>947C7DF9A9DF94F9C10BF46F294B8624</key>
+		<dict>
+			<key>primary</key>
+			<true/>
+		</dict>
+		<key>C5CBCAA97E951CC882334464FBDF983D</key>
+		<dict>
+			<key>primary</key>
+			<true/>
+		</dict>
+		<key>FBD082A0D35F7917EAB9DD9D3CCA9976</key>
+		<dict>
+			<key>primary</key>
+			<true/>
+		</dict>
+	</dict>
+</dict>
+</plist>

+ 5 - 0
Pods/Target Support Files/Alamofire/Alamofire-dummy.m

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

+ 4 - 0
Pods/Target Support Files/Alamofire/Alamofire-prefix.pch

@@ -0,0 +1,4 @@
+#ifdef __OBJC__
+#import <UIKit/UIKit.h>
+#endif
+

+ 6 - 0
Pods/Target Support Files/Alamofire/Alamofire-umbrella.h

@@ -0,0 +1,6 @@
+#import <UIKit/UIKit.h>
+
+
+FOUNDATION_EXPORT double AlamofireVersionNumber;
+FOUNDATION_EXPORT const unsigned char AlamofireVersionString[];
+

+ 6 - 0
Pods/Target Support Files/Alamofire/Alamofire.modulemap

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

+ 5 - 0
Pods/Target Support Files/Alamofire/Alamofire.xcconfig

@@ -0,0 +1,5 @@
+GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
+HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/Alamofire" "${PODS_ROOT}/Headers/Public"
+OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
+PODS_ROOT = ${SRCROOT}
+SKIP_INSTALL = YES

+ 26 - 0
Pods/Target Support Files/Alamofire/Info.plist

@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+  <key>CFBundleDevelopmentRegion</key>
+  <string>en</string>
+  <key>CFBundleExecutable</key>
+  <string>${EXECUTABLE_NAME}</string>
+  <key>CFBundleIdentifier</key>
+  <string>org.cocoapods.${PRODUCT_NAME:rfc1034identifier}</string>
+  <key>CFBundleInfoDictionaryVersion</key>
+  <string>6.0</string>
+  <key>CFBundleName</key>
+  <string>${PRODUCT_NAME}</string>
+  <key>CFBundlePackageType</key>
+  <string>FMWK</string>
+  <key>CFBundleShortVersionString</key>
+  <string>3.2.1</string>
+  <key>CFBundleSignature</key>
+  <string>????</string>
+  <key>CFBundleVersion</key>
+  <string>${CURRENT_PROJECT_VERSION}</string>
+  <key>NSPrincipalClass</key>
+  <string></string>
+</dict>
+</plist>

+ 5 - 0
Pods/Target Support Files/AlamofireImage/AlamofireImage-dummy.m

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

+ 0 - 0
Pods/Target Support Files/AlamofireImage/AlamofireImage-prefix.pch


Some files were not shown because too many files changed in this diff