浏览代码

Merge branch 'master' into code_cleaning

* master: (61 commits)
  Update Travis config for Xcode 10.
  Add test for object posting notification
  update README.md, the old "Foundation URL Loading System" link is 404
  Change test name to correct one
  Change default teardown methods to tests
  Update tests to use new API
  Update PR feedback, add more tests
  Add test
  remove temporary method that could be doing nothing
  Update HTTPBin certificates.
  Chinese CONTRIBUTING.md translate
  Delete CONTRIBUTING_CH.md
  Chinese Contributing.md translate
  rollback method 'AFPostReachabilityStatusChange'
  Use AFNetworkReachabilityManager to compare  consistency of notification posts and gets, instead of SCNetworkReachabilityRef. And test case reference.
  Remove test that is nilling session manually as it's not possible anymore to not have valid session (correctly)
  Add tests for  verifing reachability manager consistence  for notification posting and getting
  Specify Xcode 9.4 in Travis file.
  Update AFImageDownloader.m
  Add an ability that notification-observer know which reachability its belong
  ...
svoit 6 年之前
父节点
当前提交
d6db8307d9
共有 62 个文件被更改,包括 1097 次插入217 次删除
  1. 16 6
      .travis.yml
  2. 3 3
      AFNetworking.podspec
  3. 35 9
      AFNetworking.xcodeproj/project.pbxproj
  4. 3 5
      AFNetworking.xcodeproj/xcshareddata/xcschemes/AFNetworking iOS.xcscheme
  5. 3 5
      AFNetworking.xcodeproj/xcshareddata/xcschemes/AFNetworking macOS.xcscheme
  6. 1 3
      AFNetworking.xcodeproj/xcshareddata/xcschemes/AFNetworking tvOS.xcscheme
  7. 1 3
      AFNetworking.xcodeproj/xcshareddata/xcschemes/AFNetworking watchOS.xcscheme
  8. 43 0
      AFNetworking/AFCompatibilityMacros.h
  9. 130 4
      AFNetworking/AFHTTPSessionManager.h
  10. 95 20
      AFNetworking/AFHTTPSessionManager.m
  11. 9 6
      AFNetworking/AFNetworkReachabilityManager.m
  12. 5 0
      AFNetworking/AFURLResponseSerialization.h
  13. 4 2
      AFNetworking/AFURLResponseSerialization.m
  14. 24 2
      AFNetworking/AFURLSessionManager.h
  15. 96 17
      AFNetworking/AFURLSessionManager.m
  16. 22 0
      CHANGELOG.md
  17. 97 0
      CONTRIBUTING_CH.md
  18. 18 1
      Example/AFNetworking Example.xcodeproj/project.pbxproj
  19. 1 3
      Example/AFNetworking Example.xcodeproj/xcshareddata/xcschemes/iOS Example.xcscheme
  20. 1 3
      Example/AFNetworking Example.xcodeproj/xcshareddata/xcschemes/iOS Today Extension Example.xcscheme
  21. 1 3
      Example/AFNetworking Example.xcodeproj/xcshareddata/xcschemes/macOS Example.xcscheme
  22. 1 3
      Example/AFNetworking Example.xcodeproj/xcshareddata/xcschemes/tvOS Example.xcscheme
  23. 1 3
      Example/AFNetworking Example.xcodeproj/xcshareddata/xcschemes/watchOS Example.xcscheme
  24. 62 32
      Example/Assets.xcassets/AppIcon.appiconset/Contents.json
  25. 4 0
      Example/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Content.imageset/Contents.json
  26. 4 0
      Example/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Content.imageset/Contents.json
  27. 4 0
      Example/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json
  28. 4 0
      Example/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Content.imageset/Contents.json
  29. 4 0
      Example/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Content.imageset/Contents.json
  30. 4 0
      Example/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json
  31. 7 1
      Example/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json
  32. 16 0
      Example/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Contents.json
  33. 4 0
      Example/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json
  34. 7 0
      Example/tvOS Example/Assets.xcassets/LaunchImage.launchimage/Contents.json
  35. 1 0
      Framework/AFNetworking.h
  36. 1 1
      Framework/Info.plist
  37. 1 1
      README.md
  38. 二进制
      Tests/Resources/HTTPBin.org/HTTPBinOrgServerTrustChain/httpbin_0.cer
  39. 二进制
      Tests/Resources/HTTPBin.org/httpbinorg_04112018.cer
  40. 二进制
      Tests/Resources/HTTPBin.org/httpbinorg_10102018.cer
  41. 4 4
      Tests/Tests/AFCompoundResponseSerializerTests.m
  42. 255 40
      Tests/Tests/AFHTTPSessionManagerTests.m
  43. 1 1
      Tests/Tests/AFImageDownloaderTests.m
  44. 2 1
      Tests/Tests/AFJSONSerializationTests.m
  45. 7 1
      Tests/Tests/AFNetworkActivityManagerTests.m
  46. 13 0
      Tests/Tests/AFNetworkReachabilityManagerTests.m
  47. 1 1
      Tests/Tests/AFSecurityPolicyTests.m
  48. 1 1
      Tests/Tests/AFUIActivityIndicatorViewTests.m
  49. 1 1
      Tests/Tests/AFUIRefreshControlTests.m
  50. 40 15
      Tests/Tests/AFURLSessionManagerTests.m
  51. 2 2
      UIKit+AFNetworking/AFAutoPurgingImageCache.m
  52. 16 8
      UIKit+AFNetworking/AFImageDownloader.m
  53. 1 1
      UIKit+AFNetworking/UIImage+AFNetworking.h
  54. 1 1
      UIKit+AFNetworking/UIWebView+AFNetworking.m
  55. 3 3
      fastlane/.env.default
  56. 3 0
      fastlane/.env.ios11_xcode9
  57. 3 0
      fastlane/.env.ios11_xcode91
  58. 3 0
      fastlane/.env.ios11_xcode92
  59. 1 1
      fastlane/.env.ios11_xcode93
  60. 3 0
      fastlane/.env.ios11_xcode94
  61. 3 0
      fastlane/.env.ios12_xcode10
  62. 0 0
      fastlane/.env.tvos12_xcode10

+ 16 - 6
.travis.yml

@@ -1,5 +1,5 @@
 language: objective-c
-osx_image: xcode7.1
+osx_image: xcode10
 sudo: false
 env:
   global:
@@ -9,14 +9,24 @@ env:
   - FASTLANE_LANE=ci_commit
 matrix:
   include:
-    - osx_image: xcode9.2
+    - osx_image: xcode10
       env: FASTLANE_LANE=code_coverage FASTLANE_ENV=default
+    - osx_image: xcode10
+      env: FASTLANE_ENV=ios12_xcode10
+    - osx_image: xcode10
+      env: FASTLANE_ENV=tvos12_xcode10
+    - osx_image: xcode10
+      env: FASTLANE_ENV=osx
+    - osx_image: xcode9.4
+      env: FASTLANE_ENV=ios11_xcode94
+    - osx_image: xcode9.3
+      env: FASTLANE_ENV=ios11_xcode93
     - osx_image: xcode9.2
+      env: FASTLANE_ENV=ios11_xcode92
+    - osx_image: xcode9.1
+      env: FASTLANE_ENV=ios11_xcode91
+    - osx_image: xcode9
       env: FASTLANE_ENV=ios11_xcode9
-    - osx_image: xcode9.2
-      env: FASTLANE_ENV=tvos11_xcode9
-    - osx_image: xcode9.2
-      env: FASTLANE_ENV=osx
     - osx_image: xcode8.3
       env: FASTLANE_ENV=ios10_xcode8
     - osx_image: xcode7.3

+ 3 - 3
AFNetworking.podspec

@@ -1,6 +1,6 @@
 Pod::Spec.new do |s|
   s.name     = 'AFNetworking'
-  s.version  = '3.2.0'
+  s.version  = '3.2.1'
   s.license  = 'MIT'
   s.summary  = 'A delightful iOS and OS X networking framework.'
   s.homepage = 'https://github.com/AFNetworking/AFNetworking'
@@ -64,8 +64,8 @@ EOS
     ss.tvos.dependency 'AFNetworking/Reachability'
     ss.dependency 'AFNetworking/Security'
 
-    ss.source_files = 'AFNetworking/AF{URL,HTTP}SessionManager.{h,m}'
-    ss.public_header_files = 'AFNetworking/AF{URL,HTTP}SessionManager.h'
+    ss.source_files = 'AFNetworking/AF{URL,HTTP}SessionManager.{h,m}', 'AFNetworking/AFCompatibilityMacros.h'
+    ss.public_header_files = 'AFNetworking/AF{URL,HTTP}SessionManager.h', 'AFNetworking/AFCompatibilityMacros.h'
   end
 
   s.subspec 'UIKit' do |ss|

+ 35 - 9
AFNetworking.xcodeproj/project.pbxproj

@@ -16,9 +16,13 @@
 		1F6F7DFB1F17051000C979D0 /* Let's Encrypt Authority X3.cer in Resources */ = {isa = PBXBuildFile; fileRef = 1F6F7DF51F1703A100C979D0 /* Let's Encrypt Authority X3.cer */; };
 		1F6F7DFD1F17051100C979D0 /* DST Root CA X3.cer in Resources */ = {isa = PBXBuildFile; fileRef = 1F6F7DF61F1703A100C979D0 /* DST Root CA X3.cer */; };
 		1F6F7DFE1F17051100C979D0 /* Let's Encrypt Authority X3.cer in Resources */ = {isa = PBXBuildFile; fileRef = 1F6F7DF51F1703A100C979D0 /* Let's Encrypt Authority X3.cer */; };
-		1FDA5AE42036373000BF0F94 /* httpbinorg_04112018.cer in Resources */ = {isa = PBXBuildFile; fileRef = 1FDA5AE32036372900BF0F94 /* httpbinorg_04112018.cer */; };
-		1FDA5AE52036373000BF0F94 /* httpbinorg_04112018.cer in Resources */ = {isa = PBXBuildFile; fileRef = 1FDA5AE32036372900BF0F94 /* httpbinorg_04112018.cer */; };
-		1FDA5AE62036373000BF0F94 /* httpbinorg_04112018.cer in Resources */ = {isa = PBXBuildFile; fileRef = 1FDA5AE32036372900BF0F94 /* httpbinorg_04112018.cer */; };
+		1F73A747211B6C0C00AFCFA5 /* httpbinorg_10102018.cer in Resources */ = {isa = PBXBuildFile; fileRef = 1F73A746211B6C0C00AFCFA5 /* httpbinorg_10102018.cer */; };
+		1F73A748211B6C0C00AFCFA5 /* httpbinorg_10102018.cer in Resources */ = {isa = PBXBuildFile; fileRef = 1F73A746211B6C0C00AFCFA5 /* httpbinorg_10102018.cer */; };
+		1F73A749211B6C0C00AFCFA5 /* httpbinorg_10102018.cer in Resources */ = {isa = PBXBuildFile; fileRef = 1F73A746211B6C0C00AFCFA5 /* httpbinorg_10102018.cer */; };
+		1F96D2A4203649560085FC3F /* AFCompatibilityMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F083A4920364648004D80C7 /* AFCompatibilityMacros.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		1F96D2A5203649570085FC3F /* AFCompatibilityMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F083A4920364648004D80C7 /* AFCompatibilityMacros.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		1F96D2A6203649570085FC3F /* AFCompatibilityMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F083A4920364648004D80C7 /* AFCompatibilityMacros.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		1F96D2A7203649580085FC3F /* AFCompatibilityMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F083A4920364648004D80C7 /* AFCompatibilityMacros.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		2960BAC31C1B2F1A00BA02F0 /* AFUIButtonTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 2960BAC21C1B2F1A00BA02F0 /* AFUIButtonTests.m */; };
 		297824A31BC2D69A0041C395 /* adn_0.cer in Resources */ = {isa = PBXBuildFile; fileRef = 297824A01BC2D69A0041C395 /* adn_0.cer */; };
 		297824A41BC2D69A0041C395 /* adn_0.cer in Resources */ = {isa = PBXBuildFile; fileRef = 297824A01BC2D69A0041C395 /* adn_0.cer */; };
@@ -229,9 +233,10 @@
 
 /* Begin PBXFileReference section */
 		1BF9F95F1C87832B00F1F35A /* AFImageResponseSerializerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFImageResponseSerializerTests.m; sourceTree = "<group>"; };
+		1F083A4920364648004D80C7 /* AFCompatibilityMacros.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AFCompatibilityMacros.h; sourceTree = "<group>"; };
 		1F6F7DF51F1703A100C979D0 /* Let's Encrypt Authority X3.cer */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Let's Encrypt Authority X3.cer"; sourceTree = "<group>"; };
 		1F6F7DF61F1703A100C979D0 /* DST Root CA X3.cer */ = {isa = PBXFileReference; lastKnownFileType = file; path = "DST Root CA X3.cer"; sourceTree = "<group>"; };
-		1FDA5AE32036372900BF0F94 /* httpbinorg_04112018.cer */ = {isa = PBXFileReference; lastKnownFileType = file; path = httpbinorg_04112018.cer; sourceTree = "<group>"; };
+		1F73A746211B6C0C00AFCFA5 /* httpbinorg_10102018.cer */ = {isa = PBXFileReference; lastKnownFileType = file; path = httpbinorg_10102018.cer; sourceTree = "<group>"; };
 		2960BAC21C1B2F1A00BA02F0 /* AFUIButtonTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFUIButtonTests.m; sourceTree = "<group>"; };
 		297824A01BC2D69A0041C395 /* adn_0.cer */ = {isa = PBXFileReference; lastKnownFileType = file; name = adn_0.cer; path = ADNNetServerTrustChain/adn_0.cer; sourceTree = "<group>"; };
 		297824A11BC2D69A0041C395 /* adn_1.cer */ = {isa = PBXFileReference; lastKnownFileType = file; name = adn_1.cer; path = ADNNetServerTrustChain/adn_1.cer; sourceTree = "<group>"; };
@@ -407,7 +412,7 @@
 				298D7CE21BC2CB7C00FD3B3E /* HTTPBinOrgServerTrustChain */,
 				1F6F7DF61F1703A100C979D0 /* DST Root CA X3.cer */,
 				1F6F7DF51F1703A100C979D0 /* Let's Encrypt Authority X3.cer */,
-				1FDA5AE32036372900BF0F94 /* httpbinorg_04112018.cer */,
+				1F73A746211B6C0C00AFCFA5 /* httpbinorg_10102018.cer */,
 			);
 			path = HTTPBin.org;
 			sourceTree = "<group>";
@@ -509,6 +514,7 @@
 		299522451BBF125A00859F49 /* AFNetworking */ = {
 			isa = PBXGroup;
 			children = (
+				1F083A4920364648004D80C7 /* AFCompatibilityMacros.h */,
 				299522461BBF125A00859F49 /* AFHTTPSessionManager.h */,
 				299522471BBF125A00859F49 /* AFHTTPSessionManager.m */,
 				299522491BBF125A00859F49 /* AFNetworkReachabilityManager.h */,
@@ -581,6 +587,7 @@
 				29D96E8D1BCC3D7D00F571A5 /* AFURLSessionManager.h in Headers */,
 				29D96E941BCC406B00F571A5 /* AFAutoPurgingImageCache.h in Headers */,
 				29D96E951BCC406B00F571A5 /* AFImageDownloader.h in Headers */,
+				1F96D2A7203649580085FC3F /* AFCompatibilityMacros.h in Headers */,
 				29D96E961BCC406B00F571A5 /* UIActivityIndicatorView+AFNetworking.h in Headers */,
 				29D96E971BCC406B00F571A5 /* UIButton+AFNetworking.h in Headers */,
 				29D96E981BCC406B00F571A5 /* UIImage+AFNetworking.h in Headers */,
@@ -605,6 +612,7 @@
 				2995225E1BBF125A00859F49 /* AFURLSessionManager.h in Headers */,
 				2995225C1BBF125A00859F49 /* AFURLResponseSerialization.h in Headers */,
 				299522A21BBF13C700859F49 /* UIActivityIndicatorView+AFNetworking.h in Headers */,
+				1F96D2A4203649560085FC3F /* AFCompatibilityMacros.h in Headers */,
 				2995223D1BBF104D00859F49 /* AFNetworking.h in Headers */,
 				299522B01BBF13C700859F49 /* UIWebView+AFNetworking.h in Headers */,
 				299522AC1BBF13C700859F49 /* UIProgressView+AFNetworking.h in Headers */,
@@ -620,6 +628,7 @@
 			files = (
 				29D96E7A1BCC3D6000F571A5 /* AFHTTPSessionManager.h in Headers */,
 				29D96E7C1BCC3D6000F571A5 /* AFSecurityPolicy.h in Headers */,
+				1F96D2A5203649570085FC3F /* AFCompatibilityMacros.h in Headers */,
 				29D96E7D1BCC3D6000F571A5 /* AFURLRequestSerialization.h in Headers */,
 				29D96E7E1BCC3D6000F571A5 /* AFURLResponseSerialization.h in Headers */,
 				29D96E7F1BCC3D6000F571A5 /* AFURLSessionManager.h in Headers */,
@@ -634,6 +643,7 @@
 				29D96E811BCC3D7200F571A5 /* AFHTTPSessionManager.h in Headers */,
 				29D96E821BCC3D7200F571A5 /* AFNetworkReachabilityManager.h in Headers */,
 				29D96E831BCC3D7200F571A5 /* AFSecurityPolicy.h in Headers */,
+				1F96D2A6203649570085FC3F /* AFCompatibilityMacros.h in Headers */,
 				29D96E841BCC3D7200F571A5 /* AFURLRequestSerialization.h in Headers */,
 				29D96E851BCC3D7200F571A5 /* AFURLResponseSerialization.h in Headers */,
 				29D96E861BCC3D7200F571A5 /* AFURLSessionManager.h in Headers */,
@@ -776,7 +786,7 @@
 		299522301BBF104D00859F49 /* Project object */ = {
 			isa = PBXProject;
 			attributes = {
-				LastUpgradeCheck = 0910;
+				LastUpgradeCheck = 0930;
 				ORGANIZATIONNAME = AFNetworking;
 				TargetAttributes = {
 					2987B0A41BC408A200179A4C = {
@@ -850,11 +860,11 @@
 				2987B0D51BC40AE900179A4C /* adn_2.cer in Resources */,
 				5F4323D71BF63CB0003B8749 /* GoogleComServerTrustChainPath1 in Resources */,
 				1F6F7DFE1F17051100C979D0 /* Let's Encrypt Authority X3.cer in Resources */,
-				1FDA5AE62036373000BF0F94 /* httpbinorg_04112018.cer in Resources */,
 				5F4323DB1BF63CBA003B8749 /* GoogleComServerTrustChainPath2 in Resources */,
 				5F4323BD1BF63741003B8749 /* Equifax_Secure_Certificate_Authority_Root.cer in Resources */,
 				5F4323DF1BF63CCC003B8749 /* GeoTrust_Global_CA_Root.cer in Resources */,
 				5F4323C01BF63741003B8749 /* GeoTrust_Global_CA-cross.cer in Resources */,
+				1F73A749211B6C0C00AFCFA5 /* httpbinorg_10102018.cer in Resources */,
 				1F6F7DFD1F17051100C979D0 /* DST Root CA X3.cer in Resources */,
 				5F4323CF1BF63741003B8749 /* GoogleInternetAuthorityG2.cer in Resources */,
 				5F4323C31BF63741003B8749 /* google.com.cer in Resources */,
@@ -876,11 +886,11 @@
 				298D7CBE1BC2CA9D00FD3B3E /* AltName.cer in Resources */,
 				5F4323D51BF63CB0003B8749 /* GoogleComServerTrustChainPath1 in Resources */,
 				1F6F7DF81F17051000C979D0 /* Let's Encrypt Authority X3.cer in Resources */,
-				1FDA5AE42036373000BF0F94 /* httpbinorg_04112018.cer in Resources */,
 				5F4323D91BF63CBA003B8749 /* GoogleComServerTrustChainPath2 in Resources */,
 				5F4323BB1BF63741003B8749 /* Equifax_Secure_Certificate_Authority_Root.cer in Resources */,
 				5F4323DD1BF63CCC003B8749 /* GeoTrust_Global_CA_Root.cer in Resources */,
 				5F4323BE1BF63741003B8749 /* GeoTrust_Global_CA-cross.cer in Resources */,
+				1F73A747211B6C0C00AFCFA5 /* httpbinorg_10102018.cer in Resources */,
 				1F6F7DF71F17051000C979D0 /* DST Root CA X3.cer in Resources */,
 				5F4323CD1BF63741003B8749 /* GoogleInternetAuthorityG2.cer in Resources */,
 				5F4323C11BF63741003B8749 /* google.com.cer in Resources */,
@@ -902,11 +912,11 @@
 				298D7CBB1BC2CA9C00FD3B3E /* AltName.cer in Resources */,
 				5F4323D61BF63CB0003B8749 /* GoogleComServerTrustChainPath1 in Resources */,
 				1F6F7DFB1F17051000C979D0 /* Let's Encrypt Authority X3.cer in Resources */,
-				1FDA5AE52036373000BF0F94 /* httpbinorg_04112018.cer in Resources */,
 				5F4323DA1BF63CBA003B8749 /* GoogleComServerTrustChainPath2 in Resources */,
 				5F4323BC1BF63741003B8749 /* Equifax_Secure_Certificate_Authority_Root.cer in Resources */,
 				5F4323CE1BF63741003B8749 /* GoogleInternetAuthorityG2.cer in Resources */,
 				5F4323DE1BF63CCC003B8749 /* GeoTrust_Global_CA_Root.cer in Resources */,
+				1F73A748211B6C0C00AFCFA5 /* httpbinorg_10102018.cer in Resources */,
 				1F6F7DFA1F17051000C979D0 /* DST Root CA X3.cer in Resources */,
 				5F4323BF1BF63741003B8749 /* GeoTrust_Global_CA-cross.cer in Resources */,
 				5F4323C21BF63741003B8749 /* google.com.cer in Resources */,
@@ -1102,6 +1112,7 @@
 			buildSettings = {
 				APPLICATION_EXTENSION_API_ONLY = YES;
 				BITCODE_GENERATION_MODE = marker;
+				CLANG_ENABLE_OBJC_WEAK = YES;
 				"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
 				DEFINES_MODULE = YES;
 				DYLIB_COMPATIBILITY_VERSION = 1;
@@ -1126,6 +1137,7 @@
 			buildSettings = {
 				APPLICATION_EXTENSION_API_ONLY = YES;
 				BITCODE_GENERATION_MODE = bitcode;
+				CLANG_ENABLE_OBJC_WEAK = YES;
 				"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
 				DEFINES_MODULE = YES;
 				DYLIB_COMPATIBILITY_VERSION = 1;
@@ -1148,6 +1160,7 @@
 		2987B0B81BC408A200179A4C /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
+				CLANG_ENABLE_OBJC_WEAK = YES;
 				CODE_SIGN_IDENTITY = "";
 				DEVELOPMENT_TEAM = "";
 				INFOPLIST_FILE = ./Tests/Info.plist;
@@ -1162,6 +1175,7 @@
 		2987B0B91BC408A200179A4C /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
+				CLANG_ENABLE_OBJC_WEAK = YES;
 				CODE_SIGN_IDENTITY = "";
 				DEVELOPMENT_TEAM = "";
 				INFOPLIST_FILE = ./Tests/Info.plist;
@@ -1176,6 +1190,7 @@
 		298D7C431BC2C79500FD3B3E /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
+				CLANG_ENABLE_OBJC_WEAK = YES;
 				CODE_SIGN_IDENTITY = "";
 				DEVELOPMENT_TEAM = "";
 				GCC_PREFIX_HEADER = "$(PROJECT_DIR)/Tests/Tests-Prefix.pch";
@@ -1190,6 +1205,7 @@
 		298D7C441BC2C79500FD3B3E /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
+				CLANG_ENABLE_OBJC_WEAK = YES;
 				CODE_SIGN_IDENTITY = "";
 				DEVELOPMENT_TEAM = "";
 				GCC_PREFIX_HEADER = "$(PROJECT_DIR)/Tests/Tests-Prefix.pch";
@@ -1204,6 +1220,7 @@
 		298D7C531BC2C7B200FD3B3E /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
+				CLANG_ENABLE_OBJC_WEAK = YES;
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
 				COMBINE_HIDPI_IMAGES = YES;
 				GCC_PREFIX_HEADER = "$(PROJECT_DIR)/Tests/Tests-Prefix.pch";
@@ -1219,6 +1236,7 @@
 		298D7C541BC2C7B200FD3B3E /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
+				CLANG_ENABLE_OBJC_WEAK = YES;
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
 				COMBINE_HIDPI_IMAGES = YES;
 				GCC_PREFIX_HEADER = "$(PROJECT_DIR)/Tests/Tests-Prefix.pch";
@@ -1237,6 +1255,7 @@
 				ALWAYS_SEARCH_USER_PATHS = NO;
 				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
 				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_CODE_COVERAGE = YES;
 				CLANG_ENABLE_MODULES = YES;
 				CLANG_ENABLE_OBJC_ARC = YES;
 				CLANG_WARN_ASSIGN_ENUM = YES;
@@ -1317,6 +1336,7 @@
 				ALWAYS_SEARCH_USER_PATHS = NO;
 				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
 				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_CODE_COVERAGE = NO;
 				CLANG_ENABLE_MODULES = YES;
 				CLANG_ENABLE_OBJC_ARC = YES;
 				CLANG_WARN_ASSIGN_ENUM = YES;
@@ -1390,6 +1410,7 @@
 			buildSettings = {
 				APPLICATION_EXTENSION_API_ONLY = YES;
 				BITCODE_GENERATION_MODE = marker;
+				CLANG_ENABLE_OBJC_WEAK = YES;
 				CODE_SIGN_IDENTITY = "iPhone Developer";
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
 				DEFINES_MODULE = YES;
@@ -1412,6 +1433,7 @@
 			buildSettings = {
 				APPLICATION_EXTENSION_API_ONLY = YES;
 				BITCODE_GENERATION_MODE = bitcode;
+				CLANG_ENABLE_OBJC_WEAK = YES;
 				CODE_SIGN_IDENTITY = "iPhone Developer";
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
 				DEFINES_MODULE = YES;
@@ -1434,6 +1456,7 @@
 			buildSettings = {
 				APPLICATION_EXTENSION_API_ONLY = YES;
 				BITCODE_GENERATION_MODE = marker;
+				CLANG_ENABLE_OBJC_WEAK = YES;
 				"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
 				DEFINES_MODULE = YES;
 				DYLIB_COMPATIBILITY_VERSION = 1;
@@ -1457,6 +1480,7 @@
 			buildSettings = {
 				APPLICATION_EXTENSION_API_ONLY = YES;
 				BITCODE_GENERATION_MODE = bitcode;
+				CLANG_ENABLE_OBJC_WEAK = YES;
 				"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
 				DEFINES_MODULE = YES;
 				DYLIB_COMPATIBILITY_VERSION = 1;
@@ -1480,6 +1504,7 @@
 			buildSettings = {
 				APPLICATION_EXTENSION_API_ONLY = YES;
 				BITCODE_GENERATION_MODE = marker;
+				CLANG_ENABLE_OBJC_WEAK = YES;
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
 				COMBINE_HIDPI_IMAGES = YES;
 				DEFINES_MODULE = YES;
@@ -1506,6 +1531,7 @@
 			buildSettings = {
 				APPLICATION_EXTENSION_API_ONLY = YES;
 				BITCODE_GENERATION_MODE = bitcode;
+				CLANG_ENABLE_OBJC_WEAK = YES;
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
 				COMBINE_HIDPI_IMAGES = YES;
 				DEFINES_MODULE = YES;

+ 3 - 5
AFNetworking.xcodeproj/xcshareddata/xcschemes/AFNetworking iOS.xcscheme

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "0910"
+   LastUpgradeVersion = "0930"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
@@ -41,9 +41,8 @@
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
       enableAddressSanitizer = "YES"
-      language = ""
-      shouldUseLaunchSchemeArgsEnv = "NO"
-      codeCoverageEnabled = "YES">
+      codeCoverageEnabled = "YES"
+      shouldUseLaunchSchemeArgsEnv = "NO">
       <Testables>
          <TestableReference
             skipped = "NO">
@@ -89,7 +88,6 @@
       buildConfiguration = "Debug"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      language = ""
       launchStyle = "0"
       useCustomWorkingDirectory = "NO"
       ignoresPersistentStateOnLaunch = "NO"

+ 3 - 5
AFNetworking.xcodeproj/xcshareddata/xcschemes/AFNetworking macOS.xcscheme

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "0910"
+   LastUpgradeVersion = "0930"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
@@ -26,9 +26,8 @@
       buildConfiguration = "Debug"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      language = ""
-      shouldUseLaunchSchemeArgsEnv = "NO"
-      codeCoverageEnabled = "YES">
+      codeCoverageEnabled = "YES"
+      shouldUseLaunchSchemeArgsEnv = "NO">
       <Testables>
          <TestableReference
             skipped = "NO">
@@ -69,7 +68,6 @@
       buildConfiguration = "Debug"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      language = ""
       launchStyle = "0"
       useCustomWorkingDirectory = "NO"
       ignoresPersistentStateOnLaunch = "NO"

+ 1 - 3
AFNetworking.xcodeproj/xcshareddata/xcschemes/AFNetworking tvOS.xcscheme

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "0910"
+   LastUpgradeVersion = "0930"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
@@ -27,7 +27,6 @@
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
       enableAddressSanitizer = "YES"
-      language = ""
       shouldUseLaunchSchemeArgsEnv = "NO">
       <Testables>
          <TestableReference
@@ -80,7 +79,6 @@
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
       enableThreadSanitizer = "YES"
-      language = ""
       launchStyle = "0"
       useCustomWorkingDirectory = "NO"
       ignoresPersistentStateOnLaunch = "NO"

+ 1 - 3
AFNetworking.xcodeproj/xcshareddata/xcschemes/AFNetworking watchOS.xcscheme

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "0910"
+   LastUpgradeVersion = "0930"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
@@ -26,7 +26,6 @@
       buildConfiguration = "Debug"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      language = ""
       shouldUseLaunchSchemeArgsEnv = "YES">
       <Testables>
       </Testables>
@@ -37,7 +36,6 @@
       buildConfiguration = "Debug"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      language = ""
       launchStyle = "0"
       useCustomWorkingDirectory = "NO"
       ignoresPersistentStateOnLaunch = "NO"

+ 43 - 0
AFNetworking/AFCompatibilityMacros.h

@@ -0,0 +1,43 @@
+// AFCompatibilityMacros.h
+// Copyright (c) 2011–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.
+
+#ifndef AFCompatibilityMacros_h
+#define AFCompatibilityMacros_h
+
+#ifdef API_UNAVAILABLE
+    #define AF_API_UNAVAILABLE(x) API_UNAVAILABLE(x)
+#else
+    #define AF_API_UNAVAILABLE(x)
+#endif // API_UNAVAILABLE
+
+#if __has_warning("-Wunguarded-availability-new")
+    #define AF_CAN_USE_AT_AVAILABLE 1
+#else
+    #define AF_CAN_USE_AT_AVAILABLE 0
+#endif
+
+#if ((__IPHONE_OS_VERSION_MAX_ALLOWED && __IPHONE_OS_VERSION_MAX_ALLOWED < 100000) || (__MAC_OS_VERSION_MAX_ALLOWED && __MAC_OS_VERSION_MAX_ALLOWED < 101200) ||(__WATCH_OS_MAX_VERSION_ALLOWED && __WATCH_OS_MAX_VERSION_ALLOWED < 30000) ||(__TV_OS_MAX_VERSION_ALLOWED && __TV_OS_MAX_VERSION_ALLOWED < 100000))
+    #define AF_CAN_INCLUDE_SESSION_TASK_METRICS 0
+#else
+    #define AF_CAN_INCLUDE_SESSION_TASK_METRICS 1
+#endif
+
+#endif /* AFCompatibilityMacros_h */

+ 130 - 4
AFNetworking/AFHTTPSessionManager.h

@@ -167,6 +167,25 @@ NS_ASSUME_NONNULL_BEGIN
  */
 - (nullable NSURLSessionDataTask *)GET:(NSString *)URLString
                             parameters:(nullable id)parameters
+                              progress:(nullable void (^)(NSProgress *downloadProgress))downloadProgress
+                               success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
+                               failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure DEPRECATED_ATTRIBUTE;
+
+/**
+ Creates and runs an `NSURLSessionDataTask` with a `GET` request.
+ 
+ @param URLString The URL string used to create the request URL.
+ @param parameters The parameters to be encoded according to the client request serializer.
+ @param headers The headers appended to the default headers for this request.
+ @param downloadProgress A block object to be executed when the download progress is updated. Note this block is called on the session queue, not the main queue.
+ @param success A block object to be executed when the task finishes successfully. This block has no return value and takes two arguments: the data task, and the response object created by the client response serializer.
+ @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred.
+ 
+ @see -dataTaskWithRequest:uploadProgress:downloadProgress:completionHandler:
+ */
+- (nullable NSURLSessionDataTask *)GET:(NSString *)URLString
+                            parameters:(nullable id)parameters
+                               headers:(nullable NSDictionary <NSString *, NSString *> *)headers
                               progress:(nullable void (^)(NSProgress *downloadProgress))downloadProgress
                                success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
                                failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;
@@ -184,7 +203,24 @@ NS_ASSUME_NONNULL_BEGIN
 - (nullable NSURLSessionDataTask *)HEAD:(NSString *)URLString
                     parameters:(nullable id)parameters
                        success:(nullable void (^)(NSURLSessionDataTask *task))success
-                       failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;
+                       failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure DEPRECATED_ATTRIBUTE;
+
+/**
+ Creates and runs an `NSURLSessionDataTask` with a `HEAD` request.
+ 
+ @param URLString The URL string used to create the request URL.
+ @param parameters The parameters to be encoded according to the client request serializer.
+ @param headers The headers appended to the default headers for this request.
+ @param success A block object to be executed when the task finishes successfully. This block has no return value and takes a single arguments: the data task.
+ @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred.
+ 
+ @see -dataTaskWithRequest:completionHandler:
+ */
+- (nullable NSURLSessionDataTask *)HEAD:(NSString *)URLString
+                             parameters:(nullable id)parameters
+                                headers:(nullable NSDictionary <NSString *, NSString *> *)headers
+                                success:(nullable void (^)(NSURLSessionDataTask *task))success
+                                failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;
 
 /**
  Creates and runs an `NSURLSessionDataTask` with a `POST` request.
@@ -214,6 +250,25 @@ NS_ASSUME_NONNULL_BEGIN
  */
 - (nullable NSURLSessionDataTask *)POST:(NSString *)URLString
                              parameters:(nullable id)parameters
+                               progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgress
+                                success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
+                                failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure DEPRECATED_ATTRIBUTE;
+
+/**
+ Creates and runs an `NSURLSessionDataTask` with a `POST` request.
+ 
+ @param URLString The URL string used to create the request URL.
+ @param parameters The parameters to be encoded according to the client request serializer.
+ @param headers The headers appended to the default headers for this request.
+ @param uploadProgress A block object to be executed when the upload progress is updated. Note this block is called on the session queue, not the main queue.
+ @param success A block object to be executed when the task finishes successfully. This block has no return value and takes two arguments: the data task, and the response object created by the client response serializer.
+ @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred.
+ 
+ @see -dataTaskWithRequest:uploadProgress:downloadProgress:completionHandler:
+ */
+- (nullable NSURLSessionDataTask *)POST:(NSString *)URLString
+                             parameters:(nullable id)parameters
+                                headers:(nullable NSDictionary <NSString *, NSString *> *)headers
                                progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgress
                                 success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
                                 failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;
@@ -249,6 +304,26 @@ NS_ASSUME_NONNULL_BEGIN
  */
 - (nullable NSURLSessionDataTask *)POST:(NSString *)URLString
                              parameters:(nullable id)parameters
+              constructingBodyWithBlock:(nullable void (^)(id <AFMultipartFormData> formData))block
+                               progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgress
+                                success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
+                                failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure DEPRECATED_ATTRIBUTE;
+/**
+ Creates and runs an `NSURLSessionDataTask` with a multipart `POST` request.
+ 
+ @param URLString The URL string used to create the request URL.
+ @param parameters The parameters to be encoded according to the client request serializer.
+ @param headers The headers appended to the default headers for this request.
+ @param block A block that takes a single argument and appends data to the HTTP body. The block argument is an object adopting the `AFMultipartFormData` protocol.
+ @param uploadProgress A block object to be executed when the upload progress is updated. Note this block is called on the session queue, not the main queue.
+ @param success A block object to be executed when the task finishes successfully. This block has no return value and takes two arguments: the data task, and the response object created by the client response serializer.
+ @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred.
+ 
+ @see -dataTaskWithRequest:uploadProgress:downloadProgress:completionHandler:
+ */
+- (nullable NSURLSessionDataTask *)POST:(NSString *)URLString
+                             parameters:(nullable id)parameters
+                                headers:(nullable NSDictionary <NSString *, NSString *> *)headers
               constructingBodyWithBlock:(nullable void (^)(id <AFMultipartFormData> formData))block
                                progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgress
                                 success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
@@ -267,7 +342,24 @@ NS_ASSUME_NONNULL_BEGIN
 - (nullable NSURLSessionDataTask *)PUT:(NSString *)URLString
                    parameters:(nullable id)parameters
                       success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
-                      failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;
+                      failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure DEPRECATED_ATTRIBUTE;
+
+/**
+ Creates and runs an `NSURLSessionDataTask` with a `PUT` request.
+ 
+ @param URLString The URL string used to create the request URL.
+ @param parameters The parameters to be encoded according to the client request serializer.
+ @param headers The headers appended to the default headers for this request.
+ @param success A block object to be executed when the task finishes successfully. This block has no return value and takes two arguments: the data task, and the response object created by the client response serializer.
+ @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred.
+ 
+ @see -dataTaskWithRequest:completionHandler:
+ */
+- (nullable NSURLSessionDataTask *)PUT:(NSString *)URLString
+                            parameters:(nullable id)parameters
+                               headers:(nullable NSDictionary <NSString *, NSString *> *)headers
+                               success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
+                               failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;
 
 /**
  Creates and runs an `NSURLSessionDataTask` with a `PATCH` request.
@@ -282,7 +374,24 @@ NS_ASSUME_NONNULL_BEGIN
 - (nullable NSURLSessionDataTask *)PATCH:(NSString *)URLString
                      parameters:(nullable id)parameters
                         success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
-                        failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;
+                        failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure DEPRECATED_ATTRIBUTE;
+
+/**
+ Creates and runs an `NSURLSessionDataTask` with a `PATCH` request.
+ 
+ @param URLString The URL string used to create the request URL.
+ @param parameters The parameters to be encoded according to the client request serializer.
+ @param headers The headers appended to the default headers for this request.
+ @param success A block object to be executed when the task finishes successfully. This block has no return value and takes two arguments: the data task, and the response object created by the client response serializer.
+ @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred.
+ 
+ @see -dataTaskWithRequest:completionHandler:
+ */
+- (nullable NSURLSessionDataTask *)PATCH:(NSString *)URLString
+                              parameters:(nullable id)parameters
+                                 headers:(nullable NSDictionary <NSString *, NSString *> *)headers
+                                 success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
+                                 failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;
 
 /**
  Creates and runs an `NSURLSessionDataTask` with a `DELETE` request.
@@ -297,7 +406,24 @@ NS_ASSUME_NONNULL_BEGIN
 - (nullable NSURLSessionDataTask *)DELETE:(NSString *)URLString
                       parameters:(nullable id)parameters
                          success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
-                         failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;
+                         failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure DEPRECATED_ATTRIBUTE;
+
+/**
+ Creates and runs an `NSURLSessionDataTask` with a `DELETE` request.
+ 
+ @param URLString The URL string used to create the request URL.
+ @param parameters The parameters to be encoded according to the client request serializer.
+ @param headers The headers appended to the default headers for this request.
+ @param success A block object to be executed when the task finishes successfully. This block has no return value and takes two arguments: the data task, and the response object created by the client response serializer.
+ @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred.
+ 
+ @see -dataTaskWithRequest:completionHandler:
+ */
+- (nullable NSURLSessionDataTask *)DELETE:(NSString *)URLString
+                               parameters:(nullable id)parameters
+                                  headers:(nullable NSDictionary <NSString *, NSString *> *)headers
+                                  success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
+                                  failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;
 
 @end
 

+ 95 - 20
AFNetworking/AFHTTPSessionManager.m

@@ -123,7 +123,7 @@
                       failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
 {
 
-    return [self GET:URLString parameters:parameters progress:nil success:success failure:failure];
+    return [self GET:URLString parameters:parameters headers:nil progress:nil success:success failure:failure];
 }
 
 - (NSURLSessionDataTask *)GET:(NSString *)URLString
@@ -133,16 +133,28 @@
                       failure:(void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure
 {
 
+    return [self GET:URLString parameters:parameters headers:nil progress:downloadProgress success:success failure:failure];
+}
+
+- (NSURLSessionDataTask *)GET:(NSString *)URLString
+                   parameters:(id)parameters
+                      headers:(nullable NSDictionary <NSString *, NSString *> *)headers
+                     progress:(void (^)(NSProgress * _Nonnull))downloadProgress
+                      success:(void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success
+                      failure:(void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure
+{
+    
     NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"GET"
                                                         URLString:URLString
                                                        parameters:parameters
+                                                          headers:headers
                                                    uploadProgress:nil
                                                  downloadProgress:downloadProgress
                                                           success:success
                                                           failure:failure];
-
+    
     [dataTask resume];
-
+    
     return dataTask;
 }
 
@@ -151,14 +163,23 @@
                        success:(void (^)(NSURLSessionDataTask *task))success
                        failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
 {
-    NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"HEAD" URLString:URLString parameters:parameters uploadProgress:nil downloadProgress:nil success:^(NSURLSessionDataTask *task, __unused id responseObject) {
+    return [self HEAD:URLString parameters:parameters headers:nil success:success failure:failure];
+}
+
+- (NSURLSessionDataTask *)HEAD:(NSString *)URLString
+                    parameters:(id)parameters
+                       headers:(NSDictionary<NSString *,NSString *> *)headers
+                       success:(void (^)(NSURLSessionDataTask * _Nonnull))success
+                       failure:(void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure
+{
+    NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"HEAD" URLString:URLString parameters:parameters headers:headers uploadProgress:nil downloadProgress:nil success:^(NSURLSessionDataTask *task, __unused id responseObject) {
         if (success) {
             success(task);
         }
     } failure:failure];
-
+    
     [dataTask resume];
-
+    
     return dataTask;
 }
 
@@ -167,7 +188,7 @@
                        success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
                        failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
 {
-    return [self POST:URLString parameters:parameters progress:nil success:success failure:failure];
+    return [self POST:URLString parameters:parameters headers:nil progress:nil success:success failure:failure];
 }
 
 - (NSURLSessionDataTask *)POST:(NSString *)URLString
@@ -176,10 +197,20 @@
                        success:(void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success
                        failure:(void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure
 {
-    NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"POST" URLString:URLString parameters:parameters uploadProgress:uploadProgress downloadProgress:nil success:success failure:failure];
+    return [self POST:URLString parameters:parameters headers:nil progress:uploadProgress success:success failure:failure];
+}
 
+- (nullable NSURLSessionDataTask *)POST:(NSString *)URLString
+                             parameters:(nullable id)parameters
+                                headers:(nullable NSDictionary <NSString *, NSString *> *)headers
+                               progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgress
+                                success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
+                                failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure
+{
+    NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"POST" URLString:URLString parameters:parameters headers:headers uploadProgress:uploadProgress downloadProgress:nil success:success failure:failure];
+    
     [dataTask resume];
-
+    
     return dataTask;
 }
 
@@ -189,7 +220,7 @@
                        success:(nullable void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success
                        failure:(nullable void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure
 {
-    return [self POST:URLString parameters:parameters constructingBodyWithBlock:block progress:nil success:success failure:failure];
+    return [self POST:URLString parameters:parameters headers:nil constructingBodyWithBlock:block progress:nil success:success failure:failure];
 }
 
 - (NSURLSessionDataTask *)POST:(NSString *)URLString
@@ -198,19 +229,32 @@
                       progress:(nullable void (^)(NSProgress * _Nonnull))uploadProgress
                        success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
                        failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
+{
+    return [self POST:URLString parameters:parameters headers:nil constructingBodyWithBlock:block progress:uploadProgress success:success failure:failure];
+}
+
+- (NSURLSessionDataTask *)POST:(NSString *)URLString
+                    parameters:(id)parameters
+                       headers:(NSDictionary<NSString *,NSString *> *)headers
+     constructingBodyWithBlock:(void (^)(id<AFMultipartFormData> _Nonnull))block
+                      progress:(void (^)(NSProgress * _Nonnull))uploadProgress
+                       success:(void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success failure:(void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure
 {
     NSError *serializationError = nil;
     NSMutableURLRequest *request = [self.requestSerializer multipartFormRequestWithMethod:@"POST" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters constructingBodyWithBlock:block error:&serializationError];
+    for (NSString *headerField in headers.keyEnumerator) {
+        [request addValue:headers[headerField] forHTTPHeaderField:headerField];
+    }
     if (serializationError) {
         if (failure) {
             dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{
                 failure(nil, serializationError);
             });
         }
-
+        
         return nil;
     }
-
+    
     __block NSURLSessionDataTask *task = [self uploadTaskWithStreamedRequest:request progress:uploadProgress completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) {
         if (error) {
             if (failure) {
@@ -222,9 +266,9 @@
             }
         }
     }];
-
+    
     [task resume];
-
+    
     return task;
 }
 
@@ -233,10 +277,19 @@
                       success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
                       failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
 {
-    NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"PUT" URLString:URLString parameters:parameters uploadProgress:nil downloadProgress:nil success:success failure:failure];
+    return [self PUT:URLString parameters:parameters headers:nil success:success failure:failure];
+}
 
+- (NSURLSessionDataTask *)PUT:(NSString *)URLString
+                   parameters:(id)parameters
+                      headers:(NSDictionary<NSString *,NSString *> *)headers
+                      success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
+                      failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
+{
+    NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"PUT" URLString:URLString parameters:parameters headers:headers uploadProgress:nil downloadProgress:nil success:success failure:failure];
+    
     [dataTask resume];
-
+    
     return dataTask;
 }
 
@@ -245,10 +298,19 @@
                         success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
                         failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
 {
-    NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"PATCH" URLString:URLString parameters:parameters uploadProgress:nil downloadProgress:nil success:success failure:failure];
+    return [self PATCH:URLString parameters:parameters headers:nil success:success failure:failure];
+}
 
+- (NSURLSessionDataTask *)PATCH:(NSString *)URLString
+                     parameters:(id)parameters
+                        headers:(NSDictionary<NSString *,NSString *> *)headers
+                        success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
+                        failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
+{
+    NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"PATCH" URLString:URLString parameters:parameters headers:headers uploadProgress:nil downloadProgress:nil success:success failure:failure];
+    
     [dataTask resume];
-
+    
     return dataTask;
 }
 
@@ -257,16 +319,26 @@
                          success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
                          failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
 {
-    NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"DELETE" URLString:URLString parameters:parameters uploadProgress:nil downloadProgress:nil success:success failure:failure];
+    return [self DELETE:URLString parameters:parameters headers:nil success:success failure:failure];
+}
 
+- (NSURLSessionDataTask *)DELETE:(NSString *)URLString
+                      parameters:(id)parameters
+                         headers:(NSDictionary<NSString *,NSString *> *)headers
+                         success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
+                         failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
+{
+    NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"DELETE" URLString:URLString parameters:parameters headers:headers uploadProgress:nil downloadProgress:nil success:success failure:failure];
+    
     [dataTask resume];
-
+    
     return dataTask;
 }
 
 - (NSURLSessionDataTask *)dataTaskWithHTTPMethod:(NSString *)method
                                        URLString:(NSString *)URLString
                                       parameters:(id)parameters
+                                         headers:(NSDictionary <NSString *, NSString *> *)headers
                                   uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgress
                                 downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgress
                                          success:(void (^)(NSURLSessionDataTask *, id))success
@@ -274,6 +346,9 @@
 {
     NSError *serializationError = nil;
     NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&serializationError];
+    for (NSString *headerField in headers.keyEnumerator) {
+        [request addValue:headers[headerField] forHTTPHeaderField:headerField];
+    }
     if (serializationError) {
         if (failure) {
             dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{

+ 9 - 6
AFNetworking/AFNetworkReachabilityManager.m

@@ -32,6 +32,7 @@ NSString * const AFNetworkingReachabilityDidChangeNotification = @"com.alamofire
 NSString * const AFNetworkingReachabilityNotificationStatusItem = @"AFNetworkingReachabilityNotificationStatusItem";
 
 typedef void (^AFNetworkReachabilityStatusBlock)(AFNetworkReachabilityStatus status);
+typedef AFNetworkReachabilityManager * (^AFNetworkReachabilityStatusCallback)(AFNetworkReachabilityStatus status);
 
 NSString * AFStringFromNetworkReachabilityStatus(AFNetworkReachabilityStatus status) {
     switch (status) {
@@ -78,20 +79,21 @@ static AFNetworkReachabilityStatus AFNetworkReachabilityStatusForFlags(SCNetwork
  * a queued notification (for an earlier status condition) is processed after
  * the later update, resulting in the listener being left in the wrong state.
  */
-static void AFPostReachabilityStatusChange(SCNetworkReachabilityFlags flags, AFNetworkReachabilityStatusBlock block) {
+static void AFPostReachabilityStatusChange(SCNetworkReachabilityFlags flags, AFNetworkReachabilityStatusCallback block) {
     AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusForFlags(flags);
     dispatch_async(dispatch_get_main_queue(), ^{
+        AFNetworkReachabilityManager *manager = nil;
         if (block) {
-            block(status);
+            manager = block(status);
         }
         NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
         NSDictionary *userInfo = @{ AFNetworkingReachabilityNotificationStatusItem: @(status) };
-        [notificationCenter postNotificationName:AFNetworkingReachabilityDidChangeNotification object:nil userInfo:userInfo];
+        [notificationCenter postNotificationName:AFNetworkingReachabilityDidChangeNotification object:manager userInfo:userInfo];
     });
 }
 
 static void AFNetworkReachabilityCallback(SCNetworkReachabilityRef __unused target, SCNetworkReachabilityFlags flags, void *info) {
-    AFPostReachabilityStatusChange(flags, (__bridge AFNetworkReachabilityStatusBlock)info);
+    AFPostReachabilityStatusChange(flags, (__bridge AFNetworkReachabilityStatusCallback)info);
 }
 
 
@@ -210,14 +212,15 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
     }
 
     __weak __typeof(self)weakSelf = self;
-    AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status) {
+    AFNetworkReachabilityStatusCallback callback = ^(AFNetworkReachabilityStatus status) {
         __strong __typeof(weakSelf)strongSelf = weakSelf;
 
         strongSelf.networkReachabilityStatus = status;
         if (strongSelf.networkReachabilityStatusBlock) {
             strongSelf.networkReachabilityStatusBlock(status);
         }
-
+        
+        return strongSelf;
     };
 
     SCNetworkReachabilityContext context = {0, (__bridge void *)callback, AFNetworkReachabilityRetainCallback, AFNetworkReachabilityReleaseCallback, NULL};

+ 5 - 0
AFNetworking/AFURLResponseSerialization.h

@@ -24,6 +24,11 @@
 
 NS_ASSUME_NONNULL_BEGIN
 
+/**
+ Recursively removes `NSNull` values from a JSON object.
+*/
+id AFJSONObjectByRemovingKeysWithNullValues(id JSONObject, NSJSONReadingOptions readingOptions);
+
 /**
  The `AFURLResponseSerialization` protocol is adopted by an object that decodes data into a more useful object representation, according to details in the server response. Response serializers may additionally perform validation on the incoming response and data.
 

+ 4 - 2
AFNetworking/AFURLResponseSerialization.m

@@ -60,11 +60,13 @@ static BOOL AFErrorOrUnderlyingErrorHasCodeInDomain(NSError *error, NSInteger co
     return NO;
 }
 
-static id AFJSONObjectByRemovingKeysWithNullValues(id JSONObject, NSJSONReadingOptions readingOptions) {
+id AFJSONObjectByRemovingKeysWithNullValues(id JSONObject, NSJSONReadingOptions readingOptions) {
     if ([JSONObject isKindOfClass:[NSArray class]]) {
         NSMutableArray *mutableArray = [NSMutableArray arrayWithCapacity:[(NSArray *)JSONObject count]];
         for (id value in (NSArray *)JSONObject) {
-            [mutableArray addObject:AFJSONObjectByRemovingKeysWithNullValues(value, readingOptions)];
+            if (![value isEqual:[NSNull null]]) {
+                [mutableArray addObject:AFJSONObjectByRemovingKeysWithNullValues(value, readingOptions)];
+            }
         }
 
         return (readingOptions & NSJSONReadingMutableContainers) ? mutableArray : [NSArray arrayWithArray:mutableArray];

+ 24 - 2
AFNetworking/AFURLSessionManager.h

@@ -25,6 +25,7 @@
 #import "AFURLResponseSerialization.h"
 #import "AFURLRequestSerialization.h"
 #import "AFSecurityPolicy.h"
+#import "AFCompatibilityMacros.h"
 #if !TARGET_OS_WATCH
 #import "AFNetworkReachabilityManager.h"
 #endif
@@ -195,7 +196,15 @@ NS_ASSUME_NONNULL_BEGIN
 
  @param cancelPendingTasks Whether or not to cancel pending tasks.
  */
-- (void)invalidateSessionCancelingTasks:(BOOL)cancelPendingTasks;
+- (void)invalidateSessionCancelingTasks:(BOOL)cancelPendingTasks DEPRECATED_ATTRIBUTE;
+
+/**
+ Invalidates the managed session, optionally canceling pending tasks and optionally resets given session.
+ 
+ @param cancelPendingTasks  Whether or not to cancel pending tasks.
+ @param resetSession        Whether or not to reset the session of the manager.
+ */
+- (void)invalidateSessionCancelingTasks:(BOOL)cancelPendingTasks resetSession:(BOOL)resetSession;
 
 ///-------------------------
 /// @name Running Data Tasks
@@ -377,6 +386,14 @@ NS_ASSUME_NONNULL_BEGIN
  */
 - (void)setTaskDidCompleteBlock:(nullable void (^)(NSURLSession *session, NSURLSessionTask *task, NSError * _Nullable error))block;
 
+/**
+ Sets a block to be executed when metrics are finalized related to a specific task, as handled by the `NSURLSessionTaskDelegate` method `URLSession:task:didFinishCollectingMetrics:`.
+
+ @param block A block object to be executed when a session task is completed. The block has no return value, and takes three arguments: the session, the task, and any metrics that were collected in the process of executing the task.
+ */
+#if AF_CAN_INCLUDE_SESSION_TASK_METRICS
+- (void)setTaskDidFinishCollectingMetricsBlock:(nullable void (^)(NSURLSession *session, NSURLSessionTask *task, NSURLSessionTaskMetrics * _Nullable metrics))block;
+#endif
 ///-------------------------------------------
 /// @name Setting Data Task Delegate Callbacks
 ///-------------------------------------------
@@ -414,7 +431,7 @@ NS_ASSUME_NONNULL_BEGIN
 
  @param block A block object to be executed once all messages enqueued for a session have been delivered. The block has no return value and takes a single argument: the session.
  */
-- (void)setDidFinishEventsForBackgroundURLSessionBlock:(nullable void (^)(NSURLSession *session))block;
+- (void)setDidFinishEventsForBackgroundURLSessionBlock:(nullable void (^)(NSURLSession *session))block AF_API_UNAVAILABLE(macos);
 
 ///-----------------------------------------------
 /// @name Setting Download Task Delegate Callbacks
@@ -497,4 +514,9 @@ FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteAssetPathKey;
  */
 FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteErrorKey;
 
+/**
+ The session task metrics taken from the download task. Included in the userInfo dictionary of the `AFNetworkingTaskDidCompleteSessionTaskMetrics`
+ */
+FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteSessionTaskMetrics;
+
 NS_ASSUME_NONNULL_END

+ 96 - 17
AFNetworking/AFURLSessionManager.m

@@ -38,14 +38,16 @@ static dispatch_queue_t url_session_manager_creation_queue() {
     return af_url_session_manager_creation_queue;
 }
 
-static void url_session_manager_create_task_safely(dispatch_block_t block) {
-    if (NSFoundationVersionNumber < NSFoundationVersionNumber_With_Fixed_5871104061079552_bug) {
-        // Fix of bug
-        // Open Radar:http://openradar.appspot.com/radar?id=5871104061079552 (status: Fixed in iOS8)
-        // Issue about:https://github.com/AFNetworking/AFNetworking/issues/2093
-        dispatch_sync(url_session_manager_creation_queue(), block);
-    } else {
-        block();
+static void url_session_manager_create_task_safely(dispatch_block_t _Nonnull block) {
+    if (block != NULL) {
+        if (NSFoundationVersionNumber < NSFoundationVersionNumber_With_Fixed_5871104061079552_bug) {
+            // Fix of bug
+            // Open Radar:http://openradar.appspot.com/radar?id=5871104061079552 (status: Fixed in iOS8)
+            // Issue about:https://github.com/AFNetworking/AFNetworking/issues/2093
+            dispatch_sync(url_session_manager_creation_queue(), block);
+        } else {
+            block();
+        }
     }
 }
 
@@ -80,6 +82,7 @@ NSString * const AFNetworkingTaskDidCompleteResponseSerializerKey = @"com.alamof
 NSString * const AFNetworkingTaskDidCompleteResponseDataKey = @"com.alamofire.networking.complete.finish.responsedata";
 NSString * const AFNetworkingTaskDidCompleteErrorKey = @"com.alamofire.networking.task.complete.error";
 NSString * const AFNetworkingTaskDidCompleteAssetPathKey = @"com.alamofire.networking.task.complete.assetpath";
+NSString * const AFNetworkingTaskDidCompleteSessionTaskMetrics = @"com.alamofire.networking.complete.sessiontaskmetrics";
 
 static NSString * const AFURLSessionManagerLockName = @"com.alamofire.networking.session.manager.lock";
 
@@ -95,6 +98,9 @@ typedef void (^AFURLSessionDidFinishEventsForBackgroundURLSessionBlock)(NSURLSes
 typedef NSInputStream * (^AFURLSessionTaskNeedNewBodyStreamBlock)(NSURLSession *session, NSURLSessionTask *task);
 typedef void (^AFURLSessionTaskDidSendBodyDataBlock)(NSURLSession *session, NSURLSessionTask *task, int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend);
 typedef void (^AFURLSessionTaskDidCompleteBlock)(NSURLSession *session, NSURLSessionTask *task, NSError *error);
+#if AF_CAN_INCLUDE_SESSION_TASK_METRICS
+typedef void (^AFURLSessionTaskDidFinishCollectingMetricsBlock)(NSURLSession *session, NSURLSessionTask *task, NSURLSessionTaskMetrics * metrics);
+#endif
 
 typedef NSURLSessionResponseDisposition (^AFURLSessionDataTaskDidReceiveResponseBlock)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLResponse *response);
 typedef void (^AFURLSessionDataTaskDidBecomeDownloadTaskBlock)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLSessionDownloadTask *downloadTask);
@@ -118,6 +124,9 @@ typedef void (^AFURLSessionTaskCompletionHandler)(NSURLResponse *response, id re
 @property (nonatomic, strong) NSProgress *uploadProgress;
 @property (nonatomic, strong) NSProgress *downloadProgress;
 @property (nonatomic, copy) NSURL *downloadFileURL;
+#if AF_CAN_INCLUDE_SESSION_TASK_METRICS
+@property (nonatomic, strong) NSURLSessionTaskMetrics *sessionTaskMetrics;
+#endif
 @property (nonatomic, copy) AFURLSessionDownloadTaskDidFinishDownloadingBlock downloadTaskDidFinishDownloading;
 @property (nonatomic, copy) AFURLSessionTaskProgressBlock uploadProgressBlock;
 @property (nonatomic, copy) AFURLSessionTaskProgressBlock downloadProgressBlock;
@@ -148,7 +157,7 @@ typedef void (^AFURLSessionTaskCompletionHandler)(NSURLResponse *response, id re
         progress.pausingHandler = ^{
             [weakTask suspend];
         };
-#if __has_warning("-Wunguarded-availability-new")
+#if AF_CAN_USE_AT_AVAILABLE
         if (@available(iOS 9, macOS 10.11, *))
 #else
         if ([progress respondsToSelector:@selector(setResumingHandler:)])
@@ -208,6 +217,14 @@ didCompleteWithError:(NSError *)error
         self.mutableData = nil;
     }
 
+#if AF_CAN_USE_AT_AVAILABLE && AF_CAN_INCLUDE_SESSION_TASK_METRICS
+    if (@available(iOS 10, macOS 10.12, watchOS 3, tvOS 10, *)) {
+        if (self.sessionTaskMetrics) {
+            userInfo[AFNetworkingTaskDidCompleteSessionTaskMetrics] = self.sessionTaskMetrics;
+        }
+    }
+#endif
+
     if (self.downloadFileURL) {
         userInfo[AFNetworkingTaskDidCompleteAssetPathKey] = self.downloadFileURL;
     } else if (data) {
@@ -256,6 +273,14 @@ didCompleteWithError:(NSError *)error
     }
 }
 
+#if AF_CAN_INCLUDE_SESSION_TASK_METRICS
+- (void)URLSession:(NSURLSession *)session
+              task:(NSURLSessionTask *)task
+didFinishCollectingMetrics:(NSURLSessionTaskMetrics *)metrics {
+    self.sessionTaskMetrics = metrics;
+}
+#endif
+
 #pragma mark - NSURLSessionDataDelegate
 
 - (void)URLSession:(__unused NSURLSession *)session
@@ -380,7 +405,7 @@ static NSString * const AFNSURLSessionTaskDidSuspendNotification = @"com.alamofi
             8) Set the current class to the super class, and repeat steps 3-8
          */
         NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration ephemeralSessionConfiguration];
-        NSURLSession * session = [NSURLSession sessionWithConfiguration:configuration];
+        NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wnonnull"
         NSURLSessionDataTask *localDataTask = [session dataTaskWithURL:nil];
@@ -454,12 +479,15 @@ static NSString * const AFNSURLSessionTaskDidSuspendNotification = @"com.alamofi
 @property (readwrite, nonatomic, strong) NSLock *lock;
 @property (readwrite, nonatomic, copy) AFURLSessionDidBecomeInvalidBlock sessionDidBecomeInvalid;
 @property (readwrite, nonatomic, copy) AFURLSessionDidReceiveAuthenticationChallengeBlock sessionDidReceiveAuthenticationChallenge;
-@property (readwrite, nonatomic, copy) AFURLSessionDidFinishEventsForBackgroundURLSessionBlock didFinishEventsForBackgroundURLSession;
+@property (readwrite, nonatomic, copy) AFURLSessionDidFinishEventsForBackgroundURLSessionBlock didFinishEventsForBackgroundURLSession AF_API_UNAVAILABLE(macos);
 @property (readwrite, nonatomic, copy) AFURLSessionTaskWillPerformHTTPRedirectionBlock taskWillPerformHTTPRedirection;
 @property (readwrite, nonatomic, copy) AFURLSessionTaskDidReceiveAuthenticationChallengeBlock taskDidReceiveAuthenticationChallenge;
 @property (readwrite, nonatomic, copy) AFURLSessionTaskNeedNewBodyStreamBlock taskNeedNewBodyStream;
 @property (readwrite, nonatomic, copy) AFURLSessionTaskDidSendBodyDataBlock taskDidSendBodyData;
 @property (readwrite, nonatomic, copy) AFURLSessionTaskDidCompleteBlock taskDidComplete;
+#if AF_CAN_INCLUDE_SESSION_TASK_METRICS
+@property (readwrite, nonatomic, copy) AFURLSessionTaskDidFinishCollectingMetricsBlock taskDidFinishCollectingMetrics;
+#endif
 @property (readwrite, nonatomic, copy) AFURLSessionDataTaskDidReceiveResponseBlock dataTaskDidReceiveResponse;
 @property (readwrite, nonatomic, copy) AFURLSessionDataTaskDidBecomeDownloadTaskBlock dataTaskDidBecomeDownloadTask;
 @property (readwrite, nonatomic, copy) AFURLSessionDataTaskDidReceiveDataBlock dataTaskDidReceiveData;
@@ -490,8 +518,6 @@ static NSString * const AFNSURLSessionTaskDidSuspendNotification = @"com.alamofi
     self.operationQueue = [[NSOperationQueue alloc] init];
     self.operationQueue.maxConcurrentOperationCount = 1;
 
-    self.session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration delegate:self delegateQueue:self.operationQueue];
-
     self.responseSerializer = [AFJSONResponseSerializer serializer];
 
     self.securityPolicy = [AFSecurityPolicy defaultPolicy];
@@ -505,17 +531,20 @@ static NSString * const AFNSURLSessionTaskDidSuspendNotification = @"com.alamofi
     self.lock = [[NSLock alloc] init];
     self.lock.name = AFURLSessionManagerLockName;
 
+    __weak typeof(self) weakSelf = self;
     [self.session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {
+        
+        __strong typeof(weakSelf) strongSelf = weakSelf;
         for (NSURLSessionDataTask *task in dataTasks) {
-            [self addDelegateForDataTask:task uploadProgress:nil downloadProgress:nil completionHandler:nil];
+            [strongSelf addDelegateForDataTask:task uploadProgress:nil downloadProgress:nil completionHandler:nil];
         }
 
         for (NSURLSessionUploadTask *uploadTask in uploadTasks) {
-            [self addDelegateForUploadTask:uploadTask progress:nil completionHandler:nil];
+            [strongSelf addDelegateForUploadTask:uploadTask progress:nil completionHandler:nil];
         }
 
         for (NSURLSessionDownloadTask *downloadTask in downloadTasks) {
-            [self addDelegateForDownloadTask:downloadTask progress:nil destination:nil completionHandler:nil];
+            [strongSelf addDelegateForDownloadTask:downloadTask progress:nil destination:nil completionHandler:nil];
         }
     }];
 
@@ -528,6 +557,19 @@ static NSString * const AFNSURLSessionTaskDidSuspendNotification = @"com.alamofi
 
 #pragma mark -
 
+- (NSURLSession *)session {
+    
+    @synchronized (self) {
+        if (!_session) {
+            _session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration delegate:self delegateQueue:self.operationQueue];
+        }
+    }
+    return _session;
+}
+
+#pragma mark -
+
+
 - (NSString *)taskDescriptionForSessionTasks {
     return [NSString stringWithFormat:@"%p", self];
 }
@@ -684,11 +726,18 @@ static NSString * const AFNSURLSessionTaskDidSuspendNotification = @"com.alamofi
 #pragma mark -
 
 - (void)invalidateSessionCancelingTasks:(BOOL)cancelPendingTasks {
+    [self invalidateSessionCancelingTasks:cancelPendingTasks resetSession:NO];
+}
+
+- (void)invalidateSessionCancelingTasks:(BOOL)cancelPendingTasks resetSession:(BOOL)resetSession {
     if (cancelPendingTasks) {
         [self.session invalidateAndCancel];
     } else {
         [self.session finishTasksAndInvalidate];
     }
+    if (resetSession) {
+        self.session = nil;
+    }
 }
 
 #pragma mark -
@@ -841,9 +890,11 @@ static NSString * const AFNSURLSessionTaskDidSuspendNotification = @"com.alamofi
     self.sessionDidReceiveAuthenticationChallenge = block;
 }
 
+#if !TARGET_OS_OSX
 - (void)setDidFinishEventsForBackgroundURLSessionBlock:(void (^)(NSURLSession *session))block {
     self.didFinishEventsForBackgroundURLSession = block;
 }
+#endif
 
 #pragma mark -
 
@@ -867,6 +918,12 @@ static NSString * const AFNSURLSessionTaskDidSuspendNotification = @"com.alamofi
     self.taskDidComplete = block;
 }
 
+#if AF_CAN_INCLUDE_SESSION_TASK_METRICS
+- (void)setTaskDidFinishCollectingMetricsBlock:(void (^)(NSURLSession * _Nonnull, NSURLSessionTask * _Nonnull, NSURLSessionTaskMetrics * _Nullable))block {
+    self.taskDidFinishCollectingMetrics = block;
+}
+#endif
+
 #pragma mark -
 
 - (void)setDataTaskDidReceiveResponseBlock:(NSURLSessionResponseDisposition (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLResponse *response))block {
@@ -912,9 +969,12 @@ static NSString * const AFNSURLSessionTaskDidSuspendNotification = @"com.alamofi
         return self.dataTaskDidReceiveResponse != nil;
     } else if (selector == @selector(URLSession:dataTask:willCacheResponse:completionHandler:)) {
         return self.dataTaskWillCacheResponse != nil;
-    } else if (selector == @selector(URLSessionDidFinishEventsForBackgroundURLSession:)) {
+    }
+#if !TARGET_OS_OSX
+    else if (selector == @selector(URLSessionDidFinishEventsForBackgroundURLSession:)) {
         return self.didFinishEventsForBackgroundURLSession != nil;
     }
+#endif
 
     return [[self class] instancesRespondToSelector:selector];
 }
@@ -1070,6 +1130,23 @@ didCompleteWithError:(NSError *)error
     }
 }
 
+#if AF_CAN_INCLUDE_SESSION_TASK_METRICS
+- (void)URLSession:(NSURLSession *)session
+              task:(NSURLSessionTask *)task
+didFinishCollectingMetrics:(NSURLSessionTaskMetrics *)metrics
+{
+    AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:task];
+    // Metrics may fire after URLSession:task:didCompleteWithError: is called, delegate may be nil
+    if (delegate) {
+        [delegate URLSession:session task:task didFinishCollectingMetrics:metrics];
+    }
+
+    if (self.taskDidFinishCollectingMetrics) {
+        self.taskDidFinishCollectingMetrics(session, task, metrics);
+    }
+}
+#endif
+
 #pragma mark - NSURLSessionDataDelegate
 
 - (void)URLSession:(NSURLSession *)session
@@ -1132,6 +1209,7 @@ didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask
     }
 }
 
+#if !TARGET_OS_OSX
 - (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session {
     if (self.didFinishEventsForBackgroundURLSession) {
         dispatch_async(dispatch_get_main_queue(), ^{
@@ -1139,6 +1217,7 @@ didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask
         });
     }
 }
+#endif
 
 #pragma mark - NSURLSessionDownloadDelegate
 

+ 22 - 0
CHANGELOG.md

@@ -4,6 +4,28 @@ All notable changes to this project will be documented in this file.
 
 --- 
 
+## [3.2.1](https://github.com/AFNetworking/AFNetworking/releases/tag/3.2.1) (05/04/2018)
+Released on Friday, May 04, 2018. All issues associated with this milestone can be found using this [filter](https://github.com/AFNetworking/AFNetworking/issues?q=milestone%3A3.2.1+is%3Aclosed).
+
+#### Updated
+* Xcode 9.3 Support
+ * Implemented by Jeff Kelley in [#4199](https://github.com/AFNetworking/AFNetworking/pull/4199).
+* Update HTTPBin certificates for April 2018.
+ * Implemented by Jeff Kelley in [#4198](https://github.com/AFNetworking/AFNetworking/pull/4198).
+
+#### Additional Changes
+* Remove conflicting nullable specifier on init
+ * Implemented by Nick Brook and Jeff Kelley in [#4182](https://github.com/AFNetworking/AFNetworking/pull/4182).
+* Use @available if available to silence a warning.
+ * Implemented by Jeff Kelley in [#4138](https://github.com/AFNetworking/AFNetworking/pull/4138).
+* UIImageView+AFNetworking: Prevent stuck state for malformed urlRequest
+ * Implemented by Adam Duflo and aduflo in [#4131](https://github.com/AFNetworking/AFNetworking/pull/4131).
+* add the link for LICENSE
+ * Implemented by Liao Malin in [#4125](https://github.com/AFNetworking/AFNetworking/pull/4125).
+* Fix analyzer warning for upload task creation
+ * Implemented by Jeff Kelley in [#4122](https://github.com/AFNetworking/AFNetworking/pull/4122).
+ 
+
 ## [3.2.0](https://github.com/AFNetworking/AFNetworking/releases/tag/3.2.0) (12/15/2017)
 Released on Friday, December 15, 2017. All issues associated with this milestone can be found using this [filter](https://github.com/AFNetworking/AFNetworking/issues?q=milestone%3A3.2.0+is%3Aclosed).
 

+ 97 - 0
CONTRIBUTING_CH.md

@@ -0,0 +1,97 @@
+# 贡献指南
+本文档包含有关为此项目做出贡献的信息和指南。
+请在开始参加之前阅读。
+
+**主题**
+
+* [提问](#提问)
+* [报告安全问题](#报告安全问题)
+* [报告其他问题](#报告其他问题)
+* [提交拉取请求](#提交拉取请求)
+* [开发人员原产地证书](#开发人员原产地证书-1.1)
+* [行为守则](#行为守则)
+
+## 提问
+
+我们不使用GitHub的论坛发表问题
+对于任何非特定于项目本身的使用问题,
+请直接在[Stack Overflow](https://stackoverflow.com)上询问。
+通过此方法,你可以快速解决您的问题,
+并且任何有相同问题的人可以找到答案。
+这也使维护人员能够专注于为其他人改进项目。
+
+## 报告安全问题
+
+Alamofire Software Foundation 认真对待安全问题。
+如果您发现任何关于安全的问题,请立即通知我们!
+
+请**不要**公然公开发布问题,
+而是将您的问题私下发送到<security@alamofire.org>。
+这将有于帮助确保发现的任何漏洞
+可以[披露制度](http://en.wikipedia.org/wiki/Responsible_disclosure)
+对任何受影响的各方
+
+## 报告其他问题
+
+为此项目贡献的方法
+是当遇到问题时,请发送一篇详细的错误报告。
+我们会感谢您写出的一份精心编写的详尽错误报告。
+
+在提交问题之前,请检查项目里的问题数据库是否已存在此问题。
+如果您找到匹配项,请添加“+1”或“我也遇到此问题”。
+这样做有助于确定最常见问题和请求的优先级。
+
+报告问题时,请包含以下内容:
+
+* 您正在使用的Xcode版本
+* 您的iOS或OS X版本
+* 任何堆栈轨迹或编译器错误的完整输出
+* 如果代码段可再现所描述的行为
+* 任何其他有助于理解问题的细节
+
+此信息有助于我们更快地查看和修复您的问题。
+
+## 提交拉取请求
+
+大力鼓励和欢迎拉取请求。在提交拉取请求时,请创建适当的测试用例,说明修复的问题或新功能。
+
+## 开发人员原产地证书 1.1
+
+为了项目做出贡献,我保证:
+
+- (a) The contribution was created in whole or in part by me and I
+      have the right to submit it under the open source license
+      indicated in the file; or
+
+- (b) The contribution is based upon previous work that, to the best
+      of my knowledge, is covered under an appropriate open source
+      license and I have the right under that license to submit that
+      work with modifications, whether created in whole or in part
+      by me, under the same open source license (unless I am
+      permitted to submit under a different license), as indicated
+      in the file; or
+
+- (c) The contribution was provided directly to me by some other
+      person who certified (a), (b) or (c) and I have not modified
+      it.
+
+- (d) I understand and agree that this project and the contribution
+      are public and that a record of the contribution (including all
+      personal information I submit with it, including my sign-off) is
+      maintained indefinitely and may be redistributed consistent with
+      this project or the open source license(s) involved.
+
+## 行为守则
+
+该项目采取贡献者公约为准则。
+
+这项目的成果将会被我们的行为或行动影响。
+
+我们期望每个为此项目做出贡献的人都会对此表示敬意。
+
+详情请阅读 [CONDUCT.md](https://github.com/Alamofire/Foundation/blob/master/CONDUCT.md)。
+
+----
+
+*上述陈述的一些想法和措辞是基于 [Docker](https://github.com/docker/docker/blob/master/CONTRIBUTING.md) 和 [Linux](http://elinux.org/Developer_Certificate_Of_Origin) 社区. 
+我们表彰和感激他们为促进项目合作所做的付出。*

+ 18 - 1
Example/AFNetworking Example.xcodeproj/project.pbxproj

@@ -500,7 +500,7 @@
 		29E6F16B1BB9DA2E00A4466C /* Project object */ = {
 			isa = PBXProject;
 			attributes = {
-				LastUpgradeCheck = 0910;
+				LastUpgradeCheck = 0930;
 				TargetAttributes = {
 					291BFDB81BB9E85400FFB029 = {
 						CreatedOnToolsVersion = 7.1;
@@ -709,6 +709,7 @@
 				CLANG_CXX_LIBRARY = "libc++";
 				CLANG_ENABLE_MODULES = YES;
 				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_ENABLE_OBJC_WEAK = YES;
 				CLANG_WARN_BOOL_CONVERSION = YES;
 				CLANG_WARN_CONSTANT_CONVERSION = YES;
 				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
@@ -757,6 +758,7 @@
 				CLANG_CXX_LIBRARY = "libc++";
 				CLANG_ENABLE_MODULES = YES;
 				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_ENABLE_OBJC_WEAK = YES;
 				CLANG_WARN_BOOL_CONVERSION = YES;
 				CLANG_WARN_CONSTANT_CONVERSION = YES;
 				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
@@ -800,6 +802,7 @@
 				CLANG_CXX_LIBRARY = "libc++";
 				CLANG_ENABLE_MODULES = YES;
 				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_ENABLE_OBJC_WEAK = YES;
 				CLANG_WARN_BOOL_CONVERSION = YES;
 				CLANG_WARN_CONSTANT_CONVERSION = YES;
 				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
@@ -849,6 +852,7 @@
 				CLANG_CXX_LIBRARY = "libc++";
 				CLANG_ENABLE_MODULES = YES;
 				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_ENABLE_OBJC_WEAK = YES;
 				CLANG_WARN_BOOL_CONVERSION = YES;
 				CLANG_WARN_CONSTANT_CONVERSION = YES;
 				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
@@ -892,6 +896,7 @@
 				CLANG_CXX_LIBRARY = "libc++";
 				CLANG_ENABLE_MODULES = YES;
 				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_ENABLE_OBJC_WEAK = YES;
 				CLANG_WARN_BOOL_CONVERSION = YES;
 				CLANG_WARN_CONSTANT_CONVERSION = YES;
 				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
@@ -941,6 +946,7 @@
 				CLANG_CXX_LIBRARY = "libc++";
 				CLANG_ENABLE_MODULES = YES;
 				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_ENABLE_OBJC_WEAK = YES;
 				CLANG_WARN_BOOL_CONVERSION = YES;
 				CLANG_WARN_CONSTANT_CONVERSION = YES;
 				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
@@ -984,6 +990,7 @@
 				CLANG_CXX_LIBRARY = "libc++";
 				CLANG_ENABLE_MODULES = YES;
 				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_ENABLE_OBJC_WEAK = YES;
 				CLANG_WARN_BOOL_CONVERSION = YES;
 				CLANG_WARN_CONSTANT_CONVERSION = YES;
 				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
@@ -1036,6 +1043,7 @@
 				CLANG_CXX_LIBRARY = "libc++";
 				CLANG_ENABLE_MODULES = YES;
 				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_ENABLE_OBJC_WEAK = YES;
 				CLANG_WARN_BOOL_CONVERSION = YES;
 				CLANG_WARN_CONSTANT_CONVERSION = YES;
 				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
@@ -1078,11 +1086,13 @@
 				CLANG_WARN_BOOL_CONVERSION = YES;
 				CLANG_WARN_COMMA = YES;
 				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
 				CLANG_WARN_EMPTY_BODY = YES;
 				CLANG_WARN_ENUM_CONVERSION = YES;
 				CLANG_WARN_INFINITE_RECURSION = YES;
 				CLANG_WARN_INT_CONVERSION = YES;
 				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
 				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
 				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
 				CLANG_WARN_STRICT_PROTOTYPES = YES;
@@ -1109,11 +1119,13 @@
 				CLANG_WARN_BOOL_CONVERSION = YES;
 				CLANG_WARN_COMMA = YES;
 				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
 				CLANG_WARN_EMPTY_BODY = YES;
 				CLANG_WARN_ENUM_CONVERSION = YES;
 				CLANG_WARN_INFINITE_RECURSION = YES;
 				CLANG_WARN_INT_CONVERSION = YES;
 				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
 				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
 				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
 				CLANG_WARN_STRICT_PROTOTYPES = YES;
@@ -1128,6 +1140,7 @@
 				GCC_WARN_UNINITIALIZED_AUTOS = YES;
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
+				SWIFT_COMPILATION_MODE = wholemodule;
 				SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
 			};
 			name = Release;
@@ -1141,6 +1154,7 @@
 				CLANG_CXX_LIBRARY = "libc++";
 				CLANG_ENABLE_MODULES = YES;
 				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_ENABLE_OBJC_WEAK = YES;
 				CLANG_WARN_BOOL_CONVERSION = YES;
 				CLANG_WARN_CONSTANT_CONVERSION = YES;
 				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
@@ -1189,6 +1203,7 @@
 				CLANG_CXX_LIBRARY = "libc++";
 				CLANG_ENABLE_MODULES = YES;
 				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_ENABLE_OBJC_WEAK = YES;
 				CLANG_WARN_BOOL_CONVERSION = YES;
 				CLANG_WARN_CONSTANT_CONVERSION = YES;
 				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
@@ -1230,6 +1245,7 @@
 				CLANG_CXX_LIBRARY = "libc++";
 				CLANG_ENABLE_MODULES = YES;
 				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_ENABLE_OBJC_WEAK = YES;
 				CLANG_WARN_BOOL_CONVERSION = YES;
 				CLANG_WARN_CONSTANT_CONVERSION = YES;
 				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
@@ -1278,6 +1294,7 @@
 				CLANG_CXX_LIBRARY = "libc++";
 				CLANG_ENABLE_MODULES = YES;
 				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_ENABLE_OBJC_WEAK = YES;
 				CLANG_WARN_BOOL_CONVERSION = YES;
 				CLANG_WARN_CONSTANT_CONVERSION = YES;
 				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;

+ 1 - 3
Example/AFNetworking Example.xcodeproj/xcshareddata/xcschemes/iOS Example.xcscheme

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "0910"
+   LastUpgradeVersion = "0930"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
@@ -40,7 +40,6 @@
       buildConfiguration = "Debug"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      language = ""
       shouldUseLaunchSchemeArgsEnv = "YES">
       <Testables>
          <TestableReference
@@ -70,7 +69,6 @@
       buildConfiguration = "Debug"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      language = ""
       launchStyle = "0"
       useCustomWorkingDirectory = "NO"
       ignoresPersistentStateOnLaunch = "NO"

+ 1 - 3
Example/AFNetworking Example.xcodeproj/xcshareddata/xcschemes/iOS Today Extension Example.xcscheme

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "0910"
+   LastUpgradeVersion = "0930"
    wasCreatedForAppExtension = "YES"
    version = "2.0">
    <BuildAction
@@ -55,7 +55,6 @@
       buildConfiguration = "Debug"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      language = ""
       shouldUseLaunchSchemeArgsEnv = "YES">
       <Testables>
          <TestableReference
@@ -85,7 +84,6 @@
       buildConfiguration = "Debug"
       selectedDebuggerIdentifier = ""
       selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
-      language = ""
       launchStyle = "0"
       useCustomWorkingDirectory = "NO"
       ignoresPersistentStateOnLaunch = "NO"

+ 1 - 3
Example/AFNetworking Example.xcodeproj/xcshareddata/xcschemes/macOS Example.xcscheme

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "0910"
+   LastUpgradeVersion = "0930"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
@@ -40,7 +40,6 @@
       buildConfiguration = "Debug"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      language = ""
       shouldUseLaunchSchemeArgsEnv = "YES">
       <Testables>
          <TestableReference
@@ -70,7 +69,6 @@
       buildConfiguration = "Debug"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      language = ""
       launchStyle = "0"
       useCustomWorkingDirectory = "NO"
       ignoresPersistentStateOnLaunch = "NO"

+ 1 - 3
Example/AFNetworking Example.xcodeproj/xcshareddata/xcschemes/tvOS Example.xcscheme

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "0910"
+   LastUpgradeVersion = "0930"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
@@ -40,7 +40,6 @@
       buildConfiguration = "Debug"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      language = ""
       shouldUseLaunchSchemeArgsEnv = "YES">
       <Testables>
          <TestableReference
@@ -70,7 +69,6 @@
       buildConfiguration = "Debug"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      language = ""
       launchStyle = "0"
       useCustomWorkingDirectory = "NO"
       ignoresPersistentStateOnLaunch = "NO"

+ 1 - 3
Example/AFNetworking Example.xcodeproj/xcshareddata/xcschemes/watchOS Example.xcscheme

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "0910"
+   LastUpgradeVersion = "0930"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
@@ -68,7 +68,6 @@
       buildConfiguration = "Debug"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      language = ""
       shouldUseLaunchSchemeArgsEnv = "YES">
       <Testables>
       </Testables>
@@ -88,7 +87,6 @@
       buildConfiguration = "Debug"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      language = ""
       launchStyle = "0"
       useCustomWorkingDirectory = "NO"
       ignoresPersistentStateOnLaunch = "NO"

+ 62 - 32
Example/Assets.xcassets/AppIcon.appiconset/Contents.json

@@ -2,79 +2,109 @@
   "images" : [
     {
       "idiom" : "iphone",
-      "size" : "29x29",
-      "scale" : "2x",
-      "filename" : "Icon-Small@2x.png"
+      "size" : "20x20",
+      "scale" : "2x"
     },
     {
       "idiom" : "iphone",
-      "size" : "29x29",
-      "scale" : "3x",
-      "filename" : "Icon-Small@3x.png"
+      "size" : "20x20",
+      "scale" : "3x"
     },
     {
+      "size" : "29x29",
       "idiom" : "iphone",
-      "size" : "40x40",
-      "scale" : "2x",
-      "filename" : "Icon-40@2x.png"
+      "filename" : "Icon-Small@2x.png",
+      "scale" : "2x"
     },
     {
+      "size" : "29x29",
       "idiom" : "iphone",
+      "filename" : "Icon-Small@3x.png",
+      "scale" : "3x"
+    },
+    {
       "size" : "40x40",
-      "scale" : "3x",
-      "filename" : "Icon-40@3x.png"
+      "idiom" : "iphone",
+      "filename" : "Icon-40@2x.png",
+      "scale" : "2x"
     },
     {
+      "size" : "40x40",
       "idiom" : "iphone",
-      "size" : "60x60",
-      "scale" : "2x",
-      "filename" : "Icon-60@2x.png"
+      "filename" : "Icon-40@3x.png",
+      "scale" : "3x"
     },
     {
+      "size" : "60x60",
       "idiom" : "iphone",
+      "filename" : "Icon-60@2x.png",
+      "scale" : "2x"
+    },
+    {
       "size" : "60x60",
-      "scale" : "3x",
-      "filename" : "Icon-60@3x.png"
+      "idiom" : "iphone",
+      "filename" : "Icon-60@3x.png",
+      "scale" : "3x"
     },
     {
       "idiom" : "ipad",
-      "size" : "29x29",
-      "scale" : "1x",
-      "filename" : "Icon-Small.png"
+      "size" : "20x20",
+      "scale" : "1x"
     },
     {
       "idiom" : "ipad",
+      "size" : "20x20",
+      "scale" : "2x"
+    },
+    {
       "size" : "29x29",
-      "scale" : "2x",
-      "filename" : "Icon-Small@2x.png"
+      "idiom" : "ipad",
+      "filename" : "Icon-Small.png",
+      "scale" : "1x"
     },
     {
+      "size" : "29x29",
       "idiom" : "ipad",
-      "size" : "40x40",
-      "scale" : "1x",
-      "filename" : "Icon-40.png"
+      "filename" : "Icon-Small@2x.png",
+      "scale" : "2x"
     },
     {
+      "size" : "40x40",
       "idiom" : "ipad",
+      "filename" : "Icon-40.png",
+      "scale" : "1x"
+    },
+    {
       "size" : "40x40",
-      "scale" : "2x",
-      "filename" : "Icon-40@2x.png"
+      "idiom" : "ipad",
+      "filename" : "Icon-40@2x.png",
+      "scale" : "2x"
     },
     {
+      "size" : "76x76",
       "idiom" : "ipad",
+      "filename" : "Icon-76.png",
+      "scale" : "1x"
+    },
+    {
       "size" : "76x76",
-      "scale" : "1x",
-      "filename" : "Icon-76.png"
+      "idiom" : "ipad",
+      "filename" : "Icon-76@2x.png",
+      "scale" : "2x"
     },
     {
       "idiom" : "ipad",
-      "size" : "76x76",
-      "scale" : "2x",
-      "filename" : "Icon-76@2x.png"
+      "size" : "83.5x83.5",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "ios-marketing",
+      "size" : "1024x1024",
+      "scale" : "1x"
     }
   ],
   "info" : {
     "version" : 1,
-    "author" : "makeappicon"
+    "author" : "xcode"
   }
 }

+ 4 - 0
Example/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Content.imageset/Contents.json

@@ -3,6 +3,10 @@
     {
       "idiom" : "tv",
       "scale" : "1x"
+    },
+    {
+      "idiom" : "tv",
+      "scale" : "2x"
     }
   ],
   "info" : {

+ 4 - 0
Example/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Content.imageset/Contents.json

@@ -3,6 +3,10 @@
     {
       "idiom" : "tv",
       "scale" : "1x"
+    },
+    {
+      "idiom" : "tv",
+      "scale" : "2x"
     }
   ],
   "info" : {

+ 4 - 0
Example/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json

@@ -3,6 +3,10 @@
     {
       "idiom" : "tv",
       "scale" : "1x"
+    },
+    {
+      "idiom" : "tv",
+      "scale" : "2x"
     }
   ],
   "info" : {

+ 4 - 0
Example/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Content.imageset/Contents.json

@@ -3,6 +3,10 @@
     {
       "idiom" : "tv",
       "scale" : "1x"
+    },
+    {
+      "idiom" : "tv",
+      "scale" : "2x"
     }
   ],
   "info" : {

+ 4 - 0
Example/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Content.imageset/Contents.json

@@ -3,6 +3,10 @@
     {
       "idiom" : "tv",
       "scale" : "1x"
+    },
+    {
+      "idiom" : "tv",
+      "scale" : "2x"
     }
   ],
   "info" : {

+ 4 - 0
Example/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json

@@ -3,6 +3,10 @@
     {
       "idiom" : "tv",
       "scale" : "1x"
+    },
+    {
+      "idiom" : "tv",
+      "scale" : "2x"
     }
   ],
   "info" : {

+ 7 - 1
Example/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json

@@ -12,6 +12,12 @@
       "filename" : "App Icon - Small.imagestack",
       "role" : "primary-app-icon"
     },
+    {
+      "size" : "2320x720",
+      "idiom" : "tv",
+      "filename" : "Top Shelf Image Wide.imageset",
+      "role" : "top-shelf-image-wide"
+    },
     {
       "size" : "1920x720",
       "idiom" : "tv",
@@ -23,4 +29,4 @@
     "version" : 1,
     "author" : "xcode"
   }
-}
+}

+ 16 - 0
Example/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Contents.json

@@ -0,0 +1,16 @@
+{
+  "images" : [
+    {
+      "idiom" : "tv",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "tv",
+      "scale" : "2x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}

+ 4 - 0
Example/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json

@@ -3,6 +3,10 @@
     {
       "idiom" : "tv",
       "scale" : "1x"
+    },
+    {
+      "idiom" : "tv",
+      "scale" : "2x"
     }
   ],
   "info" : {

+ 7 - 0
Example/tvOS Example/Assets.xcassets/LaunchImage.launchimage/Contents.json

@@ -1,5 +1,12 @@
 {
   "images" : [
+    {
+      "orientation" : "landscape",
+      "idiom" : "tv",
+      "extent" : "full-screen",
+      "minimum-system-version" : "11.0",
+      "scale" : "2x"
+    },
     {
       "orientation" : "landscape",
       "idiom" : "tv",

+ 1 - 0
Framework/AFNetworking.h

@@ -38,6 +38,7 @@ FOUNDATION_EXPORT const unsigned char AFNetworkingVersionString[];
 #import <AFNetworking/AFURLRequestSerialization.h>
 #import <AFNetworking/AFURLResponseSerialization.h>
 #import <AFNetworking/AFSecurityPolicy.h>
+#import <AFNetworking/AFCompatibilityMacros.h>
 
 #if !TARGET_OS_WATCH
 #import <AFNetworking/AFNetworkReachabilityManager.h>

+ 1 - 1
Framework/Info.plist

@@ -19,7 +19,7 @@
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleVersion</key>
-	<string>3.2.0</string>
+	<string>3.2.1</string>
 	<key>NSPrincipalClass</key>
 	<string></string>
 </dict>

+ 1 - 1
README.md

@@ -9,7 +9,7 @@
 [![Platform](https://img.shields.io/cocoapods/p/AFNetworking.svg?style=flat)](http://cocoadocs.org/docsets/AFNetworking)
 [![Twitter](https://img.shields.io/badge/twitter-@AFNetworking-blue.svg?style=flat)](http://twitter.com/AFNetworking)
 
-AFNetworking is a delightful networking library for iOS, macOS, watchOS, and tvOS. It's built on top of the [Foundation URL Loading System](http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/URLLoadingSystem/URLLoadingSystem.html), extending the powerful high-level networking abstractions built into Cocoa. It has a modular architecture with well-designed, feature-rich APIs that are a joy to use.
+AFNetworking is a delightful networking library for iOS, macOS, watchOS, and tvOS. It's built on top of the [Foundation URL Loading System](https://developer.apple.com/documentation/foundation/url_loading_system), extending the powerful high-level networking abstractions built into Cocoa. It has a modular architecture with well-designed, feature-rich APIs that are a joy to use.
 
 Perhaps the most important feature of all, however, is the amazing community of developers who use and contribute to AFNetworking every day. AFNetworking powers some of the most popular and critically-acclaimed apps on the iPhone, iPad, and Mac.
 

二进制
Tests/Resources/HTTPBin.org/HTTPBinOrgServerTrustChain/httpbin_0.cer


二进制
Tests/Resources/HTTPBin.org/httpbinorg_04112018.cer


二进制
Tests/Resources/HTTPBin.org/httpbinorg_10102018.cer


+ 4 - 4
Tests/Tests/AFCompoundResponseSerializerTests.m

@@ -71,8 +71,8 @@
     XCTAssertNotNil(copiedSerializer);
     XCTAssertNotEqual(compoundSerializer, copiedSerializer);
     XCTAssertTrue(compoundSerializer.responseSerializers.count == copiedSerializer.responseSerializers.count);
-    XCTAssertTrue([NSStringFromClass([[copiedSerializer.responseSerializers objectAtIndex:0] class]) isEqualToString:NSStringFromClass([AFImageResponseSerializer class])]);
-    XCTAssertTrue([NSStringFromClass([[copiedSerializer.responseSerializers objectAtIndex:1] class]) isEqualToString:NSStringFromClass([AFJSONResponseSerializer class])]);
+    XCTAssertTrue([NSStringFromClass([copiedSerializer.responseSerializers[0] class]) isEqualToString:NSStringFromClass([AFImageResponseSerializer class])]);
+    XCTAssertTrue([NSStringFromClass([copiedSerializer.responseSerializers[1] class]) isEqualToString:NSStringFromClass([AFJSONResponseSerializer class])]);
     XCTAssertEqual(compoundSerializer.acceptableStatusCodes, copiedSerializer.acceptableStatusCodes);
     XCTAssertEqual(compoundSerializer.acceptableContentTypes, copiedSerializer.acceptableContentTypes);
 }
@@ -87,8 +87,8 @@
     XCTAssertNotNil(unarchivedSerializer);
     XCTAssertNotEqual(unarchivedSerializer, compoundSerializer);
     XCTAssertTrue(compoundSerializer.responseSerializers.count == compoundSerializer.responseSerializers.count);
-    XCTAssertTrue([NSStringFromClass([[unarchivedSerializer.responseSerializers objectAtIndex:0] class]) isEqualToString:NSStringFromClass([AFImageResponseSerializer class])]);
-    XCTAssertTrue([NSStringFromClass([[unarchivedSerializer.responseSerializers objectAtIndex:1] class]) isEqualToString:NSStringFromClass([AFJSONResponseSerializer class])]);
+    XCTAssertTrue([NSStringFromClass([unarchivedSerializer.responseSerializers[0] class]) isEqualToString:NSStringFromClass([AFImageResponseSerializer class])]);
+    XCTAssertTrue([NSStringFromClass([unarchivedSerializer.responseSerializers[1] class]) isEqualToString:NSStringFromClass([AFJSONResponseSerializer class])]);
 }
 
 @end

+ 255 - 40
Tests/Tests/AFHTTPSessionManagerTests.m

@@ -25,24 +25,25 @@
 #import "AFSecurityPolicy.h"
 
 @interface AFHTTPSessionManagerTests : AFTestCase
-@property (readwrite, nonatomic, strong) AFHTTPSessionManager *manager;
+@property (readwrite, nonatomic, strong) AFHTTPSessionManager *sessionManager;
 @end
 
 @implementation AFHTTPSessionManagerTests
 
 - (void)setUp {
     [super setUp];
-    self.manager = [[AFHTTPSessionManager alloc] initWithBaseURL:self.baseURL];
+    self.sessionManager = [[AFHTTPSessionManager alloc] initWithBaseURL:self.baseURL];
 }
 
 - (void)tearDown {
-    [self.manager invalidateSessionCancelingTasks:YES];
+    [self.sessionManager invalidateSessionCancelingTasks:YES resetSession:NO];
+    self.sessionManager = nil;
     [super tearDown];
 }
 
 #pragma mark - init
-- (void)testSharedManagerIsNotEqualToInitdManager {
-    XCTAssertFalse([[AFHTTPSessionManager manager] isEqual:self.manager]);
+- (void)testSharedManagerIsNotEqualToInitedManager {
+    XCTAssertFalse([[AFHTTPSessionManager manager] isEqual:self.sessionManager]);
 }
 
 #pragma mark - misc
@@ -54,7 +55,7 @@
     XCTestExpectation *expectation = [self expectationWithDescription:@"Request should succeed"];
 
     NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"/get" relativeToURL:self.baseURL]];
-    NSURLSessionDataTask *task = [self.manager dataTaskWithRequest:request uploadProgress:nil downloadProgress:nil
+    NSURLSessionDataTask *task = [self.sessionManager dataTaskWithRequest:request uploadProgress:nil downloadProgress:nil
                                                  completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
         blockResponseObject = responseObject;
         blockError = error;
@@ -76,7 +77,7 @@
     XCTestExpectation *expectation = [self expectationWithDescription:@"Request should succeed"];
 
     NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"/status/404" relativeToURL:self.baseURL]];
-    NSURLSessionDataTask *task = [self.manager dataTaskWithRequest:request uploadProgress:nil downloadProgress:nil
+    NSURLSessionDataTask *task = [self.sessionManager dataTaskWithRequest:request uploadProgress:nil downloadProgress:nil
                                                  completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
         blockError = error;
         [expectation fulfill];
@@ -97,13 +98,13 @@
     XCTestExpectation *expectation = [self expectationWithDescription:@"Request should succeed"];
 
     NSURLRequest *redirectRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:@"/redirect/1" relativeToURL:self.baseURL]];
-    NSURLSessionDataTask *redirectTask = [self.manager dataTaskWithRequest:redirectRequest uploadProgress:nil downloadProgress:nil
+    NSURLSessionDataTask *redirectTask = [self.sessionManager dataTaskWithRequest:redirectRequest uploadProgress:nil downloadProgress:nil
                                                          completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
         blockError = error;
         [expectation fulfill];
     }];
 
-    [self.manager setTaskWillPerformHTTPRedirectionBlock:^NSURLRequest *(NSURLSession *session, NSURLSessionTask *task, NSURLResponse *response, NSURLRequest *request) {
+    [self.sessionManager setTaskWillPerformHTTPRedirectionBlock:^NSURLRequest *(NSURLSession *session, NSURLSessionTask *task, NSURLResponse *response, NSURLRequest *request) {
         if (response) {
             success = YES;
         }
@@ -126,14 +127,14 @@
     __block NSURL *downloadFilePath = nil;
     XCTestExpectation *expectation = [self expectationWithDescription:@"Request should succeed"];
 
-    [self.manager setDownloadTaskDidFinishDownloadingBlock:^NSURL *(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, NSURL *location) {
+    [self.sessionManager setDownloadTaskDidFinishDownloadingBlock:^NSURL *(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, NSURL *location) {
         managerDownloadFinishedBlockExecuted = YES;
         NSURL *dirURL  = [[[NSFileManager defaultManager] URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask] lastObject];
         return [dirURL URLByAppendingPathComponent:@"t1.file"];
     }];
 
     NSURLSessionDownloadTask *downloadTask;
-    downloadTask = [self.manager
+    downloadTask = [self.sessionManager
                     downloadTaskWithRequest:[NSURLRequest requestWithURL:self.baseURL]
                     progress:nil
                     destination:nil
@@ -155,7 +156,7 @@
     __block NSURL *downloadFilePath = nil;
     XCTestExpectation *expectation = [self expectationWithDescription:@"Request should succeed"];
 
-    NSURLSessionDownloadTask *downloadTask = [self.manager downloadTaskWithRequest:[NSURLRequest requestWithURL:self.baseURL]
+    NSURLSessionDownloadTask *downloadTask = [self.sessionManager downloadTaskWithRequest:[NSURLRequest requestWithURL:self.baseURL]
                                                                           progress:nil
                                                                        destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {
                                                                            destinationBlockExecuted = YES;
@@ -177,7 +178,7 @@
 - (void)testThatSerializationErrorGeneratesErrorAndNullTaskForGET {
     XCTestExpectation *expectation = [self expectationWithDescription:@"Serialization should fail"];
 
-    [self.manager.requestSerializer setQueryStringSerializationWithBlock:^NSString * _Nonnull(NSURLRequest * _Nonnull request, id  _Nonnull parameters, NSError * _Nullable __autoreleasing * _Nullable error) {
+    [self.sessionManager.requestSerializer setQueryStringSerializationWithBlock:^NSString * _Nonnull(NSURLRequest * _Nonnull request, id  _Nonnull parameters, NSError * _Nullable __autoreleasing * _Nullable error) {
         if (error != NULL) {
             *error = [NSError errorWithDomain:@"Custom" code:-1 userInfo:nil];
         }
@@ -185,9 +186,10 @@
     }];
 
     NSURLSessionTask *nilTask;
-    nilTask = [self.manager
+    nilTask = [self.sessionManager
                GET:@"test"
                parameters:@{@"key":@"value"}
+               headers:nil
                progress:nil
                success:nil
                failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
@@ -205,12 +207,12 @@
 }
 
 - (void)testCanBeEncoded {
-    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self.manager];
+    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self.sessionManager];
     XCTAssertNotNil(data);
 }
 
 - (void)testCanBeDecoded {
-    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self.manager];
+    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self.sessionManager];
     AFHTTPSessionManager *newManager = [NSKeyedUnarchiver unarchiveObjectWithData:data];
     XCTAssertNotNil(newManager.securityPolicy);
     XCTAssertNotNil(newManager.requestSerializer);
@@ -223,7 +225,7 @@
 #pragma mark - NSCopying 
 
 - (void)testCanBeCopied {
-    AFHTTPSessionManager *copyManager = [self.manager copy];
+    AFHTTPSessionManager *copyManager = [self.sessionManager copy];
     XCTAssertNotNil(copyManager);
 }
 
@@ -231,9 +233,10 @@
 
 - (void)testDownloadProgressIsReportedForGET {
     __weak XCTestExpectation *expectation = [self expectationWithDescription:@"Progress Should equal 1.0"];
-    [self.manager
+    [self.sessionManager
      GET:@"image"
      parameters:nil
+     headers:nil
      progress:^(NSProgress * _Nonnull downloadProgress) {
          if (downloadProgress.fractionCompleted == 1.0) {
              [expectation fulfill];
@@ -252,9 +255,10 @@
 
     __weak XCTestExpectation *expectation = [self expectationWithDescription:@"Progress Should equal 1.0"];
 
-    [self.manager
+    [self.sessionManager
      POST:@"post"
      parameters:payload
+     headers:nil
      progress:^(NSProgress * _Nonnull uploadProgress) {
          if (uploadProgress.fractionCompleted == 1.0) {
              [expectation fulfill];
@@ -273,9 +277,10 @@
 
     __weak XCTestExpectation *expectation = [self expectationWithDescription:@"Progress Should equal 1.0"];
 
-    [self.manager
+    [self.sessionManager
      POST:@"post"
      parameters:nil
+     headers:nil
      constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
          [formData appendPartWithFileData:[payload dataUsingEncoding:NSUTF8StringEncoding] name:@"AFNetworking" fileName:@"AFNetworking" mimeType:@"text/html"];
      }
@@ -289,13 +294,83 @@
     [self waitForExpectationsWithCommonTimeout];
 }
 
+# pragma mark - Deprecated Progress
+
+- (void)testDownloadProgressIsReportedForDeprecatedGET {
+    __weak XCTestExpectation *expectation = [self expectationWithDescription:@"Progress Should equal 1.0"];
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+    [self.sessionManager
+     GET:@"image"
+     parameters:nil
+     progress:^(NSProgress * _Nonnull downloadProgress) {
+         if (downloadProgress.fractionCompleted == 1.0) {
+             [expectation fulfill];
+         }
+     }
+     success:nil
+     failure:nil];
+#pragma clang diagnostic pop
+    [self waitForExpectationsWithCommonTimeout];
+}
+
+- (void)testUploadProgressIsReportedForDeprecatedPOST {
+    NSMutableString *payload = [NSMutableString stringWithString:@"AFNetworking"];
+    while ([payload lengthOfBytesUsingEncoding:NSUTF8StringEncoding] < 20000) {
+        [payload appendString:@"AFNetworking"];
+    }
+    
+    __weak XCTestExpectation *expectation = [self expectationWithDescription:@"Progress Should equal 1.0"];
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+    [self.sessionManager
+     POST:@"post"
+     parameters:payload
+     progress:^(NSProgress * _Nonnull uploadProgress) {
+         if (uploadProgress.fractionCompleted == 1.0) {
+             [expectation fulfill];
+         }
+     }
+     success:nil
+     failure:nil];
+#pragma clang diagnostic pop
+    [self waitForExpectationsWithCommonTimeout];
+}
+
+- (void)testUploadProgressIsReportedForStreamingDeprecatedPost {
+    NSMutableString *payload = [NSMutableString stringWithString:@"AFNetworking"];
+    while ([payload lengthOfBytesUsingEncoding:NSUTF8StringEncoding] < 20000) {
+        [payload appendString:@"AFNetworking"];
+    }
+    
+    __weak XCTestExpectation *expectation = [self expectationWithDescription:@"Progress Should equal 1.0"];
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+    [self.sessionManager
+     POST:@"post"
+     parameters:nil
+     constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
+         [formData appendPartWithFileData:[payload dataUsingEncoding:NSUTF8StringEncoding] name:@"AFNetworking" fileName:@"AFNetworking" mimeType:@"text/html"];
+     }
+     progress:^(NSProgress * _Nonnull uploadProgress) {
+         if (uploadProgress.fractionCompleted == 1.0) {
+             [expectation fulfill];
+         }
+     }
+     success:nil
+     failure:nil];
+#pragma clang diagnostic pop
+    [self waitForExpectationsWithCommonTimeout];
+}
+
 # pragma mark - HTTP Status Codes
 
 - (void)testThatSuccessBlockIsCalledFor200 {
     XCTestExpectation *expectation = [self expectationWithDescription:@"Request should succeed"];
-    [self.manager
+    [self.sessionManager
      GET:@"status/200"
      parameters:nil
+     headers:nil
      progress:nil
      success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
          [expectation fulfill];
@@ -306,9 +381,10 @@
 
 - (void)testThatFailureBlockIsCalledFor404 {
     XCTestExpectation *expectation = [self expectationWithDescription:@"Request should succeed"];
-    [self.manager
+    [self.sessionManager
      GET:@"status/404"
      parameters:nil
+     headers:nil
      progress:nil
      success:nil
      failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nullable error) {
@@ -320,9 +396,10 @@
 - (void)testThatResponseObjectIsEmptyFor204 {
     __block id urlResponseObject = nil;
     XCTestExpectation *expectation = [self expectationWithDescription:@"Request should succeed"];
-    [self.manager
+    [self.sessionManager
      GET:@"status/204"
      parameters:nil
+     headers:nil
      progress:nil
      success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
          urlResponseObject = responseObject;
@@ -337,9 +414,10 @@
 
 - (void)testGET {
     XCTestExpectation *expectation = [self expectationWithDescription:@"Request should succeed"];
-    [self.manager
+    [self.sessionManager
      GET:@"get"
      parameters:nil
+     headers:nil
      progress:nil
      success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
          XCTAssertNotNil(responseObject);
@@ -351,9 +429,10 @@
 
 - (void)testHEAD {
     XCTestExpectation *expectation = [self expectationWithDescription:@"Request should succeed"];
-    [self.manager
+    [self.sessionManager
      HEAD:@"get"
      parameters:nil
+     headers:nil
      success:^(NSURLSessionDataTask * _Nonnull task) {
          XCTAssertNotNil(task);
          [expectation fulfill];
@@ -364,11 +443,13 @@
 
 - (void)testPOST {
     XCTestExpectation *expectation = [self expectationWithDescription:@"Request should succeed"];
-    [self.manager
+    [self.sessionManager
      POST:@"post"
      parameters:@{@"key":@"value"}
+     headers:@{@"field":@"value"}
      progress:nil
      success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
+         XCTAssertTrue([task.originalRequest.allHTTPHeaderFields[@"field"] isEqualToString:@"value"]);
          XCTAssertTrue([responseObject[@"form"][@"key"] isEqualToString:@"value"]);
          [expectation fulfill];
      }
@@ -378,9 +459,10 @@
 
 - (void)testPOSTWithConstructingBody {
     XCTestExpectation *expectation = [self expectationWithDescription:@"Request should succeed"];
-    [self.manager
+    [self.sessionManager
      POST:@"post"
      parameters:@{@"key":@"value"}
+     headers:@{@"field":@"value"}
      constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
          [formData appendPartWithFileData:[@"Data" dataUsingEncoding:NSUTF8StringEncoding]
                                      name:@"DataName"
@@ -389,6 +471,7 @@
      }
      progress:nil
      success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
+         XCTAssertTrue([task.originalRequest.allHTTPHeaderFields[@"field"] isEqualToString:@"value"]);
          XCTAssertTrue([responseObject[@"files"][@"DataName"] isEqualToString:@"Data"]);
          XCTAssertTrue([responseObject[@"form"][@"key"] isEqualToString:@"value"]);
          [expectation fulfill];
@@ -399,10 +482,12 @@
 
 - (void)testPUT {
     XCTestExpectation *expectation = [self expectationWithDescription:@"Request should succeed"];
-    [self.manager
+    [self.sessionManager
      PUT:@"put"
      parameters:@{@"key":@"value"}
+     headers:@{@"field":@"value"}
      success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
+         XCTAssertTrue([task.originalRequest.allHTTPHeaderFields[@"field"] isEqualToString:@"value"]);
          XCTAssertTrue([responseObject[@"form"][@"key"] isEqualToString:@"value"]);
          [expectation fulfill];
      }
@@ -412,10 +497,12 @@
 
 - (void)testDELETE {
     XCTestExpectation *expectation = [self expectationWithDescription:@"Request should succeed"];
-    [self.manager
+    [self.sessionManager
      DELETE:@"delete"
      parameters:@{@"key":@"value"}
+     headers:@{@"field":@"value"}
      success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
+         XCTAssertTrue([task.originalRequest.allHTTPHeaderFields[@"field"] isEqualToString:@"value"]);
          XCTAssertTrue([responseObject[@"args"][@"key"] isEqualToString:@"value"]);
          [expectation fulfill];
      }
@@ -425,10 +512,12 @@
 
 - (void)testPATCH {
     XCTestExpectation *expectation = [self expectationWithDescription:@"Request should succeed"];
-    [self.manager
+    [self.sessionManager
      PATCH:@"patch"
      parameters:@{@"key":@"value"}
+     headers:@{@"field":@"value"}
      success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
+         XCTAssertTrue([task.originalRequest.allHTTPHeaderFields[@"field"] isEqualToString:@"value"]);
          XCTAssertTrue([responseObject[@"form"][@"key"] isEqualToString:@"value"]);
          [expectation fulfill];
      }
@@ -439,11 +528,11 @@
 
 #pragma mark - Deprecated Rest Interface
 
-- (void)testDeprecatedGET {
+- (void)testDeprecatedGETWithoutProgress {
     XCTestExpectation *expectation = [self expectationWithDescription:@"Request should succeed"];
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
-    [self.manager
+    [self.sessionManager
      GET:@"get"
      parameters:nil
      success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
@@ -455,11 +544,11 @@
     [self waitForExpectationsWithCommonTimeout];
 }
 
-- (void)testDeprecatedPOST {
+- (void)testDeprecatedPOSTWithoutProgress {
     XCTestExpectation *expectation = [self expectationWithDescription:@"Request should succeed"];
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
-    [self.manager
+    [self.sessionManager
      POST:@"post"
      parameters:@{@"key":@"value"}
      success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
@@ -471,11 +560,11 @@
     [self waitForExpectationsWithCommonTimeout];
 }
 
-- (void)testDeprecatedPOSTWithConstructingBody {
+- (void)testDeprecatedPOSTWithoutProgressWithConstructingBody {
     XCTestExpectation *expectation = [self expectationWithDescription:@"Request should succeed"];
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
-    [self.manager
+    [self.sessionManager
      POST:@"post"
      parameters:@{@"key":@"value"}
      constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
@@ -494,14 +583,138 @@
     [self waitForExpectationsWithCommonTimeout];
 }
 
+
+- (void)testDeprecatedGETWithoutHeaders {
+    XCTestExpectation *expectation = [self expectationWithDescription:@"Request should succeed"];
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+    [self.sessionManager
+     GET:@"get"
+     parameters:nil
+     progress:nil
+     success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
+         XCTAssertNotNil(responseObject);
+         [expectation fulfill];
+     }
+     failure:nil];
+#pragma clang diagnostic pop
+    [self waitForExpectationsWithCommonTimeout];
+}
+
+- (void)testDeprecatedHEADWithoutHeaders {
+    XCTestExpectation *expectation = [self expectationWithDescription:@"Request should succeed"];
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+    [self.sessionManager
+     HEAD:@"get"
+     parameters:nil
+     success:^(NSURLSessionDataTask * _Nonnull task) {
+         XCTAssertNotNil(task);
+         [expectation fulfill];
+     }
+     failure:nil];
+#pragma clang diagnostic pop
+    [self waitForExpectationsWithCommonTimeout];
+}
+
+- (void)testDeprecatedPOSTWithoutHeaders {
+    XCTestExpectation *expectation = [self expectationWithDescription:@"Request should succeed"];
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+    [self.sessionManager
+     POST:@"post"
+     parameters:@{@"key":@"value"}
+     progress:nil
+     success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
+         XCTAssertTrue([responseObject[@"form"][@"key"] isEqualToString:@"value"]);
+         [expectation fulfill];
+     }
+     failure:nil];
+#pragma clang diagnostic pop
+    [self waitForExpectationsWithCommonTimeout];
+}
+
+- (void)testDeprecatedPOSTWithoutHeadersWithConstructingBody {
+    XCTestExpectation *expectation = [self expectationWithDescription:@"Request should succeed"];
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+    [self.sessionManager
+     POST:@"post"
+     parameters:@{@"key":@"value"}
+     constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
+         [formData appendPartWithFileData:[@"Data" dataUsingEncoding:NSUTF8StringEncoding]
+                                     name:@"DataName"
+                                 fileName:@"DataFileName"
+                                 mimeType:@"data"];
+     }
+     progress:nil
+     success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
+         XCTAssertTrue([responseObject[@"files"][@"DataName"] isEqualToString:@"Data"]);
+         XCTAssertTrue([responseObject[@"form"][@"key"] isEqualToString:@"value"]);
+         [expectation fulfill];
+     }
+     failure:nil];
+#pragma clang diagnostic pop
+    [self waitForExpectationsWithCommonTimeout];
+}
+
+- (void)testDeprecatedPUTWithoutHeaders {
+    XCTestExpectation *expectation = [self expectationWithDescription:@"Request should succeed"];
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+    [self.sessionManager
+     PUT:@"put"
+     parameters:@{@"key":@"value"}
+     success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
+         XCTAssertTrue([responseObject[@"form"][@"key"] isEqualToString:@"value"]);
+         [expectation fulfill];
+     }
+     failure:nil];
+#pragma clang diagnostic pop
+    [self waitForExpectationsWithCommonTimeout];
+}
+
+- (void)testDeprecatedDELETEWithoutHeaders {
+    XCTestExpectation *expectation = [self expectationWithDescription:@"Request should succeed"];
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+    [self.sessionManager
+     DELETE:@"delete"
+     parameters:@{@"key":@"value"}
+     success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
+         XCTAssertTrue([responseObject[@"args"][@"key"] isEqualToString:@"value"]);
+         [expectation fulfill];
+     }
+     failure:nil];
+#pragma clang diagnostic pop
+    [self waitForExpectationsWithCommonTimeout];
+}
+
+- (void)testDeprecatedPATCHWithoutHeaders {
+    XCTestExpectation *expectation = [self expectationWithDescription:@"Request should succeed"];
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+    [self.sessionManager
+     PATCH:@"patch"
+     parameters:@{@"key":@"value"}
+     success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
+         XCTAssertTrue([responseObject[@"form"][@"key"] isEqualToString:@"value"]);
+         [expectation fulfill];
+     }
+     failure:nil];
+#pragma clang diagnostic pop
+    [self waitForExpectationsWithCommonTimeout];
+}
+
 #pragma mark - Auth
 
 - (void)testHiddenBasicAuthentication {
     __weak XCTestExpectation *expectation = [self expectationWithDescription:@"Request should finish"];
-    [self.manager.requestSerializer setAuthorizationHeaderFieldWithUsername:@"user" password:@"password"];
-    [self.manager
+    [self.sessionManager.requestSerializer setAuthorizationHeaderFieldWithUsername:@"user" password:@"password"];
+    [self.sessionManager
      GET:@"hidden-basic-auth/user/password"
      parameters:nil
+     headers:nil
      progress:nil
      success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
          [expectation fulfill];
@@ -574,6 +787,7 @@
     [manager
      GET:@""
      parameters:nil
+     headers:nil
      progress:nil
      success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
          XCTFail(@"Request should fail");
@@ -585,7 +799,7 @@
          [expectation fulfill];
      }];
     [self waitForExpectationsWithCommonTimeout];
-    [manager invalidateSessionCancelingTasks:YES];
+    [manager invalidateSessionCancelingTasks:YES resetSession:NO];
 }
 
 - (void)testInvalidServerTrustProducesCorrectErrorForPublicKeyPinning {
@@ -598,6 +812,7 @@
     [manager
      GET:@""
      parameters:nil
+     headers:nil
      progress:nil
      success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
          XCTFail(@"Request should fail");
@@ -609,7 +824,7 @@
          [expectation fulfill];
      }];
     [self waitForExpectationsWithCommonTimeout];
-    [manager invalidateSessionCancelingTasks:YES];
+    [manager invalidateSessionCancelingTasks:YES resetSession:NO];
 }
 
 @end

+ 1 - 1
Tests/Tests/AFImageDownloaderTests.m

@@ -45,7 +45,7 @@
 }
 
 - (void)tearDown {
-    [self.downloader.sessionManager invalidateSessionCancelingTasks:YES];
+    [self.downloader.sessionManager invalidateSessionCancelingTasks:YES resetSession:NO];
     self.downloader = nil;
     // Put teardown code here. This method is called after the invocation of each test method in the class.
     [super tearDown];

+ 2 - 1
Tests/Tests/AFJSONSerializationTests.m

@@ -177,7 +177,7 @@ static NSData * AFJSONTestData() {
 - (void)testThatJSONRemovesKeysWithNullValues {
     self.responseSerializer.removesKeysWithNullValues = YES;
     NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:self.baseURL statusCode:200 HTTPVersion:@"1.1" headerFields:@{@"Content-Type":@"text/json"}];
-    NSData *data = [NSJSONSerialization dataWithJSONObject:@{@"key":@"value",@"nullkey":[NSNull null],@"array":@[@{@"subnullkey":[NSNull null]}]}
+    NSData *data = [NSJSONSerialization dataWithJSONObject:@{@"key":@"value",@"nullkey":[NSNull null],@"array":@[@{@"subnullkey":[NSNull null]}], @"arrayWithNulls": @[[NSNull null]]}
                                                    options:(NSJSONWritingOptions)0
                                                      error:nil];
 
@@ -189,6 +189,7 @@ static NSData * AFJSONTestData() {
     XCTAssertNotNil(responseObject[@"key"]);
     XCTAssertNil(responseObject[@"nullkey"]);
     XCTAssertNil(responseObject[@"array"][0][@"subnullkey"]);
+    XCTAssertEqualObjects(responseObject[@"arrayWithNulls"], @[]);
 }
 
 - (void)testThatJSONResponseSerializerCanBeCopied {

+ 7 - 1
Tests/Tests/AFNetworkActivityManagerTests.m

@@ -46,7 +46,8 @@
     [super tearDown];
     self.networkActivityIndicatorManager = nil;
 
-    [self.sessionManager invalidateSessionCancelingTasks:YES];
+    [self.sessionManager invalidateSessionCancelingTasks:YES resetSession:NO];
+    self.sessionManager = nil;
 }
 
 #pragma mark -
@@ -69,6 +70,7 @@
     [self.sessionManager
      GET:@"/delay/1"
      parameters:nil
+     headers:nil
      progress:nil
      success:^(NSURLSessionDataTask * _Nonnull task, id  _Nonnull responseObject) {
          [requestExpectation fulfill];
@@ -95,6 +97,7 @@
     [self.sessionManager
      GET:@"/status/404"
      parameters:nil
+     headers:nil
      progress:nil
      success:nil
      failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
@@ -128,6 +131,7 @@
     [self.sessionManager
      GET:@"/delay/2"
      parameters:nil
+     headers:nil
      progress:nil
      success:^(NSURLSessionDataTask * _Nonnull task, id  _Nonnull responseObject) {
          requestEndTime = CACurrentMediaTime();
@@ -157,6 +161,7 @@
     [self.sessionManager
      GET:@"/delay/4"
      parameters:nil
+     headers:nil
      progress:nil
      success:^(NSURLSessionDataTask * _Nonnull task, id  _Nonnull responseObject) {
          [requestExpectation fulfill];
@@ -167,6 +172,7 @@
     [self.sessionManager
      GET:@"/delay/2"
      parameters:nil
+     headers:nil
      progress:nil
      success:^(NSURLSessionDataTask * _Nonnull task, id  _Nonnull responseObject) {
 

+ 13 - 0
Tests/Tests/AFNetworkReachabilityManagerTests.m

@@ -125,4 +125,17 @@
     [self verifyReachabilityStatusBlockGetsCalledWithManager:self.domainReachability];
 }
 
+- (void)testObjectPostingReachabilityManagerNotification {
+    [self expectationForNotification:AFNetworkingReachabilityDidChangeNotification
+                              object:self.domainReachability
+                             handler:^BOOL(NSNotification *notification) {
+                                 BOOL isObjectPostingNotification = [notification.object isEqual:self.domainReachability];
+                                 return isObjectPostingNotification;
+                             }];
+    
+    [self.domainReachability startMonitoring];
+    
+    [self waitForExpectationsWithCommonTimeout];
+}
+
 @end

+ 1 - 1
Tests/Tests/AFSecurityPolicyTests.m

@@ -58,7 +58,7 @@ static SecTrustRef AFUTADNNetServerTrust() {
 }
 
 static SecCertificateRef AFUTHTTPBinOrgCertificate() {
-    NSString *certPath = [[NSBundle bundleForClass:[AFSecurityPolicyTests class]] pathForResource:@"httpbinorg_04112018" ofType:@"cer"];
+    NSString *certPath = [[NSBundle bundleForClass:[AFSecurityPolicyTests class]] pathForResource:@"httpbinorg_10102018" ofType:@"cer"];
     NSCAssert(certPath != nil, @"Path for certificate should not be nil");
     NSData *certData = [NSData dataWithContentsOfFile:certPath];
 

+ 1 - 1
Tests/Tests/AFUIActivityIndicatorViewTests.m

@@ -40,7 +40,7 @@
 
 - (void)tearDown {
     [super tearDown];
-    [self.sessionManager invalidateSessionCancelingTasks:YES];
+    [self.sessionManager invalidateSessionCancelingTasks:YES resetSession:NO];
     self.sessionManager = nil;
 }
 

+ 1 - 1
Tests/Tests/AFUIRefreshControlTests.m

@@ -40,7 +40,7 @@
 
 - (void)tearDown {
     [super tearDown];
-    [self.sessionManager invalidateSessionCancelingTasks:YES];
+    [self.sessionManager invalidateSessionCancelingTasks:YES resetSession:NO];
     self.sessionManager = nil;
 }
 

+ 40 - 15
Tests/Tests/AFURLSessionManagerTests.m

@@ -70,10 +70,10 @@
 - (void)tearDown {
     [super tearDown];
     [self.localManager.session.configuration.URLCache removeAllCachedResponses];
-    [self.localManager invalidateSessionCancelingTasks:YES];
+    [self.localManager invalidateSessionCancelingTasks:YES resetSession:NO];
     self.localManager = nil;
     
-    [self.backgroundManager invalidateSessionCancelingTasks:YES];
+    [self.backgroundManager invalidateSessionCancelingTasks:YES resetSession:NO];
     self.backgroundManager = nil;
 }
 
@@ -133,19 +133,44 @@
     [self waitForExpectationsWithCommonTimeout];
 }
 
-// iOS 7 has a bug that may return nil for a session. To simulate that, nil out the
-// session and it will return nil itself.
-- (void)testFileUploadTaskReturnsNilWithBug {
-    [self.localManager setValue:nil forKey:@"session"];
+- (void)testSessionTaskDoesReportMetrics {
+    [self expectationForNotification:AFNetworkingTaskDidCompleteNotification object:nil handler:^BOOL(NSNotification * _Nonnull notification) {
+#if AF_CAN_USE_AT_AVAILABLE && AF_CAN_INCLUDE_SESSION_TASK_METRICS
+        if (@available(iOS 10, macOS 10.12, watchOS 3, tvOS 10, *)) {
+            return [notification userInfo][AFNetworkingTaskDidCompleteSessionTaskMetrics] != nil;
+        }
+#endif
+        return YES;
+    }];
+
+#if AF_CAN_INCLUDE_SESSION_TASK_METRICS
+    __weak XCTestExpectation *metricsBlock = [self expectationWithDescription:@"Metrics completion block is called"];
+    [self.localManager setTaskDidFinishCollectingMetricsBlock:^(NSURLSession * _Nonnull session, NSURLSessionTask * _Nonnull task, NSURLSessionTaskMetrics * _Nullable metrics) {
+        [metricsBlock fulfill];
+    }];
+#endif
+
+    NSURLSessionTask *task = [self.localManager downloadTaskWithRequest:[self bigImageURLRequest]
+                                                               progress:nil
+                                                            destination:nil
+                                                      completionHandler:nil];
+    [task resume];
+    [self waitForExpectationsWithCommonTimeout];
+}
+
+- (void)testSessionIsStillValid {
     
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wnonnull"
-    XCTAssertNil([self.localManager uploadTaskWithRequest:[NSURLRequest requestWithURL:self.baseURL]
-                                                 fromFile:nil
-                                                 progress:NULL
-                                        completionHandler:NULL],
-                 @"Upload task should be nil.");
-#pragma GCC diagnostic pop
+    NSURLSession *session = self.localManager.session;
+    [self.localManager invalidateSessionCancelingTasks:YES resetSession:NO];
+    
+    XCTAssertEqual(session, self.localManager.session);
+}
+
+- (void)testSessionRecreatesAgain {
+    
+    [self.localManager invalidateSessionCancelingTasks:YES resetSession:YES];
+    
+    XCTAssertNotNil(self.localManager.session);
 }
 
 - (void)testUploadTaskDoesReportProgress {
@@ -473,7 +498,7 @@
     return [NSURLRequest requestWithURL:self.delayURL];
 }
 
-- (IMP)_implementationForTask:(NSURLSessionTask  *)task selector:(SEL)selector {
+- (IMP)_implementationForTask:(NSURLSessionTask *)task selector:(SEL)selector {
     return [self _implementationForClass:[task class] selector:selector];
 }
 

+ 2 - 2
UIKit+AFNetworking/AFAutoPurgingImageCache.m

@@ -28,7 +28,7 @@
 @interface AFCachedImage : NSObject
 
 @property (nonatomic, strong) UIImage *image;
-@property (nonatomic, strong) NSString *identifier;
+@property (nonatomic, copy) NSString *identifier;
 @property (nonatomic, assign) UInt64 totalBytes;
 @property (nonatomic, strong) NSDate *lastAccessDate;
 @property (nonatomic, assign) UInt64 currentMemoryUsage;
@@ -51,7 +51,7 @@
     return self;
 }
 
-- (UIImage*)accessImage {
+- (UIImage *)accessImage {
     self.lastAccessDate = [NSDate date];
     return self.image;
 }

+ 16 - 8
UIKit+AFNetworking/AFImageDownloader.m

@@ -28,8 +28,8 @@
 
 @interface AFImageDownloaderResponseHandler : NSObject
 @property (nonatomic, strong) NSUUID *uuid;
-@property (nonatomic, copy) void (^successBlock)(NSURLRequest*, NSHTTPURLResponse*, UIImage*);
-@property (nonatomic, copy) void (^failureBlock)(NSURLRequest*, NSHTTPURLResponse*, NSError*);
+@property (nonatomic, copy) void (^successBlock)(NSURLRequest *, NSHTTPURLResponse *, UIImage *);
+@property (nonatomic, copy) void (^failureBlock)(NSURLRequest *, NSHTTPURLResponse *, NSError *);
 @end
 
 @implementation AFImageDownloaderResponseHandler
@@ -71,11 +71,11 @@
     return self;
 }
 
-- (void)addResponseHandler:(AFImageDownloaderResponseHandler*)handler {
+- (void)addResponseHandler:(AFImageDownloaderResponseHandler *)handler {
     [self.responseHandlers addObject:handler];
 }
 
-- (void)removeResponseHandler:(AFImageDownloaderResponseHandler*)handler {
+- (void)removeResponseHandler:(AFImageDownloaderResponseHandler *)handler {
     [self.responseHandlers removeObject:handler];
 }
 
@@ -254,14 +254,14 @@
                        completionHandler:^(NSURLResponse * _Nonnull response, id  _Nullable responseObject, NSError * _Nullable error) {
                            dispatch_async(self.responseQueue, ^{
                                __strong __typeof__(weakSelf) strongSelf = weakSelf;
-                               AFImageDownloaderMergedTask *mergedTask = strongSelf.mergedTasks[URLIdentifier];
+                               AFImageDownloaderMergedTask *mergedTask = [strongSelf safelyGetMergedTask:URLIdentifier];
                                if ([mergedTask.identifier isEqual:mergedTaskIdentifier]) {
                                    mergedTask = [strongSelf safelyRemoveMergedTaskWithURLIdentifier:URLIdentifier];
                                    if (error) {
                                        for (AFImageDownloaderResponseHandler *handler in mergedTask.responseHandlers) {
                                            if (handler.failureBlock) {
                                                dispatch_async(dispatch_get_main_queue(), ^{
-                                                   handler.failureBlock(request, (NSHTTPURLResponse*)response, error);
+                                                   handler.failureBlock(request, (NSHTTPURLResponse *)response, error);
                                                });
                                            }
                                        }
@@ -273,7 +273,7 @@
                                        for (AFImageDownloaderResponseHandler *handler in mergedTask.responseHandlers) {
                                            if (handler.successBlock) {
                                                dispatch_async(dispatch_get_main_queue(), ^{
-                                                   handler.successBlock(request, (NSHTTPURLResponse*)response, responseObject);
+                                                   handler.successBlock(request, (NSHTTPURLResponse *)response, responseObject);
                                                });
                                            }
                                        }
@@ -340,7 +340,7 @@
     });
 }
 
-- (AFImageDownloaderMergedTask*)safelyRemoveMergedTaskWithURLIdentifier:(NSString *)URLIdentifier {
+- (AFImageDownloaderMergedTask *)safelyRemoveMergedTaskWithURLIdentifier:(NSString *)URLIdentifier {
     __block AFImageDownloaderMergedTask *mergedTask = nil;
     dispatch_sync(self.synchronizationQueue, ^{
         mergedTask = [self removeMergedTaskWithURLIdentifier:URLIdentifier];
@@ -404,6 +404,14 @@
     return self.activeRequestCount < self.maximumActiveDownloads;
 }
 
+- (AFImageDownloaderMergedTask *)safelyGetMergedTask:(NSString *)URLIdentifier {
+    __block AFImageDownloaderMergedTask *mergedTask;
+    dispatch_sync(self.synchronizationQueue, ^(){
+        mergedTask = self.mergedTasks[URLIdentifier];
+    });
+    return mergedTask;
+}
+
 @end
 
 #endif

+ 1 - 1
UIKit+AFNetworking/UIImage+AFNetworking.h

@@ -28,7 +28,7 @@
 
 @interface UIImage (AFNetworking)
 
-+ (UIImage*) safeImageWithData:(NSData*)data;
++ (UIImage *)safeImageWithData:(NSData *)data;
 
 @end
 

+ 1 - 1
UIKit+AFNetworking/UIWebView+AFNetworking.m

@@ -49,7 +49,7 @@
 
 @implementation UIWebView (AFNetworking)
 
-- (AFHTTPSessionManager  *)sessionManager {
+- (AFHTTPSessionManager *)sessionManager {
     static AFHTTPSessionManager *_af_defaultHTTPSessionManager = nil;
     static dispatch_once_t onceToken;
     dispatch_once(&onceToken, ^{

+ 3 - 3
fastlane/.env.default

@@ -1,6 +1,6 @@
-AF_IOS_SDK=iphonesimulator11.2
-AF_MAC_SDK=macosx10.13
-AF_TVOS_SDK=appletvsimulator11.2
+AF_IOS_SDK=iphonesimulator12.0
+AF_MAC_SDK=macosx10.14
+AF_TVOS_SDK=appletvsimulator12.0
 
 AF_CONFIGURATION=Release
 

+ 3 - 0
fastlane/.env.ios11_xcode9

@@ -0,0 +1,3 @@
+SCAN_DEVICE="iPhone 8"
+SCAN_SDK=iphonesimulator11.0
+EXAMPLE_DESTINATION="platform=iOS Simulator,name=iPhone 8"

+ 3 - 0
fastlane/.env.ios11_xcode91

@@ -0,0 +1,3 @@
+SCAN_DEVICE="iPhone 8"
+SCAN_SDK=iphonesimulator11.1
+EXAMPLE_DESTINATION="platform=iOS Simulator,name=iPhone 8"

+ 3 - 0
fastlane/.env.ios11_xcode92

@@ -0,0 +1,3 @@
+SCAN_DEVICE="iPhone 8"
+SCAN_SDK=iphonesimulator11.2
+EXAMPLE_DESTINATION="platform=iOS Simulator,name=iPhone 8"

+ 1 - 1
fastlane/.env.ios11_xcode93

@@ -1,3 +1,3 @@
 SCAN_DEVICE="iPhone 8"
-SCAN_SDK=$AF_IOS_SDK
+SCAN_SDK=iphonesimulator11.3
 EXAMPLE_DESTINATION="platform=iOS Simulator,name=iPhone 8"

+ 3 - 0
fastlane/.env.ios11_xcode94

@@ -0,0 +1,3 @@
+SCAN_DEVICE="iPhone 8"
+SCAN_SDK=iphonesimulator11.4
+EXAMPLE_DESTINATION="platform=iOS Simulator,name=iPhone 8"

+ 3 - 0
fastlane/.env.ios12_xcode10

@@ -0,0 +1,3 @@
+SCAN_DEVICE="iPhone 8"
+SCAN_SDK=$AF_IOS_SDK
+EXAMPLE_DESTINATION="platform=iOS Simulator,name=iPhone 8"

+ 0 - 0
fastlane/.env.tvos11_xcode9 → fastlane/.env.tvos12_xcode10