├── .gitignore ├── .travis.yml ├── 1.x ├── AFHTTPClient+Synchronous.h ├── AFHTTPClient+Synchronous.m ├── AFHTTPRequestOperation+ResponseObject.h ├── AFHTTPRequestOperation+ResponseObject.m └── TestProject │ ├── Podfile │ ├── Podfile.lock │ ├── TestProject.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── xcshareddata │ │ └── xcschemes │ │ └── Tests.xcscheme │ ├── TestProject.xcworkspace │ └── contents.xcworkspacedata │ └── Tests │ ├── Info.plist │ └── Tests.m ├── 2.x ├── AFHTTPRequestOperationManager+Synchronous.h ├── AFHTTPRequestOperationManager+Synchronous.m └── TestProject │ ├── Podfile │ ├── Podfile.lock │ ├── TestProject.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── xcshareddata │ │ └── xcschemes │ │ └── Tests.xcscheme │ ├── TestProject.xcworkspace │ └── contents.xcworkspacedata │ └── Tests │ ├── Info.plist │ └── Tests.m ├── 3.x ├── AFHTTPSessionManager+Synchronous.h ├── AFHTTPSessionManager+Synchronous.m └── TestProject │ ├── Podfile │ ├── Podfile.lock │ ├── TestProject.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── xcshareddata │ │ └── xcschemes │ │ └── Tests.xcscheme │ ├── TestProject.xcworkspace │ └── contents.xcworkspacedata │ └── Tests │ ├── Info.plist │ └── Tests.m ├── 4.x ├── AFHTTPSessionManager+Synchronous.h ├── AFHTTPSessionManager+Synchronous.m └── TestProject │ ├── Podfile │ ├── Podfile.lock │ ├── TestProject.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ └── xcschemes │ │ └── Tests.xcscheme │ ├── TestProject.xcworkspace │ └── contents.xcworkspacedata │ └── Tests │ ├── Info.plist │ └── Tests.m ├── AFNetworking-Synchronous.podspec ├── CHANGELOG.md ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X 2 | .DS_Store 3 | 4 | # Xcode 5 | build/ 6 | *.pbxuser 7 | !default.pbxuser 8 | *.mode1v3 9 | !default.mode1v3 10 | *.mode2v3 11 | !default.mode2v3 12 | *.perspectivev3 13 | !default.perspectivev3 14 | xcuserdata/ 15 | *.xccheckout 16 | profile 17 | *.moved-aside 18 | DerivedData 19 | *.hmap 20 | *.ipa 21 | 22 | Carthage 23 | 24 | Pods/ 25 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | 3 | osx_image: xcode8.2 4 | 5 | before_install: 6 | - test $CI && curl -sSL https://raw.githubusercontent.com/paulmelnikow/simon-says/master/simon-says -o simon-says && chmod +x simon-says 7 | - ./simon-says prepare 8 | - ./simon-says appledoc install 9 | 10 | before_script: 11 | - (cd 3.x/TestProject && pod install) 12 | - (cd 2.x/TestProject && pod install) 13 | - (cd 1.x/TestProject && pod install) 14 | 15 | script: 16 | - ./simon-says test 3.x/TestProject/TestProject.xcworkspace Tests "platform=iOS Simulator,name=iPhone 7 Plus,OS=10.2" 17 | - ./simon-says test 2.x/TestProject/TestProject.xcworkspace Tests "platform=iOS Simulator,name=iPhone 7 Plus,OS=10.2" 18 | - ./simon-says test 1.x/TestProject/TestProject.xcworkspace Tests "platform=iOS Simulator,name=iPhone 7 Plus,OS=10.2" 19 | - ./simon-says appledoc test 1.x/*.h 2.x/*.h 3.x/*.h 20 | - pod lib lint --allow-warnings 21 | 22 | notifications: 23 | slack: 24 | on_success: change 25 | secure: L60jPEUeOW1Uimwmn6SImasEaFBdsGSqoPEZsamm9poukhBL3FVqtPRmCc8WMCCTvWtr6yRS0N+CnoClPsK3nL9q/ou0jh7OFcQ5Qgkfu5DNYvnoV9/7Yy0izcj9F2ZHVjuLF/R0OXmcuxmjsh3PRMqzSH9FNe6iiSDDOSSXpCA= 26 | -------------------------------------------------------------------------------- /1.x/AFHTTPClient+Synchronous.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) 4 | FOUNDATION_EXPORT NSString * const AFHTTPClientErrorDomain; 5 | FOUNDATION_EXPORT NSInteger const AFHTTPClientBackgroundTaskExpiredError; 6 | #endif 7 | 8 | /** 9 | A minimal category which extends AFHTTPClient to support synchronous requests. 10 | 11 | **This category is for AFNetworking 1.x.** 12 | 13 | Custom subclasses of AFHTTPRequestOperation must override `-responseObject`. 14 | 15 | If a custom subclass does asynchronous processing in its completion blocks, you 16 | may need to use the using-completion-blocks branch. 17 | */ 18 | @interface AFHTTPClient (Synchronous) 19 | 20 | /** 21 | Enqueue an AFHTTPRequestOperation with a GET request. 22 | 23 | @param path The path to be appended to the HTTP client's base URL and used as the 24 | request URL. 25 | @param parameters The parameters to be encoded and appended as the query string for 26 | the request URL. 27 | @param operationPtr The address at which a pointer to the 28 | AFHTTPRequestOperation is placed. 29 | @param outError The address at which a pointer to an error object is placed 30 | when the request operation finishes unsucessfully. 31 | 32 | @return The object created from the response data of the request. 33 | */ 34 | - (id)synchronouslyGetPath:(NSString *)path 35 | parameters:(NSDictionary *)parameters 36 | operation:(AFHTTPRequestOperation *__autoreleasing *)operationPtr 37 | error:(NSError *__autoreleasing *)outError; 38 | 39 | /** 40 | Enqueue an AFHTTPRequestOperation with a POST request. 41 | 42 | @param path The path to be appended to the HTTP client's base URL and used as the 43 | request URL. 44 | @param parameters The parameters to be encoded and set in the request HTTP body. 45 | @param operationPtr The address at which a pointer to the 46 | AFHTTPRequestOperation is placed. 47 | @param outError The address at which a pointer to an error object is placed 48 | when the request operation finishes unsucessfully. 49 | 50 | @return The object created from the response data of the request. 51 | */ 52 | - (id)synchronouslyPostPath:(NSString *)path 53 | parameters:(NSDictionary *)parameters 54 | operation:(AFHTTPRequestOperation *__autoreleasing *)operationPtr 55 | error:(NSError *__autoreleasing *)outError; 56 | 57 | /** 58 | Enqueue an AFHTTPRequestOperation with a PUT request. 59 | 60 | @param path The path to be appended to the HTTP client's base URL and used as the 61 | request URL. 62 | @param parameters The parameters to be encoded and set in the request HTTP body. 63 | @param operationPtr The address at which a pointer to the 64 | AFHTTPRequestOperation is placed. 65 | @param outError The address at which a pointer to an error object is placed 66 | when the request operation finishes unsucessfully. 67 | 68 | @return The object created from the response data of the request. 69 | */ 70 | - (id)synchronouslyPutPath:(NSString *)path 71 | parameters:(NSDictionary *)parameters 72 | operation:(AFHTTPRequestOperation *__autoreleasing *)operationPtr 73 | error:(NSError *__autoreleasing *)outError; 74 | 75 | /** 76 | Enqueue an AFHTTPRequestOperation with a DELETE request. 77 | 78 | @param path The path to be appended to the HTTP client's base URL and used as the 79 | request URL. 80 | @param parameters The parameters to be encoded and appended as the query string for 81 | the request URL. 82 | @param operationPtr The address at which a pointer to the 83 | AFHTTPRequestOperation is placed. 84 | @param outError The address at which a pointer to an error object is placed 85 | when the request operation finishes unsucessfully. 86 | 87 | @return The object created from the response data of the request. 88 | */ 89 | - (id)synchronouslyDeletePath:(NSString *)path 90 | parameters:(NSDictionary *)parameters 91 | operation:(AFHTTPRequestOperation *__autoreleasing *)operationPtr 92 | error:(NSError *__autoreleasing *)outError; 93 | 94 | /** 95 | Enqueue an AFHTTPRequestOperation with a PATCH request. 96 | 97 | @param path The path to be appended to the HTTP client's base URL and used as the 98 | request URL. 99 | @param parameters The parameters to be encoded and set in the request HTTP body. 100 | @param operationPtr The address at which a pointer to the 101 | AFHTTPRequestOperation is placed. 102 | @param outError The address at which a pointer to an error object is placed 103 | when the request operation finishes unsucessfully. 104 | 105 | @return The object created from the response data of the request. 106 | */ 107 | - (id)synchronouslyPatchPath:(NSString *)path 108 | parameters:(NSDictionary *)parameters 109 | operation:(AFHTTPRequestOperation *__autoreleasing *)operationPtr 110 | error:(NSError *__autoreleasing *)outError; 111 | 112 | /** 113 | Enqueue an AFHTTPRequestOperation with a request for the given HTTP method. 114 | 115 | @param method The HTTP method. 116 | @param path The path to be appended to the HTTP client's base URL and used as the 117 | request URL. 118 | @param parameters The parameters to be encoded and set in the request HTTP body. 119 | @param operationPtr The address at which a pointer to the 120 | AFHTTPRequestOperation is placed. 121 | @param outError The address at which a pointer to an error object is placed 122 | when the request operation finishes unsucessfully. 123 | 124 | @return The object created from the response data of the request. 125 | */ 126 | - (id)synchronouslyPerformMethod:(NSString *)method 127 | path:(NSString *)path 128 | parameters:(NSDictionary *)parameters 129 | operation:(AFHTTPRequestOperation *__autoreleasing *)operationPtr 130 | error:(NSError *__autoreleasing *)outError; 131 | 132 | @end 133 | -------------------------------------------------------------------------------- /1.x/AFHTTPClient+Synchronous.m: -------------------------------------------------------------------------------- 1 | #import "AFHTTPClient+Synchronous.h" 2 | #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) 3 | #import 4 | #elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED) 5 | #import 6 | #endif 7 | #import "AFHTTPRequestOperation+ResponseObject.h" 8 | 9 | NSString * const AFHTTPClientErrorDomain = @"com.alamofire.httpclient"; 10 | NSInteger const AFHTTPClientBackgroundTaskExpiredError = -1001; 11 | 12 | @implementation AFHTTPClient (Synchronous) 13 | 14 | - (id)synchronouslyPerformMethod:(NSString *)method 15 | path:(NSString *)path 16 | parameters:(NSDictionary *)parameters 17 | operation:(AFHTTPRequestOperation *__autoreleasing *)operationPtr 18 | error:(NSError *__autoreleasing *)outError 19 | { 20 | NSURLRequest *request = [self requestWithMethod:method path:path parameters:parameters]; 21 | AFHTTPRequestOperation *op = [self HTTPRequestOperationWithRequest:request success:nil failure:nil]; 22 | 23 | #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) 24 | // By registering the operation as a long-running background task, if the app enters 25 | // background, it is more likely to complete. However, it does not guarantee that the 26 | // method will return. 27 | // 28 | // When a background task is about to run out of time, the expiration handler is run 29 | // on the main queue. 30 | // 31 | // Using this feature while blocking the main thread causes a deadlock. Then the 32 | // operation never gets to call `endBackgroundTask:` and the system terminates the 33 | // app. Refer to the docs for 34 | // `-[AFURLConnectionOperation setShouldExecuteAsBackgroundTaskWithExpirationHandler:` 35 | // and `-[NSOperation beginBackgroundTaskWithExpirationHandler:]` 36 | 37 | if (![NSThread isMainThread]) { 38 | [op setShouldExecuteAsBackgroundTaskWithExpirationHandler:^(void) { 39 | if (outError) *outError = 40 | [NSError errorWithDomain:AFHTTPClientErrorDomain 41 | code:AFHTTPClientBackgroundTaskExpiredError 42 | userInfo:@{ NSLocalizedDescriptionKey: @"Background operation time expired" }]; 43 | }]; 44 | // At this point this thread may wake up but probably isn't guaranteed to do so. 45 | } 46 | #endif 47 | 48 | [op start]; 49 | [op waitUntilFinished]; 50 | 51 | if (operationPtr != nil) *operationPtr = op; 52 | if (outError != nil) *outError = [op error]; 53 | return [op responseObject]; 54 | } 55 | 56 | - (id)synchronouslyGetPath:(NSString *)path 57 | parameters:(NSDictionary *)parameters 58 | operation:(AFHTTPRequestOperation *__autoreleasing *)operationPtr 59 | error:(NSError *__autoreleasing *)outError 60 | { 61 | return [self synchronouslyPerformMethod:@"GET" path:path parameters:parameters operation:operationPtr error:outError]; 62 | } 63 | 64 | - (id)synchronouslyPostPath:(NSString *)path 65 | parameters:(NSDictionary *)parameters 66 | operation:(AFHTTPRequestOperation *__autoreleasing *) operationPtr 67 | error:(NSError *__autoreleasing *) outError 68 | { 69 | return [self synchronouslyPerformMethod:@"POST" path:path parameters:parameters operation:operationPtr error:outError]; 70 | } 71 | 72 | - (id)synchronouslyPutPath:(NSString *)path 73 | parameters:(NSDictionary *)parameters 74 | operation:(AFHTTPRequestOperation *__autoreleasing *) operationPtr 75 | error:(NSError *__autoreleasing *) outError 76 | { 77 | return [self synchronouslyPerformMethod:@"PUT" path:path parameters:parameters operation:operationPtr error:outError]; 78 | } 79 | 80 | - (id)synchronouslyDeletePath:(NSString *)path 81 | parameters:(NSDictionary *)parameters 82 | operation:(AFHTTPRequestOperation *__autoreleasing *) operationPtr 83 | error:(NSError *__autoreleasing *) outError 84 | { 85 | return [self synchronouslyPerformMethod:@"DELETE" path:path parameters:parameters operation:operationPtr error:outError]; 86 | } 87 | 88 | - (id)synchronouslyPatchPath:(NSString *)path 89 | parameters:(NSDictionary *)parameters 90 | operation:(AFHTTPRequestOperation *__autoreleasing *) operationPtr 91 | error:(NSError *__autoreleasing *) outError 92 | { 93 | return [self synchronouslyPerformMethod:@"PATCH" path:path parameters:parameters operation:operationPtr error:outError]; 94 | } 95 | 96 | @end 97 | -------------------------------------------------------------------------------- /1.x/AFHTTPRequestOperation+ResponseObject.h: -------------------------------------------------------------------------------- 1 | #import 2 | #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) 3 | @class UIImage; 4 | #elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED) 5 | @class NSImage; 6 | #endif 7 | 8 | /** 9 | Category definining a method on `AFHTTPRequestOperation` which subclasses 10 | should use to return response data. 11 | 12 | **This category is for AFNetworking 1.x.** 13 | */ 14 | @interface AFHTTPRequestOperation (ResponseObject) 15 | 16 | /** 17 | Return an object derived from the response data. 18 | 19 | Subclasses must override this method, and may redeclare it to indicate its 20 | type. 21 | 22 | If a custom subclass does asynchronous processing in its completion blocks, 23 | you may need to use the using-completion-blocks branch. 24 | */ 25 | - (id) responseObject; 26 | 27 | @end 28 | 29 | /** 30 | Implementation of the `ResponseObject` categor for `AFXMLRequestOperation`. 31 | 32 | **This category is for AFNetworking 1.x.** 33 | */ 34 | @interface AFXMLRequestOperation (ResponseObject) 35 | 36 | /** 37 | An `NSXMLParser` object constructed from the response data. 38 | */ 39 | - (NSXMLParser *) responseObject; 40 | 41 | @end 42 | 43 | /** 44 | Implementation of the `ResponseObject` categor for `AFImageRequestOperation`. 45 | 46 | **This category is for AFNetworking 1.x.** 47 | 48 | If you're using the `processingBlock`, which contains essential processing in 49 | the completion handler, or your subclass performs other asynchronous 50 | processing in the completion handler, use the version in the 51 | using-completion-blocks branch. 52 | */ 53 | @interface AFImageRequestOperation (ResponseObject) 54 | 55 | /** 56 | An image constructed from the response data. 57 | */ 58 | #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) 59 | - (UIImage *) responseObject; 60 | #elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED) 61 | - (NSImage *) responseObject; 62 | #endif 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /1.x/AFHTTPRequestOperation+ResponseObject.m: -------------------------------------------------------------------------------- 1 | #import "AFHTTPRequestOperation+ResponseObject.h" 2 | #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) 3 | #import 4 | #elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED) 5 | #import 6 | #endif 7 | 8 | @implementation AFHTTPRequestOperation (ResponseObject) 9 | 10 | - (id) responseObject { return [self responseData]; } 11 | 12 | @end 13 | 14 | @implementation AFJSONRequestOperation (ResponseObject) 15 | 16 | - (id) responseObject { return [self responseJSON]; } 17 | 18 | @end 19 | 20 | @implementation AFXMLRequestOperation (ResponseObject) 21 | 22 | - (NSXMLParser *) responseObject { return [self responseXMLParser]; } 23 | 24 | @end 25 | 26 | @implementation AFImageRequestOperation (ResponseObject) 27 | 28 | - (id) responseObject { return [self responseImage]; } 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /1.x/TestProject/Podfile: -------------------------------------------------------------------------------- 1 | use_frameworks! 2 | target 'Tests' do 3 | pod 'AFNetworking-Synchronous/1.x', :path => '../../' 4 | 5 | pod 'Specta' 6 | pod 'Expecta' 7 | end 8 | 9 | -------------------------------------------------------------------------------- /1.x/TestProject/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - AFNetworking (1.3.4) 3 | - AFNetworking-Synchronous/1.x (2.0.0-dev): 4 | - AFNetworking (~> 1.0) 5 | - Expecta (1.0.5) 6 | - Specta (1.0.6) 7 | 8 | DEPENDENCIES: 9 | - AFNetworking-Synchronous/1.x (from `../../`) 10 | - Expecta 11 | - Specta 12 | 13 | EXTERNAL SOURCES: 14 | AFNetworking-Synchronous: 15 | :path: "../../" 16 | 17 | SPEC CHECKSUMS: 18 | AFNetworking: cf8e418e16f0c9c7e5c3150d019a3c679d015018 19 | AFNetworking-Synchronous: 61cdd7c4526f35b6e964b9b6f60562e4e5a75a5d 20 | Expecta: e1c022fcd33910b6be89c291d2775b3fe27a89fe 21 | Specta: f506f3a8361de16bc0dcf3b17b75e269072ba465 22 | 23 | PODFILE CHECKSUM: cbb9fb0bd181d07cc245085afeb8bbc4e2447322 24 | 25 | COCOAPODS: 1.2.0 26 | -------------------------------------------------------------------------------- /1.x/TestProject/TestProject.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 2ECD212AF18571ED7786CC69 /* Pods_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6DCCCE739AB09E4629043F98 /* Pods_Tests.framework */; }; 11 | 9E9BDAA81E7982F10031B02C /* Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 9E9BDAA71E7982F10031B02C /* Tests.m */; }; 12 | /* End PBXBuildFile section */ 13 | 14 | /* Begin PBXFileReference section */ 15 | 38550BECD10EC4FF6335C28C /* Pods-Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-Tests/Pods-Tests.release.xcconfig"; sourceTree = ""; }; 16 | 6DCCCE739AB09E4629043F98 /* Pods_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 17 | 9E9BDAA41E7982F10031B02C /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 18 | 9E9BDAA71E7982F10031B02C /* Tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Tests.m; sourceTree = ""; }; 19 | 9E9BDAA91E7982F10031B02C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 20 | F715685C59413BB311540C7B /* Pods-Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Tests/Pods-Tests.debug.xcconfig"; sourceTree = ""; }; 21 | /* End PBXFileReference section */ 22 | 23 | /* Begin PBXFrameworksBuildPhase section */ 24 | 9E9BDAA11E7982F10031B02C /* Frameworks */ = { 25 | isa = PBXFrameworksBuildPhase; 26 | buildActionMask = 2147483647; 27 | files = ( 28 | 2ECD212AF18571ED7786CC69 /* Pods_Tests.framework in Frameworks */, 29 | ); 30 | runOnlyForDeploymentPostprocessing = 0; 31 | }; 32 | /* End PBXFrameworksBuildPhase section */ 33 | 34 | /* Begin PBXGroup section */ 35 | 854103492BD3D5298BD37401 /* Pods */ = { 36 | isa = PBXGroup; 37 | children = ( 38 | F715685C59413BB311540C7B /* Pods-Tests.debug.xcconfig */, 39 | 38550BECD10EC4FF6335C28C /* Pods-Tests.release.xcconfig */, 40 | ); 41 | name = Pods; 42 | sourceTree = ""; 43 | }; 44 | 9C5B2A581FCB18A2F3F9F534 /* Frameworks */ = { 45 | isa = PBXGroup; 46 | children = ( 47 | 6DCCCE739AB09E4629043F98 /* Pods_Tests.framework */, 48 | ); 49 | name = Frameworks; 50 | sourceTree = ""; 51 | }; 52 | 9E9BDA991E7981A60031B02C = { 53 | isa = PBXGroup; 54 | children = ( 55 | 9E9BDAA61E7982F10031B02C /* Tests */, 56 | 9E9BDAA51E7982F10031B02C /* Products */, 57 | 854103492BD3D5298BD37401 /* Pods */, 58 | 9C5B2A581FCB18A2F3F9F534 /* Frameworks */, 59 | ); 60 | sourceTree = ""; 61 | }; 62 | 9E9BDAA51E7982F10031B02C /* Products */ = { 63 | isa = PBXGroup; 64 | children = ( 65 | 9E9BDAA41E7982F10031B02C /* Tests.xctest */, 66 | ); 67 | name = Products; 68 | sourceTree = ""; 69 | }; 70 | 9E9BDAA61E7982F10031B02C /* Tests */ = { 71 | isa = PBXGroup; 72 | children = ( 73 | 9E9BDAA71E7982F10031B02C /* Tests.m */, 74 | 9E9BDAA91E7982F10031B02C /* Info.plist */, 75 | ); 76 | path = Tests; 77 | sourceTree = ""; 78 | }; 79 | /* End PBXGroup section */ 80 | 81 | /* Begin PBXNativeTarget section */ 82 | 9E9BDAA31E7982F10031B02C /* Tests */ = { 83 | isa = PBXNativeTarget; 84 | buildConfigurationList = 9E9BDAAC1E7982F10031B02C /* Build configuration list for PBXNativeTarget "Tests" */; 85 | buildPhases = ( 86 | B6E96878860E900085C2F4D0 /* [CP] Check Pods Manifest.lock */, 87 | 9E9BDAA01E7982F10031B02C /* Sources */, 88 | 9E9BDAA11E7982F10031B02C /* Frameworks */, 89 | 9E9BDAA21E7982F10031B02C /* Resources */, 90 | 08BD843668D5CB0F7D21D38C /* [CP] Embed Pods Frameworks */, 91 | EC436F7897D37E7B0AEA4FAD /* [CP] Copy Pods Resources */, 92 | ); 93 | buildRules = ( 94 | ); 95 | dependencies = ( 96 | ); 97 | name = Tests; 98 | productName = Tests; 99 | productReference = 9E9BDAA41E7982F10031B02C /* Tests.xctest */; 100 | productType = "com.apple.product-type.bundle.unit-test"; 101 | }; 102 | /* End PBXNativeTarget section */ 103 | 104 | /* Begin PBXProject section */ 105 | 9E9BDA9A1E7981A60031B02C /* Project object */ = { 106 | isa = PBXProject; 107 | attributes = { 108 | LastUpgradeCheck = 0820; 109 | TargetAttributes = { 110 | 9E9BDAA31E7982F10031B02C = { 111 | CreatedOnToolsVersion = 8.2.1; 112 | ProvisioningStyle = Automatic; 113 | }; 114 | }; 115 | }; 116 | buildConfigurationList = 9E9BDA9D1E7981A60031B02C /* Build configuration list for PBXProject "TestProject" */; 117 | compatibilityVersion = "Xcode 3.2"; 118 | developmentRegion = English; 119 | hasScannedForEncodings = 0; 120 | knownRegions = ( 121 | en, 122 | ); 123 | mainGroup = 9E9BDA991E7981A60031B02C; 124 | productRefGroup = 9E9BDAA51E7982F10031B02C /* Products */; 125 | projectDirPath = ""; 126 | projectRoot = ""; 127 | targets = ( 128 | 9E9BDAA31E7982F10031B02C /* Tests */, 129 | ); 130 | }; 131 | /* End PBXProject section */ 132 | 133 | /* Begin PBXResourcesBuildPhase section */ 134 | 9E9BDAA21E7982F10031B02C /* Resources */ = { 135 | isa = PBXResourcesBuildPhase; 136 | buildActionMask = 2147483647; 137 | files = ( 138 | ); 139 | runOnlyForDeploymentPostprocessing = 0; 140 | }; 141 | /* End PBXResourcesBuildPhase section */ 142 | 143 | /* Begin PBXShellScriptBuildPhase section */ 144 | 08BD843668D5CB0F7D21D38C /* [CP] Embed Pods Frameworks */ = { 145 | isa = PBXShellScriptBuildPhase; 146 | buildActionMask = 2147483647; 147 | files = ( 148 | ); 149 | inputPaths = ( 150 | ); 151 | name = "[CP] Embed Pods Frameworks"; 152 | outputPaths = ( 153 | ); 154 | runOnlyForDeploymentPostprocessing = 0; 155 | shellPath = /bin/sh; 156 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Tests/Pods-Tests-frameworks.sh\"\n"; 157 | showEnvVarsInLog = 0; 158 | }; 159 | B6E96878860E900085C2F4D0 /* [CP] Check Pods Manifest.lock */ = { 160 | isa = PBXShellScriptBuildPhase; 161 | buildActionMask = 2147483647; 162 | files = ( 163 | ); 164 | inputPaths = ( 165 | ); 166 | name = "[CP] Check Pods Manifest.lock"; 167 | outputPaths = ( 168 | ); 169 | runOnlyForDeploymentPostprocessing = 0; 170 | shellPath = /bin/sh; 171 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; 172 | showEnvVarsInLog = 0; 173 | }; 174 | EC436F7897D37E7B0AEA4FAD /* [CP] Copy Pods Resources */ = { 175 | isa = PBXShellScriptBuildPhase; 176 | buildActionMask = 2147483647; 177 | files = ( 178 | ); 179 | inputPaths = ( 180 | ); 181 | name = "[CP] Copy Pods Resources"; 182 | outputPaths = ( 183 | ); 184 | runOnlyForDeploymentPostprocessing = 0; 185 | shellPath = /bin/sh; 186 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Tests/Pods-Tests-resources.sh\"\n"; 187 | showEnvVarsInLog = 0; 188 | }; 189 | /* End PBXShellScriptBuildPhase section */ 190 | 191 | /* Begin PBXSourcesBuildPhase section */ 192 | 9E9BDAA01E7982F10031B02C /* Sources */ = { 193 | isa = PBXSourcesBuildPhase; 194 | buildActionMask = 2147483647; 195 | files = ( 196 | 9E9BDAA81E7982F10031B02C /* Tests.m in Sources */, 197 | ); 198 | runOnlyForDeploymentPostprocessing = 0; 199 | }; 200 | /* End PBXSourcesBuildPhase section */ 201 | 202 | /* Begin XCBuildConfiguration section */ 203 | 9E9BDA9E1E7981A60031B02C /* Debug */ = { 204 | isa = XCBuildConfiguration; 205 | buildSettings = { 206 | CLANG_WARN_BOOL_CONVERSION = YES; 207 | CLANG_WARN_CONSTANT_CONVERSION = YES; 208 | CLANG_WARN_EMPTY_BODY = YES; 209 | CLANG_WARN_ENUM_CONVERSION = YES; 210 | CLANG_WARN_INFINITE_RECURSION = YES; 211 | CLANG_WARN_INT_CONVERSION = YES; 212 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 213 | CLANG_WARN_UNREACHABLE_CODE = YES; 214 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 215 | ENABLE_STRICT_OBJC_MSGSEND = YES; 216 | GCC_NO_COMMON_BLOCKS = YES; 217 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 218 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 219 | GCC_WARN_UNDECLARED_SELECTOR = YES; 220 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 221 | GCC_WARN_UNUSED_FUNCTION = YES; 222 | GCC_WARN_UNUSED_VARIABLE = YES; 223 | }; 224 | name = Debug; 225 | }; 226 | 9E9BDA9F1E7981A60031B02C /* Release */ = { 227 | isa = XCBuildConfiguration; 228 | buildSettings = { 229 | CLANG_WARN_BOOL_CONVERSION = YES; 230 | CLANG_WARN_CONSTANT_CONVERSION = YES; 231 | CLANG_WARN_EMPTY_BODY = YES; 232 | CLANG_WARN_ENUM_CONVERSION = YES; 233 | CLANG_WARN_INFINITE_RECURSION = YES; 234 | CLANG_WARN_INT_CONVERSION = YES; 235 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 236 | CLANG_WARN_UNREACHABLE_CODE = YES; 237 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 238 | ENABLE_STRICT_OBJC_MSGSEND = YES; 239 | GCC_NO_COMMON_BLOCKS = YES; 240 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 241 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 242 | GCC_WARN_UNDECLARED_SELECTOR = YES; 243 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 244 | GCC_WARN_UNUSED_FUNCTION = YES; 245 | GCC_WARN_UNUSED_VARIABLE = YES; 246 | }; 247 | name = Release; 248 | }; 249 | 9E9BDAAA1E7982F10031B02C /* Debug */ = { 250 | isa = XCBuildConfiguration; 251 | baseConfigurationReference = F715685C59413BB311540C7B /* Pods-Tests.debug.xcconfig */; 252 | buildSettings = { 253 | ALWAYS_SEARCH_USER_PATHS = NO; 254 | CLANG_ANALYZER_NONNULL = YES; 255 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 256 | CLANG_CXX_LIBRARY = "libc++"; 257 | CLANG_ENABLE_MODULES = YES; 258 | CLANG_ENABLE_OBJC_ARC = YES; 259 | CLANG_WARN_BOOL_CONVERSION = YES; 260 | CLANG_WARN_CONSTANT_CONVERSION = YES; 261 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 262 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 263 | CLANG_WARN_EMPTY_BODY = YES; 264 | CLANG_WARN_ENUM_CONVERSION = YES; 265 | CLANG_WARN_INFINITE_RECURSION = YES; 266 | CLANG_WARN_INT_CONVERSION = YES; 267 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 268 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 269 | CLANG_WARN_UNREACHABLE_CODE = YES; 270 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 271 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 272 | COPY_PHASE_STRIP = NO; 273 | DEBUG_INFORMATION_FORMAT = dwarf; 274 | ENABLE_STRICT_OBJC_MSGSEND = YES; 275 | ENABLE_TESTABILITY = YES; 276 | GCC_C_LANGUAGE_STANDARD = gnu99; 277 | GCC_DYNAMIC_NO_PIC = NO; 278 | GCC_NO_COMMON_BLOCKS = YES; 279 | GCC_OPTIMIZATION_LEVEL = 0; 280 | GCC_PREPROCESSOR_DEFINITIONS = ( 281 | "DEBUG=1", 282 | "$(inherited)", 283 | ); 284 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 285 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 286 | GCC_WARN_UNDECLARED_SELECTOR = YES; 287 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 288 | GCC_WARN_UNUSED_FUNCTION = YES; 289 | GCC_WARN_UNUSED_VARIABLE = YES; 290 | INFOPLIST_FILE = Tests/Info.plist; 291 | IPHONEOS_DEPLOYMENT_TARGET = 10.2; 292 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 293 | MTL_ENABLE_DEBUG_INFO = YES; 294 | ONLY_ACTIVE_ARCH = YES; 295 | PRODUCT_BUNDLE_IDENTIFIER = com.paulmelnikow.Tests; 296 | PRODUCT_NAME = "$(TARGET_NAME)"; 297 | SDKROOT = iphoneos; 298 | }; 299 | name = Debug; 300 | }; 301 | 9E9BDAAB1E7982F10031B02C /* Release */ = { 302 | isa = XCBuildConfiguration; 303 | baseConfigurationReference = 38550BECD10EC4FF6335C28C /* Pods-Tests.release.xcconfig */; 304 | buildSettings = { 305 | ALWAYS_SEARCH_USER_PATHS = NO; 306 | CLANG_ANALYZER_NONNULL = YES; 307 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 308 | CLANG_CXX_LIBRARY = "libc++"; 309 | CLANG_ENABLE_MODULES = YES; 310 | CLANG_ENABLE_OBJC_ARC = YES; 311 | CLANG_WARN_BOOL_CONVERSION = YES; 312 | CLANG_WARN_CONSTANT_CONVERSION = YES; 313 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 314 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 315 | CLANG_WARN_EMPTY_BODY = YES; 316 | CLANG_WARN_ENUM_CONVERSION = YES; 317 | CLANG_WARN_INFINITE_RECURSION = YES; 318 | CLANG_WARN_INT_CONVERSION = YES; 319 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 320 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 321 | CLANG_WARN_UNREACHABLE_CODE = YES; 322 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 323 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 324 | COPY_PHASE_STRIP = NO; 325 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 326 | ENABLE_NS_ASSERTIONS = NO; 327 | ENABLE_STRICT_OBJC_MSGSEND = YES; 328 | GCC_C_LANGUAGE_STANDARD = gnu99; 329 | GCC_NO_COMMON_BLOCKS = YES; 330 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 331 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 332 | GCC_WARN_UNDECLARED_SELECTOR = YES; 333 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 334 | GCC_WARN_UNUSED_FUNCTION = YES; 335 | GCC_WARN_UNUSED_VARIABLE = YES; 336 | INFOPLIST_FILE = Tests/Info.plist; 337 | IPHONEOS_DEPLOYMENT_TARGET = 10.2; 338 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 339 | MTL_ENABLE_DEBUG_INFO = NO; 340 | PRODUCT_BUNDLE_IDENTIFIER = com.paulmelnikow.Tests; 341 | PRODUCT_NAME = "$(TARGET_NAME)"; 342 | SDKROOT = iphoneos; 343 | VALIDATE_PRODUCT = YES; 344 | }; 345 | name = Release; 346 | }; 347 | /* End XCBuildConfiguration section */ 348 | 349 | /* Begin XCConfigurationList section */ 350 | 9E9BDA9D1E7981A60031B02C /* Build configuration list for PBXProject "TestProject" */ = { 351 | isa = XCConfigurationList; 352 | buildConfigurations = ( 353 | 9E9BDA9E1E7981A60031B02C /* Debug */, 354 | 9E9BDA9F1E7981A60031B02C /* Release */, 355 | ); 356 | defaultConfigurationIsVisible = 0; 357 | defaultConfigurationName = Release; 358 | }; 359 | 9E9BDAAC1E7982F10031B02C /* Build configuration list for PBXNativeTarget "Tests" */ = { 360 | isa = XCConfigurationList; 361 | buildConfigurations = ( 362 | 9E9BDAAA1E7982F10031B02C /* Debug */, 363 | 9E9BDAAB1E7982F10031B02C /* Release */, 364 | ); 365 | defaultConfigurationIsVisible = 0; 366 | defaultConfigurationName = Release; 367 | }; 368 | /* End XCConfigurationList section */ 369 | }; 370 | rootObject = 9E9BDA9A1E7981A60031B02C /* Project object */; 371 | } 372 | -------------------------------------------------------------------------------- /1.x/TestProject/TestProject.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /1.x/TestProject/TestProject.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 14 | 15 | 17 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 39 | 40 | 41 | 42 | 48 | 49 | 51 | 52 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /1.x/TestProject/TestProject.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /1.x/TestProject/Tests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /1.x/TestProject/Tests/Tests.m: -------------------------------------------------------------------------------- 1 | @import Specta; 2 | @import Expecta; 3 | #import "AFNetworking.h" 4 | #import "AFHTTPClient+Synchronous.h" 5 | 6 | @interface Helpers : NSObject 7 | @end 8 | @implementation Helpers 9 | + (NSURL *) baseURL { 10 | NSDictionary *environment = [[NSProcessInfo processInfo] environment]; 11 | return [NSURL URLWithString:environment[@"HTTPBIN_BASE_URL"] ?: @"https://httpbin.org"]; 12 | } 13 | 14 | + (AFHTTPClient *) client { 15 | AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:self.baseURL]; 16 | [client registerHTTPOperationClass:[AFJSONRequestOperation class]]; 17 | [client setDefaultHeader:@"Accept" value:@"application/json; version=1.0;"]; 18 | return client; 19 | } 20 | @end 21 | 22 | SpecBegin(AFNetworking1x) 23 | 24 | describe(@"AFHTTPClient+Synchronous", ^{ 25 | 26 | __block NSError *error; 27 | __block AFHTTPClient *client; 28 | beforeEach(^{ 29 | client = [Helpers client]; 30 | error = nil; 31 | }); 32 | 33 | describe(@"For a successful request", ^{ 34 | 35 | it(@"can GET", ^{ 36 | // Execute. 37 | id result = [client synchronouslyGetPath:@"get" 38 | parameters:nil 39 | operation:NULL 40 | error:&error]; 41 | // Confidence check. 42 | expect(error).to.beNil(); 43 | 44 | // Test. 45 | expect(result).notTo.beNil(); 46 | }); 47 | 48 | it(@"passes parameters to the request", ^{ 49 | // Setup. 50 | NSDictionary *params = @{@"foo": @"bar", @"baz": @"123"}; 51 | 52 | // Execute. 53 | id result = [client synchronouslyGetPath:@"get" 54 | parameters:params 55 | operation:NULL 56 | error:&error]; 57 | // Confidence check. 58 | expect(error).to.beNil(); 59 | expect(result).notTo.beNil(); 60 | 61 | // Test. 62 | expect(result[@"args"]).to.equal(params); 63 | }); 64 | 65 | it(@"sets the operation pointer", ^{ 66 | // Setup. 67 | AFHTTPRequestOperation *operation = nil; 68 | 69 | // Execute. 70 | id result = [client synchronouslyGetPath:@"get" 71 | parameters:nil 72 | operation:&operation 73 | error:&error]; 74 | // Confidence check. 75 | expect(result).notTo.beNil(); 76 | 77 | // Test. 78 | expect(operation).to.beInstanceOf([AFJSONRequestOperation class]); 79 | }); 80 | }); 81 | 82 | describe(@"For a failed request", ^{ 83 | 84 | it(@"returns nil and sets the error pointer", ^{ 85 | // Execute. 86 | id result = [client synchronouslyGetPath:@"status/503" 87 | parameters:nil 88 | operation:NULL 89 | error:&error]; 90 | // Test. 91 | expect(result).to.beNil(); 92 | expect(error).to.beInstanceOf([NSError class]); 93 | expect(error.localizedDescription).to. 94 | equal(@"Expected status code in (200-299), got 503"); 95 | }); 96 | 97 | }); 98 | 99 | }); 100 | 101 | SpecEnd 102 | -------------------------------------------------------------------------------- /2.x/AFHTTPRequestOperationManager+Synchronous.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | /** 4 | A minimal category which extends AFHTTPRequestOperationManager to support 5 | synchronous requests. 6 | 7 | **This category is for AFNetworking 2.x.** 8 | */ 9 | @interface AFHTTPRequestOperationManager (Synchronous) 10 | 11 | /** 12 | Creates and runs an AFHTTPRequestOperation with a GET request. 13 | 14 | @param URLString The URL string used to create the request URL. 15 | @param parameters The parameters to be encoded according to the client 16 | request serializer. 17 | @param operationPtr The address at which a pointer to the 18 | AFHTTPRequestOperation is placed. 19 | @param outError The address at which a pointer to an error object is placed 20 | when the request operation finishes unsucessfully. 21 | 22 | @return The response object created by the client response serializer. 23 | */ 24 | - (id)syncGET:(NSString *)URLString 25 | parameters:(NSDictionary *)parameters 26 | operation:(AFHTTPRequestOperation *__autoreleasing *)operationPtr 27 | error:(NSError *__autoreleasing *)outError; 28 | 29 | /** 30 | Creates and runs an AFHTTPRequestOperation with a POST request. 31 | 32 | @param URLString The URL string used to create the request URL. 33 | @param parameters The parameters to be encoded according to the client 34 | request serializer. 35 | @param operationPtr The address at which a pointer to the 36 | AFHTTPRequestOperation is placed. 37 | @param outError The address at which a pointer to an error object is placed 38 | when the request operation finishes unsucessfully. 39 | 40 | @return The response object created by the client response serializer. 41 | */ 42 | - (id)syncPOST:(NSString *)URLString 43 | parameters:(NSDictionary *)parameters 44 | operation:(AFHTTPRequestOperation *__autoreleasing *) operationPtr 45 | error:(NSError *__autoreleasing *) outError; 46 | 47 | /** 48 | Creates and runs an AFHTTPRequestOperation with a PUT request. 49 | 50 | @param URLString The URL string used to create the request URL. 51 | @param parameters The parameters to be encoded according to the client 52 | request serializer. 53 | @param operationPtr The address at which a pointer to the 54 | AFHTTPRequestOperation is placed. 55 | @param outError The address at which a pointer to an error object is placed 56 | when the request operation finishes unsucessfully. 57 | 58 | @return The response object created by the client response serializer. 59 | */ 60 | - (id)syncPUT:(NSString *)URLString 61 | parameters:(NSDictionary *)parameters 62 | operation:(AFHTTPRequestOperation *__autoreleasing *) operationPtr 63 | error:(NSError *__autoreleasing *) outError; 64 | /** 65 | Creates and runs an AFHTTPRequestOperation with a DELETE request. 66 | 67 | @param URLString The URL string used to create the request URL. 68 | @param parameters The parameters to be encoded according to the client 69 | request serializer. 70 | @param operationPtr The address at which a pointer to the 71 | AFHTTPRequestOperation is placed. 72 | @param outError The address at which a pointer to an error object is placed 73 | when the request operation finishes unsucessfully. 74 | 75 | @return The response object created by the client response serializer. 76 | */ 77 | - (id)syncDELETE:(NSString *)URLString 78 | parameters:(NSDictionary *)parameters 79 | operation:(AFHTTPRequestOperation *__autoreleasing *) operationPtr 80 | error:(NSError *__autoreleasing *) outError; 81 | 82 | /** 83 | Creates and runs an AFHTTPRequestOperation with a PATCH request. 84 | 85 | @param URLString The URL string used to create the request URL. 86 | @param parameters The parameters to be encoded according to the client 87 | request serializer. 88 | @param operationPtr The address at which a pointer to the 89 | AFHTTPRequestOperation is placed. 90 | @param outError The address at which a pointer to an error object is placed 91 | when the request operation finishes unsucessfully. 92 | 93 | @return The response object created by the client response serializer. 94 | */ 95 | - (id)syncPATCH:(NSString *)URLString 96 | parameters:(NSDictionary *)parameters 97 | operation:(AFHTTPRequestOperation *__autoreleasing *) operationPtr 98 | error:(NSError *__autoreleasing *) outError; 99 | 100 | /** 101 | Enqueue an AFHTTPRequestOperation with a request for the given HTTP method. 102 | 103 | @param method The HTTP method. 104 | @param URLString The URL string used to create the request URL. 105 | @param parameters The parameters to be encoded and set in the request HTTP body. 106 | @param operationPtr The address at which a pointer to the 107 | AFHTTPRequestOperation is placed. 108 | @param outError The address at which a pointer to an error object is placed 109 | when the request operation finishes unsucessfully. 110 | 111 | @return The object created from the response data of the request. 112 | */ 113 | - (id)synchronouslyPerformMethod:(NSString *)method 114 | URLString:(NSString *)URLString 115 | parameters:(NSDictionary *)parameters 116 | operation:(AFHTTPRequestOperation *__autoreleasing *)operationPtr 117 | error:(NSError *__autoreleasing *)outError; 118 | 119 | @end 120 | -------------------------------------------------------------------------------- /2.x/AFHTTPRequestOperationManager+Synchronous.m: -------------------------------------------------------------------------------- 1 | #import "AFHTTPRequestOperationManager+Synchronous.h" 2 | 3 | @implementation AFHTTPRequestOperationManager (Synchronous) 4 | 5 | - (id)synchronouslyPerformMethod:(NSString *)method 6 | URLString:(NSString *)URLString 7 | parameters:(NSDictionary *)parameters 8 | operation:(AFHTTPRequestOperation *__autoreleasing *)operationPtr 9 | error:(NSError *__autoreleasing *)outError { 10 | 11 | NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:nil]; 12 | 13 | AFHTTPRequestOperation *op = [self HTTPRequestOperationWithRequest:request 14 | success:nil 15 | failure:nil]; 16 | 17 | [op start]; 18 | [op waitUntilFinished]; 19 | 20 | if (operationPtr != nil) *operationPtr = op; 21 | 22 | // Must call responseObject before checking the error 23 | id responseObject = [op responseObject]; 24 | if (outError != nil) *outError = [op error]; 25 | 26 | return responseObject; 27 | } 28 | 29 | - (id)syncGET:(NSString *)URLString 30 | parameters:(NSDictionary *)parameters 31 | operation:(AFHTTPRequestOperation *__autoreleasing *)operationPtr 32 | error:(NSError *__autoreleasing *)outError 33 | { 34 | return [self synchronouslyPerformMethod:@"GET" URLString:URLString parameters:parameters operation:operationPtr error:outError]; 35 | } 36 | 37 | - (id)syncPOST:(NSString *)URLString 38 | parameters:(NSDictionary *)parameters 39 | operation:(AFHTTPRequestOperation *__autoreleasing *) operationPtr 40 | error:(NSError *__autoreleasing *) outError 41 | { 42 | return [self synchronouslyPerformMethod:@"POST" URLString:URLString parameters:parameters operation:operationPtr error:outError]; 43 | } 44 | 45 | - (id)syncPUT:(NSString *)URLString 46 | parameters:(NSDictionary *)parameters 47 | operation:(AFHTTPRequestOperation *__autoreleasing *) operationPtr 48 | error:(NSError *__autoreleasing *) outError 49 | { 50 | return [self synchronouslyPerformMethod:@"PUT" URLString:URLString parameters:parameters operation:operationPtr error:outError]; 51 | } 52 | 53 | - (id)syncDELETE:(NSString *)URLString 54 | parameters:(NSDictionary *)parameters 55 | operation:(AFHTTPRequestOperation *__autoreleasing *) operationPtr 56 | error:(NSError *__autoreleasing *) outError 57 | { 58 | return [self synchronouslyPerformMethod:@"DELETE" URLString:URLString parameters:parameters operation:operationPtr error:outError]; 59 | } 60 | 61 | - (id)syncPATCH:(NSString *)URLString 62 | parameters:(NSDictionary *)parameters 63 | operation:(AFHTTPRequestOperation *__autoreleasing *) operationPtr 64 | error:(NSError *__autoreleasing *) outError 65 | { 66 | return [self synchronouslyPerformMethod:@"PATCH" URLString:URLString parameters:parameters operation:operationPtr error:outError]; 67 | } 68 | 69 | @end 70 | -------------------------------------------------------------------------------- /2.x/TestProject/Podfile: -------------------------------------------------------------------------------- 1 | use_frameworks! 2 | target 'Tests' do 3 | pod 'AFNetworking-Synchronous/2.x', :path => '../../' 4 | 5 | pod 'Specta' 6 | pod 'Expecta' 7 | end 8 | 9 | -------------------------------------------------------------------------------- /2.x/TestProject/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - AFNetworking (2.6.3): 3 | - AFNetworking/NSURLConnection (= 2.6.3) 4 | - AFNetworking/NSURLSession (= 2.6.3) 5 | - AFNetworking/Reachability (= 2.6.3) 6 | - AFNetworking/Security (= 2.6.3) 7 | - AFNetworking/Serialization (= 2.6.3) 8 | - AFNetworking/UIKit (= 2.6.3) 9 | - AFNetworking-Synchronous/2.x (2.0.0-dev): 10 | - AFNetworking (~> 2.0) 11 | - AFNetworking/NSURLConnection (2.6.3): 12 | - AFNetworking/Reachability 13 | - AFNetworking/Security 14 | - AFNetworking/Serialization 15 | - AFNetworking/NSURLSession (2.6.3): 16 | - AFNetworking/Reachability 17 | - AFNetworking/Security 18 | - AFNetworking/Serialization 19 | - AFNetworking/Reachability (2.6.3) 20 | - AFNetworking/Security (2.6.3) 21 | - AFNetworking/Serialization (2.6.3) 22 | - AFNetworking/UIKit (2.6.3): 23 | - AFNetworking/NSURLConnection 24 | - AFNetworking/NSURLSession 25 | - Expecta (1.0.5) 26 | - Specta (1.0.6) 27 | 28 | DEPENDENCIES: 29 | - AFNetworking-Synchronous/2.x (from `../../`) 30 | - Expecta 31 | - Specta 32 | 33 | EXTERNAL SOURCES: 34 | AFNetworking-Synchronous: 35 | :path: "../../" 36 | 37 | SPEC CHECKSUMS: 38 | AFNetworking: cb8d14a848e831097108418f5d49217339d4eb60 39 | AFNetworking-Synchronous: 61cdd7c4526f35b6e964b9b6f60562e4e5a75a5d 40 | Expecta: e1c022fcd33910b6be89c291d2775b3fe27a89fe 41 | Specta: f506f3a8361de16bc0dcf3b17b75e269072ba465 42 | 43 | PODFILE CHECKSUM: fd480bf1459fe3254430000aabe8990a777f8455 44 | 45 | COCOAPODS: 1.2.0 46 | -------------------------------------------------------------------------------- /2.x/TestProject/TestProject.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 2ECD212AF18571ED7786CC69 /* Pods_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6DCCCE739AB09E4629043F98 /* Pods_Tests.framework */; }; 11 | 9E9BDAA81E7982F10031B02C /* Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 9E9BDAA71E7982F10031B02C /* Tests.m */; }; 12 | /* End PBXBuildFile section */ 13 | 14 | /* Begin PBXFileReference section */ 15 | 38550BECD10EC4FF6335C28C /* Pods-Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-Tests/Pods-Tests.release.xcconfig"; sourceTree = ""; }; 16 | 6DCCCE739AB09E4629043F98 /* Pods_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 17 | 9E9BDAA41E7982F10031B02C /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 18 | 9E9BDAA71E7982F10031B02C /* Tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Tests.m; sourceTree = ""; }; 19 | 9E9BDAA91E7982F10031B02C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 20 | F715685C59413BB311540C7B /* Pods-Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Tests/Pods-Tests.debug.xcconfig"; sourceTree = ""; }; 21 | /* End PBXFileReference section */ 22 | 23 | /* Begin PBXFrameworksBuildPhase section */ 24 | 9E9BDAA11E7982F10031B02C /* Frameworks */ = { 25 | isa = PBXFrameworksBuildPhase; 26 | buildActionMask = 2147483647; 27 | files = ( 28 | 2ECD212AF18571ED7786CC69 /* Pods_Tests.framework in Frameworks */, 29 | ); 30 | runOnlyForDeploymentPostprocessing = 0; 31 | }; 32 | /* End PBXFrameworksBuildPhase section */ 33 | 34 | /* Begin PBXGroup section */ 35 | 854103492BD3D5298BD37401 /* Pods */ = { 36 | isa = PBXGroup; 37 | children = ( 38 | F715685C59413BB311540C7B /* Pods-Tests.debug.xcconfig */, 39 | 38550BECD10EC4FF6335C28C /* Pods-Tests.release.xcconfig */, 40 | ); 41 | name = Pods; 42 | sourceTree = ""; 43 | }; 44 | 9C5B2A581FCB18A2F3F9F534 /* Frameworks */ = { 45 | isa = PBXGroup; 46 | children = ( 47 | 6DCCCE739AB09E4629043F98 /* Pods_Tests.framework */, 48 | ); 49 | name = Frameworks; 50 | sourceTree = ""; 51 | }; 52 | 9E9BDA991E7981A60031B02C = { 53 | isa = PBXGroup; 54 | children = ( 55 | 9E9BDAA61E7982F10031B02C /* Tests */, 56 | 9E9BDAA51E7982F10031B02C /* Products */, 57 | 854103492BD3D5298BD37401 /* Pods */, 58 | 9C5B2A581FCB18A2F3F9F534 /* Frameworks */, 59 | ); 60 | sourceTree = ""; 61 | }; 62 | 9E9BDAA51E7982F10031B02C /* Products */ = { 63 | isa = PBXGroup; 64 | children = ( 65 | 9E9BDAA41E7982F10031B02C /* Tests.xctest */, 66 | ); 67 | name = Products; 68 | sourceTree = ""; 69 | }; 70 | 9E9BDAA61E7982F10031B02C /* Tests */ = { 71 | isa = PBXGroup; 72 | children = ( 73 | 9E9BDAA71E7982F10031B02C /* Tests.m */, 74 | 9E9BDAA91E7982F10031B02C /* Info.plist */, 75 | ); 76 | path = Tests; 77 | sourceTree = ""; 78 | }; 79 | /* End PBXGroup section */ 80 | 81 | /* Begin PBXNativeTarget section */ 82 | 9E9BDAA31E7982F10031B02C /* Tests */ = { 83 | isa = PBXNativeTarget; 84 | buildConfigurationList = 9E9BDAAC1E7982F10031B02C /* Build configuration list for PBXNativeTarget "Tests" */; 85 | buildPhases = ( 86 | B6E96878860E900085C2F4D0 /* [CP] Check Pods Manifest.lock */, 87 | 9E9BDAA01E7982F10031B02C /* Sources */, 88 | 9E9BDAA11E7982F10031B02C /* Frameworks */, 89 | 9E9BDAA21E7982F10031B02C /* Resources */, 90 | 08BD843668D5CB0F7D21D38C /* [CP] Embed Pods Frameworks */, 91 | EC436F7897D37E7B0AEA4FAD /* [CP] Copy Pods Resources */, 92 | ); 93 | buildRules = ( 94 | ); 95 | dependencies = ( 96 | ); 97 | name = Tests; 98 | productName = Tests; 99 | productReference = 9E9BDAA41E7982F10031B02C /* Tests.xctest */; 100 | productType = "com.apple.product-type.bundle.unit-test"; 101 | }; 102 | /* End PBXNativeTarget section */ 103 | 104 | /* Begin PBXProject section */ 105 | 9E9BDA9A1E7981A60031B02C /* Project object */ = { 106 | isa = PBXProject; 107 | attributes = { 108 | LastUpgradeCheck = 0820; 109 | TargetAttributes = { 110 | 9E9BDAA31E7982F10031B02C = { 111 | CreatedOnToolsVersion = 8.2.1; 112 | ProvisioningStyle = Automatic; 113 | }; 114 | }; 115 | }; 116 | buildConfigurationList = 9E9BDA9D1E7981A60031B02C /* Build configuration list for PBXProject "TestProject" */; 117 | compatibilityVersion = "Xcode 3.2"; 118 | developmentRegion = English; 119 | hasScannedForEncodings = 0; 120 | knownRegions = ( 121 | en, 122 | ); 123 | mainGroup = 9E9BDA991E7981A60031B02C; 124 | productRefGroup = 9E9BDAA51E7982F10031B02C /* Products */; 125 | projectDirPath = ""; 126 | projectRoot = ""; 127 | targets = ( 128 | 9E9BDAA31E7982F10031B02C /* Tests */, 129 | ); 130 | }; 131 | /* End PBXProject section */ 132 | 133 | /* Begin PBXResourcesBuildPhase section */ 134 | 9E9BDAA21E7982F10031B02C /* Resources */ = { 135 | isa = PBXResourcesBuildPhase; 136 | buildActionMask = 2147483647; 137 | files = ( 138 | ); 139 | runOnlyForDeploymentPostprocessing = 0; 140 | }; 141 | /* End PBXResourcesBuildPhase section */ 142 | 143 | /* Begin PBXShellScriptBuildPhase section */ 144 | 08BD843668D5CB0F7D21D38C /* [CP] Embed Pods Frameworks */ = { 145 | isa = PBXShellScriptBuildPhase; 146 | buildActionMask = 2147483647; 147 | files = ( 148 | ); 149 | inputPaths = ( 150 | ); 151 | name = "[CP] Embed Pods Frameworks"; 152 | outputPaths = ( 153 | ); 154 | runOnlyForDeploymentPostprocessing = 0; 155 | shellPath = /bin/sh; 156 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Tests/Pods-Tests-frameworks.sh\"\n"; 157 | showEnvVarsInLog = 0; 158 | }; 159 | B6E96878860E900085C2F4D0 /* [CP] Check Pods Manifest.lock */ = { 160 | isa = PBXShellScriptBuildPhase; 161 | buildActionMask = 2147483647; 162 | files = ( 163 | ); 164 | inputPaths = ( 165 | ); 166 | name = "[CP] Check Pods Manifest.lock"; 167 | outputPaths = ( 168 | ); 169 | runOnlyForDeploymentPostprocessing = 0; 170 | shellPath = /bin/sh; 171 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; 172 | showEnvVarsInLog = 0; 173 | }; 174 | EC436F7897D37E7B0AEA4FAD /* [CP] Copy Pods Resources */ = { 175 | isa = PBXShellScriptBuildPhase; 176 | buildActionMask = 2147483647; 177 | files = ( 178 | ); 179 | inputPaths = ( 180 | ); 181 | name = "[CP] Copy Pods Resources"; 182 | outputPaths = ( 183 | ); 184 | runOnlyForDeploymentPostprocessing = 0; 185 | shellPath = /bin/sh; 186 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Tests/Pods-Tests-resources.sh\"\n"; 187 | showEnvVarsInLog = 0; 188 | }; 189 | /* End PBXShellScriptBuildPhase section */ 190 | 191 | /* Begin PBXSourcesBuildPhase section */ 192 | 9E9BDAA01E7982F10031B02C /* Sources */ = { 193 | isa = PBXSourcesBuildPhase; 194 | buildActionMask = 2147483647; 195 | files = ( 196 | 9E9BDAA81E7982F10031B02C /* Tests.m in Sources */, 197 | ); 198 | runOnlyForDeploymentPostprocessing = 0; 199 | }; 200 | /* End PBXSourcesBuildPhase section */ 201 | 202 | /* Begin XCBuildConfiguration section */ 203 | 9E9BDA9E1E7981A60031B02C /* Debug */ = { 204 | isa = XCBuildConfiguration; 205 | buildSettings = { 206 | CLANG_WARN_BOOL_CONVERSION = YES; 207 | CLANG_WARN_CONSTANT_CONVERSION = YES; 208 | CLANG_WARN_EMPTY_BODY = YES; 209 | CLANG_WARN_ENUM_CONVERSION = YES; 210 | CLANG_WARN_INFINITE_RECURSION = YES; 211 | CLANG_WARN_INT_CONVERSION = YES; 212 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 213 | CLANG_WARN_UNREACHABLE_CODE = YES; 214 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 215 | ENABLE_STRICT_OBJC_MSGSEND = YES; 216 | GCC_NO_COMMON_BLOCKS = YES; 217 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 218 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 219 | GCC_WARN_UNDECLARED_SELECTOR = YES; 220 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 221 | GCC_WARN_UNUSED_FUNCTION = YES; 222 | GCC_WARN_UNUSED_VARIABLE = YES; 223 | }; 224 | name = Debug; 225 | }; 226 | 9E9BDA9F1E7981A60031B02C /* Release */ = { 227 | isa = XCBuildConfiguration; 228 | buildSettings = { 229 | CLANG_WARN_BOOL_CONVERSION = YES; 230 | CLANG_WARN_CONSTANT_CONVERSION = YES; 231 | CLANG_WARN_EMPTY_BODY = YES; 232 | CLANG_WARN_ENUM_CONVERSION = YES; 233 | CLANG_WARN_INFINITE_RECURSION = YES; 234 | CLANG_WARN_INT_CONVERSION = YES; 235 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 236 | CLANG_WARN_UNREACHABLE_CODE = YES; 237 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 238 | ENABLE_STRICT_OBJC_MSGSEND = YES; 239 | GCC_NO_COMMON_BLOCKS = YES; 240 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 241 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 242 | GCC_WARN_UNDECLARED_SELECTOR = YES; 243 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 244 | GCC_WARN_UNUSED_FUNCTION = YES; 245 | GCC_WARN_UNUSED_VARIABLE = YES; 246 | }; 247 | name = Release; 248 | }; 249 | 9E9BDAAA1E7982F10031B02C /* Debug */ = { 250 | isa = XCBuildConfiguration; 251 | baseConfigurationReference = F715685C59413BB311540C7B /* Pods-Tests.debug.xcconfig */; 252 | buildSettings = { 253 | ALWAYS_SEARCH_USER_PATHS = NO; 254 | CLANG_ANALYZER_NONNULL = YES; 255 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 256 | CLANG_CXX_LIBRARY = "libc++"; 257 | CLANG_ENABLE_MODULES = YES; 258 | CLANG_ENABLE_OBJC_ARC = YES; 259 | CLANG_WARN_BOOL_CONVERSION = YES; 260 | CLANG_WARN_CONSTANT_CONVERSION = YES; 261 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 262 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 263 | CLANG_WARN_EMPTY_BODY = YES; 264 | CLANG_WARN_ENUM_CONVERSION = YES; 265 | CLANG_WARN_INFINITE_RECURSION = YES; 266 | CLANG_WARN_INT_CONVERSION = YES; 267 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 268 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 269 | CLANG_WARN_UNREACHABLE_CODE = YES; 270 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 271 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 272 | COPY_PHASE_STRIP = NO; 273 | DEBUG_INFORMATION_FORMAT = dwarf; 274 | ENABLE_STRICT_OBJC_MSGSEND = YES; 275 | ENABLE_TESTABILITY = YES; 276 | GCC_C_LANGUAGE_STANDARD = gnu99; 277 | GCC_DYNAMIC_NO_PIC = NO; 278 | GCC_NO_COMMON_BLOCKS = YES; 279 | GCC_OPTIMIZATION_LEVEL = 0; 280 | GCC_PREPROCESSOR_DEFINITIONS = ( 281 | "DEBUG=1", 282 | "$(inherited)", 283 | ); 284 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 285 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 286 | GCC_WARN_UNDECLARED_SELECTOR = YES; 287 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 288 | GCC_WARN_UNUSED_FUNCTION = YES; 289 | GCC_WARN_UNUSED_VARIABLE = YES; 290 | INFOPLIST_FILE = Tests/Info.plist; 291 | IPHONEOS_DEPLOYMENT_TARGET = 10.2; 292 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 293 | MTL_ENABLE_DEBUG_INFO = YES; 294 | ONLY_ACTIVE_ARCH = YES; 295 | PRODUCT_BUNDLE_IDENTIFIER = com.paulmelnikow.Tests; 296 | PRODUCT_NAME = "$(TARGET_NAME)"; 297 | SDKROOT = iphoneos; 298 | }; 299 | name = Debug; 300 | }; 301 | 9E9BDAAB1E7982F10031B02C /* Release */ = { 302 | isa = XCBuildConfiguration; 303 | baseConfigurationReference = 38550BECD10EC4FF6335C28C /* Pods-Tests.release.xcconfig */; 304 | buildSettings = { 305 | ALWAYS_SEARCH_USER_PATHS = NO; 306 | CLANG_ANALYZER_NONNULL = YES; 307 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 308 | CLANG_CXX_LIBRARY = "libc++"; 309 | CLANG_ENABLE_MODULES = YES; 310 | CLANG_ENABLE_OBJC_ARC = YES; 311 | CLANG_WARN_BOOL_CONVERSION = YES; 312 | CLANG_WARN_CONSTANT_CONVERSION = YES; 313 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 314 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 315 | CLANG_WARN_EMPTY_BODY = YES; 316 | CLANG_WARN_ENUM_CONVERSION = YES; 317 | CLANG_WARN_INFINITE_RECURSION = YES; 318 | CLANG_WARN_INT_CONVERSION = YES; 319 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 320 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 321 | CLANG_WARN_UNREACHABLE_CODE = YES; 322 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 323 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 324 | COPY_PHASE_STRIP = NO; 325 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 326 | ENABLE_NS_ASSERTIONS = NO; 327 | ENABLE_STRICT_OBJC_MSGSEND = YES; 328 | GCC_C_LANGUAGE_STANDARD = gnu99; 329 | GCC_NO_COMMON_BLOCKS = YES; 330 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 331 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 332 | GCC_WARN_UNDECLARED_SELECTOR = YES; 333 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 334 | GCC_WARN_UNUSED_FUNCTION = YES; 335 | GCC_WARN_UNUSED_VARIABLE = YES; 336 | INFOPLIST_FILE = Tests/Info.plist; 337 | IPHONEOS_DEPLOYMENT_TARGET = 10.2; 338 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 339 | MTL_ENABLE_DEBUG_INFO = NO; 340 | PRODUCT_BUNDLE_IDENTIFIER = com.paulmelnikow.Tests; 341 | PRODUCT_NAME = "$(TARGET_NAME)"; 342 | SDKROOT = iphoneos; 343 | VALIDATE_PRODUCT = YES; 344 | }; 345 | name = Release; 346 | }; 347 | /* End XCBuildConfiguration section */ 348 | 349 | /* Begin XCConfigurationList section */ 350 | 9E9BDA9D1E7981A60031B02C /* Build configuration list for PBXProject "TestProject" */ = { 351 | isa = XCConfigurationList; 352 | buildConfigurations = ( 353 | 9E9BDA9E1E7981A60031B02C /* Debug */, 354 | 9E9BDA9F1E7981A60031B02C /* Release */, 355 | ); 356 | defaultConfigurationIsVisible = 0; 357 | defaultConfigurationName = Release; 358 | }; 359 | 9E9BDAAC1E7982F10031B02C /* Build configuration list for PBXNativeTarget "Tests" */ = { 360 | isa = XCConfigurationList; 361 | buildConfigurations = ( 362 | 9E9BDAAA1E7982F10031B02C /* Debug */, 363 | 9E9BDAAB1E7982F10031B02C /* Release */, 364 | ); 365 | defaultConfigurationIsVisible = 0; 366 | defaultConfigurationName = Release; 367 | }; 368 | /* End XCConfigurationList section */ 369 | }; 370 | rootObject = 9E9BDA9A1E7981A60031B02C /* Project object */; 371 | } 372 | -------------------------------------------------------------------------------- /2.x/TestProject/TestProject.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /2.x/TestProject/TestProject.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 14 | 15 | 17 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 39 | 40 | 41 | 42 | 48 | 49 | 51 | 52 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /2.x/TestProject/TestProject.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /2.x/TestProject/Tests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /2.x/TestProject/Tests/Tests.m: -------------------------------------------------------------------------------- 1 | @import Specta; 2 | @import Expecta; 3 | #import "AFNetworking.h" 4 | #import "AFHTTPRequestOperationManager+Synchronous.h" 5 | 6 | @interface Helpers : NSObject 7 | @end 8 | @implementation Helpers 9 | + (NSURL *) baseURL { 10 | NSDictionary *environment = [[NSProcessInfo processInfo] environment]; 11 | return [NSURL URLWithString:environment[@"HTTPBIN_BASE_URL"] ?: @"https://httpbin.org"]; 12 | } 13 | 14 | + (AFHTTPRequestOperationManager *) manager { 15 | AFHTTPRequestOperationManager *manager = 16 | [[AFHTTPRequestOperationManager alloc] initWithBaseURL:self.baseURL]; 17 | manager.responseSerializer = [AFJSONResponseSerializer serializer]; 18 | return manager; 19 | } 20 | @end 21 | 22 | SpecBegin(AFNetworking1x) 23 | 24 | describe(@"AFHTTPClient+Synchronous", ^{ 25 | 26 | __block NSError *error; 27 | __block AFHTTPRequestOperationManager *manager; 28 | beforeEach(^{ 29 | manager = [Helpers manager]; 30 | error = nil; 31 | }); 32 | 33 | describe(@"For a successful request", ^{ 34 | 35 | it(@"can GET", ^{ 36 | // Execute. 37 | id result = [manager syncGET:@"get" 38 | parameters:nil 39 | operation:NULL 40 | error:&error]; 41 | // Confidence check. 42 | expect(error).to.beNil(); 43 | 44 | // Test. 45 | expect(result).notTo.beNil(); 46 | }); 47 | 48 | it(@"passes parameters to the request", ^{ 49 | // Setup. 50 | NSDictionary *params = @{@"foo": @"bar", @"baz": @"123"}; 51 | 52 | // Execute. 53 | id result = [manager syncGET:@"get" 54 | parameters:params 55 | operation:NULL 56 | error:&error]; 57 | // Confidence check. 58 | expect(error).to.beNil(); 59 | expect(result).notTo.beNil(); 60 | 61 | // Test. 62 | expect(result[@"args"]).to.equal(params); 63 | }); 64 | 65 | it(@"sets the operation pointer", ^{ 66 | // Setup. 67 | AFHTTPRequestOperation *operation = nil; 68 | 69 | // Execute. 70 | id result = [manager syncGET:@"get" 71 | parameters:nil 72 | operation:&operation 73 | error:&error]; 74 | // Confidence check. 75 | expect(result).notTo.beNil(); 76 | 77 | // Test. 78 | expect(operation).to.beInstanceOf([AFHTTPRequestOperation class]); 79 | }); 80 | }); 81 | 82 | describe(@"For a failed request", ^{ 83 | 84 | it(@"returns nil and sets the error pointer", ^{ 85 | // Execute. 86 | id result = [manager syncGET:@"status/503" 87 | parameters:nil 88 | operation:NULL 89 | error:&error]; 90 | // Test. 91 | expect(result).to.beNil(); 92 | expect(error).to.beInstanceOf([NSError class]); 93 | expect(error.localizedDescription).to. 94 | equal(@"Request failed: service unavailable (503)"); 95 | }); 96 | 97 | }); 98 | 99 | }); 100 | 101 | SpecEnd 102 | -------------------------------------------------------------------------------- /3.x/AFHTTPSessionManager+Synchronous.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | /** 4 | A minimal category which extends AFHTTPSessionManager to support 5 | synchronous requests. 6 | 7 | **This category is for AFNetworking 3.x.** 8 | */ 9 | @interface AFHTTPSessionManager (Synchronous) 10 | 11 | /** 12 | Creates and runs an NSURLSessionDataTask with a GET request. 13 | 14 | @param URLString The URL string used to create the request URL. 15 | @param parameters The parameters to be encoded according to the client 16 | request serializer. 17 | @param taskPtr The address at which a pointer to the NSURLSessionDataTask is placed. 18 | @param outError The address at which a pointer to an error object is placed 19 | when the request operation finishes unsucessfully. 20 | 21 | @return The response object created by the client response serializer. 22 | */ 23 | - (id)syncGET:(NSString *)URLString 24 | parameters:(NSDictionary *)parameters 25 | task:(NSURLSessionDataTask *__autoreleasing *)taskPtr 26 | error:(NSError *__autoreleasing *)outError; 27 | 28 | /** 29 | Creates and runs an NSURLSessionDataTask with a POST request. 30 | 31 | @param URLString The URL string used to create the request URL. 32 | @param parameters The parameters to be encoded according to the client 33 | request serializer. 34 | @param taskPtr The address at which a pointer to the NSURLSessionDataTask is placed. 35 | @param outError The address at which a pointer to an error object is placed 36 | when the request operation finishes unsucessfully. 37 | 38 | @return The response object created by the client response serializer. 39 | */ 40 | - (id)syncPOST:(NSString *)URLString 41 | parameters:(NSDictionary *)parameters 42 | task:(NSURLSessionDataTask *__autoreleasing *)taskPtr 43 | error:(NSError *__autoreleasing *) outError; 44 | 45 | /** 46 | Creates and runs an NSURLSessionDataTask with a PUT request. 47 | 48 | @param URLString The URL string used to create the request URL. 49 | @param parameters The parameters to be encoded according to the client 50 | request serializer. 51 | @param taskPtr The address at which a pointer to the NSURLSessionDataTask is placed. 52 | @param outError The address at which a pointer to an error object is placed 53 | when the request operation finishes unsucessfully. 54 | 55 | @return The response object created by the client response serializer. 56 | */ 57 | - (id)syncPUT:(NSString *)URLString 58 | parameters:(NSDictionary *)parameters 59 | task:(NSURLSessionDataTask *__autoreleasing *)taskPtr 60 | error:(NSError *__autoreleasing *) outError; 61 | /** 62 | Creates and runs an NSURLSessionDataTask with a DELETE request. 63 | 64 | @param URLString The URL string used to create the request URL. 65 | @param parameters The parameters to be encoded according to the client 66 | request serializer. 67 | @param taskPtr The address at which a pointer to the NSURLSessionDataTask is placed. 68 | @param outError The address at which a pointer to an error object is placed 69 | when the request operation finishes unsucessfully. 70 | 71 | @return The response object created by the client response serializer. 72 | */ 73 | - (id)syncDELETE:(NSString *)URLString 74 | parameters:(NSDictionary *)parameters 75 | task:(NSURLSessionDataTask *__autoreleasing *)taskPtr 76 | error:(NSError *__autoreleasing *) outError; 77 | 78 | /** 79 | Creates and runs an NSURLSessionDataTask with a PATCH request. 80 | 81 | @param URLString The URL string used to create the request URL. 82 | @param parameters The parameters to be encoded according to the client 83 | request serializer. 84 | @param taskPtr The address at which a pointer to the NSURLSessionDataTask is placed. 85 | @param outError The address at which a pointer to an error object is placed 86 | when the request operation finishes unsucessfully. 87 | 88 | @return The response object created by the client response serializer. 89 | */ 90 | - (id)syncPATCH:(NSString *)URLString 91 | parameters:(NSDictionary *)parameters 92 | task:(NSURLSessionDataTask *__autoreleasing *)taskPtr 93 | error:(NSError *__autoreleasing *) outError; 94 | 95 | /** 96 | Enqueue an NSURLSessionDataTask with a request for the given HTTP method. 97 | 98 | @param method The HTTP method. 99 | @param URLString The URL string used to create the request URL. 100 | @param parameters The parameters to be encoded and set in the request HTTP body. 101 | @param taskPtr The address at which a pointer to the NSURLSessionDataTask is placed. 102 | @param outError The address at which a pointer to an error object is placed 103 | when the request operation finishes unsucessfully. 104 | 105 | @return The object created from the response data of the request. 106 | */ 107 | - (id)synchronouslyPerformMethod:(NSString *)method 108 | URLString:(NSString *)URLString 109 | parameters:(NSDictionary *)parameters 110 | task:(NSURLSessionDataTask *__autoreleasing *)taskPtr 111 | error:(NSError *__autoreleasing *)outError; 112 | 113 | @end 114 | -------------------------------------------------------------------------------- /3.x/AFHTTPSessionManager+Synchronous.m: -------------------------------------------------------------------------------- 1 | #import "AFHTTPSessionManager+Synchronous.h" 2 | 3 | @interface AFHTTPSessionManager (Private) 4 | - (NSURLSessionDataTask *)dataTaskWithHTTPMethod:(NSString *)method 5 | URLString:(NSString *)URLString 6 | parameters:(id)parameters 7 | uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgress 8 | downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgress 9 | success:(void (^)(NSURLSessionDataTask *, id))success 10 | failure:(void (^)(NSURLSessionDataTask *, NSError *))failure; 11 | @end 12 | 13 | @implementation AFHTTPSessionManager (Synchronous) 14 | 15 | - (id)synchronouslyPerformMethod:(NSString *)method 16 | URLString:(NSString *)URLString 17 | parameters:(NSDictionary *)parameters 18 | task:(NSURLSessionDataTask *__autoreleasing *)taskPtr 19 | error:(NSError *__autoreleasing *)outError { 20 | 21 | // Prevent the most common deadlock. When this method is invoked from the main 22 | // thread, and the session manager's completion queue is the main queue, the 23 | // semaphore will not be released. This method will never return. 24 | // 25 | // You really should not perform a synchronous network request on the main 26 | // thread on iOS, as it's likely to cause a crash when run outside the debugger. 27 | // You probably should not on OS X either, as it's likely to cause lags in the 28 | // UI. 29 | // 30 | // If you must dispatch from the main queue, create a new queue for the 31 | // completion handler: 32 | // 33 | // manager.completionQueue = dispatch_queue_create("AFNetworking+Synchronous", NULL); 34 | // 35 | if ([NSThread isMainThread]) { 36 | if (self.completionQueue == nil || self.completionQueue == dispatch_get_main_queue()) { 37 | @throw 38 | [NSException exceptionWithName:NSInvalidArgumentException 39 | reason:@"Can't make a synchronous request on the same queue as the completion handler" 40 | userInfo:nil]; 41 | } 42 | } 43 | 44 | __block id responseObject = nil; 45 | __block NSError *error = nil; 46 | 47 | // Thanks @tewha for this suggestion. 48 | // https://github.com/AFNetworking/AFNetworking/issues/1804#issuecomment-100396741 49 | dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); 50 | 51 | NSURLSessionDataTask *task = 52 | [self dataTaskWithHTTPMethod:method 53 | URLString:URLString 54 | parameters:parameters 55 | uploadProgress:nil 56 | downloadProgress:nil 57 | success: 58 | ^(NSURLSessionDataTask *unusedTask, id resp) { 59 | responseObject = resp; 60 | dispatch_semaphore_signal(semaphore); 61 | } 62 | failure: 63 | ^(NSURLSessionDataTask *unusedTask, NSError *err) { 64 | error = err; 65 | dispatch_semaphore_signal(semaphore); 66 | }]; 67 | 68 | [task resume]; 69 | dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); 70 | 71 | if (taskPtr != nil) *taskPtr = task; 72 | if (outError != nil) *outError = error; 73 | 74 | return responseObject; 75 | } 76 | 77 | - (id)syncGET:(NSString *)URLString 78 | parameters:(NSDictionary *)parameters 79 | task:(NSURLSessionDataTask *__autoreleasing *)taskPtr 80 | error:(NSError *__autoreleasing *)outError 81 | { 82 | return [self synchronouslyPerformMethod:@"GET" 83 | URLString:URLString 84 | parameters:parameters 85 | task:taskPtr 86 | error:outError]; 87 | } 88 | 89 | - (id)syncPOST:(NSString *)URLString 90 | parameters:(NSDictionary *)parameters 91 | task:(NSURLSessionDataTask *__autoreleasing *)taskPtr 92 | error:(NSError *__autoreleasing *) outError 93 | { 94 | return [self synchronouslyPerformMethod:@"POST" 95 | URLString:URLString 96 | parameters:parameters 97 | task:taskPtr 98 | error:outError]; 99 | } 100 | 101 | - (id)syncPUT:(NSString *)URLString 102 | parameters:(NSDictionary *)parameters 103 | task:(NSURLSessionDataTask *__autoreleasing *)taskPtr 104 | error:(NSError *__autoreleasing *) outError 105 | { 106 | return [self synchronouslyPerformMethod:@"PUT" 107 | URLString:URLString 108 | parameters:parameters 109 | task:taskPtr 110 | error:outError]; 111 | } 112 | 113 | - (id)syncDELETE:(NSString *)URLString 114 | parameters:(NSDictionary *)parameters 115 | task:(NSURLSessionDataTask *__autoreleasing *)taskPtr 116 | error:(NSError *__autoreleasing *) outError 117 | { 118 | return [self synchronouslyPerformMethod:@"DELETE" 119 | URLString:URLString 120 | parameters:parameters 121 | task:taskPtr 122 | error:outError]; 123 | } 124 | 125 | - (id)syncPATCH:(NSString *)URLString 126 | parameters:(NSDictionary *)parameters 127 | task:(NSURLSessionDataTask *__autoreleasing *)taskPtr 128 | error:(NSError *__autoreleasing *) outError 129 | { 130 | return [self synchronouslyPerformMethod:@"PATCH" 131 | URLString:URLString 132 | parameters:parameters 133 | task:taskPtr 134 | error:outError]; 135 | } 136 | 137 | @end 138 | -------------------------------------------------------------------------------- /3.x/TestProject/Podfile: -------------------------------------------------------------------------------- 1 | use_frameworks! 2 | target 'Tests' do 3 | pod 'AFNetworking-Synchronous/3.x', :path => '../../' 4 | 5 | pod 'Specta' 6 | pod 'Expecta' 7 | end 8 | 9 | -------------------------------------------------------------------------------- /3.x/TestProject/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - AFNetworking (3.1.0): 3 | - AFNetworking/NSURLSession (= 3.1.0) 4 | - AFNetworking/Reachability (= 3.1.0) 5 | - AFNetworking/Security (= 3.1.0) 6 | - AFNetworking/Serialization (= 3.1.0) 7 | - AFNetworking/UIKit (= 3.1.0) 8 | - AFNetworking-Synchronous/3.x (2.0.0-dev): 9 | - AFNetworking (~> 3.0) 10 | - AFNetworking/NSURLSession (3.1.0): 11 | - AFNetworking/Reachability 12 | - AFNetworking/Security 13 | - AFNetworking/Serialization 14 | - AFNetworking/Reachability (3.1.0) 15 | - AFNetworking/Security (3.1.0) 16 | - AFNetworking/Serialization (3.1.0) 17 | - AFNetworking/UIKit (3.1.0): 18 | - AFNetworking/NSURLSession 19 | - Expecta (1.0.5) 20 | - Specta (1.0.6) 21 | 22 | DEPENDENCIES: 23 | - AFNetworking-Synchronous/3.x (from `../../`) 24 | - Expecta 25 | - Specta 26 | 27 | EXTERNAL SOURCES: 28 | AFNetworking-Synchronous: 29 | :path: "../../" 30 | 31 | SPEC CHECKSUMS: 32 | AFNetworking: 5e0e199f73d8626b11e79750991f5d173d1f8b67 33 | AFNetworking-Synchronous: 7993907e716221b1660feb98447d504cb4645c82 34 | Expecta: e1c022fcd33910b6be89c291d2775b3fe27a89fe 35 | Specta: f506f3a8361de16bc0dcf3b17b75e269072ba465 36 | 37 | PODFILE CHECKSUM: 2cd42aaceb64b06d36f7d78000de64d42cb0d406 38 | 39 | COCOAPODS: 1.2.0 40 | -------------------------------------------------------------------------------- /3.x/TestProject/TestProject.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 2ECD212AF18571ED7786CC69 /* Pods_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6DCCCE739AB09E4629043F98 /* Pods_Tests.framework */; }; 11 | 9E9BDAA81E7982F10031B02C /* Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 9E9BDAA71E7982F10031B02C /* Tests.m */; }; 12 | /* End PBXBuildFile section */ 13 | 14 | /* Begin PBXFileReference section */ 15 | 38550BECD10EC4FF6335C28C /* Pods-Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-Tests/Pods-Tests.release.xcconfig"; sourceTree = ""; }; 16 | 6DCCCE739AB09E4629043F98 /* Pods_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 17 | 9E9BDAA41E7982F10031B02C /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 18 | 9E9BDAA71E7982F10031B02C /* Tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Tests.m; sourceTree = ""; }; 19 | 9E9BDAA91E7982F10031B02C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 20 | F715685C59413BB311540C7B /* Pods-Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Tests/Pods-Tests.debug.xcconfig"; sourceTree = ""; }; 21 | /* End PBXFileReference section */ 22 | 23 | /* Begin PBXFrameworksBuildPhase section */ 24 | 9E9BDAA11E7982F10031B02C /* Frameworks */ = { 25 | isa = PBXFrameworksBuildPhase; 26 | buildActionMask = 2147483647; 27 | files = ( 28 | 2ECD212AF18571ED7786CC69 /* Pods_Tests.framework in Frameworks */, 29 | ); 30 | runOnlyForDeploymentPostprocessing = 0; 31 | }; 32 | /* End PBXFrameworksBuildPhase section */ 33 | 34 | /* Begin PBXGroup section */ 35 | 854103492BD3D5298BD37401 /* Pods */ = { 36 | isa = PBXGroup; 37 | children = ( 38 | F715685C59413BB311540C7B /* Pods-Tests.debug.xcconfig */, 39 | 38550BECD10EC4FF6335C28C /* Pods-Tests.release.xcconfig */, 40 | ); 41 | name = Pods; 42 | sourceTree = ""; 43 | }; 44 | 9C5B2A581FCB18A2F3F9F534 /* Frameworks */ = { 45 | isa = PBXGroup; 46 | children = ( 47 | 6DCCCE739AB09E4629043F98 /* Pods_Tests.framework */, 48 | ); 49 | name = Frameworks; 50 | sourceTree = ""; 51 | }; 52 | 9E9BDA991E7981A60031B02C = { 53 | isa = PBXGroup; 54 | children = ( 55 | 9E9BDAA61E7982F10031B02C /* Tests */, 56 | 9E9BDAA51E7982F10031B02C /* Products */, 57 | 854103492BD3D5298BD37401 /* Pods */, 58 | 9C5B2A581FCB18A2F3F9F534 /* Frameworks */, 59 | ); 60 | sourceTree = ""; 61 | }; 62 | 9E9BDAA51E7982F10031B02C /* Products */ = { 63 | isa = PBXGroup; 64 | children = ( 65 | 9E9BDAA41E7982F10031B02C /* Tests.xctest */, 66 | ); 67 | name = Products; 68 | sourceTree = ""; 69 | }; 70 | 9E9BDAA61E7982F10031B02C /* Tests */ = { 71 | isa = PBXGroup; 72 | children = ( 73 | 9E9BDAA71E7982F10031B02C /* Tests.m */, 74 | 9E9BDAA91E7982F10031B02C /* Info.plist */, 75 | ); 76 | path = Tests; 77 | sourceTree = ""; 78 | }; 79 | /* End PBXGroup section */ 80 | 81 | /* Begin PBXNativeTarget section */ 82 | 9E9BDAA31E7982F10031B02C /* Tests */ = { 83 | isa = PBXNativeTarget; 84 | buildConfigurationList = 9E9BDAAC1E7982F10031B02C /* Build configuration list for PBXNativeTarget "Tests" */; 85 | buildPhases = ( 86 | B6E96878860E900085C2F4D0 /* [CP] Check Pods Manifest.lock */, 87 | 9E9BDAA01E7982F10031B02C /* Sources */, 88 | 9E9BDAA11E7982F10031B02C /* Frameworks */, 89 | 9E9BDAA21E7982F10031B02C /* Resources */, 90 | 08BD843668D5CB0F7D21D38C /* [CP] Embed Pods Frameworks */, 91 | EC436F7897D37E7B0AEA4FAD /* [CP] Copy Pods Resources */, 92 | ); 93 | buildRules = ( 94 | ); 95 | dependencies = ( 96 | ); 97 | name = Tests; 98 | productName = Tests; 99 | productReference = 9E9BDAA41E7982F10031B02C /* Tests.xctest */; 100 | productType = "com.apple.product-type.bundle.unit-test"; 101 | }; 102 | /* End PBXNativeTarget section */ 103 | 104 | /* Begin PBXProject section */ 105 | 9E9BDA9A1E7981A60031B02C /* Project object */ = { 106 | isa = PBXProject; 107 | attributes = { 108 | LastUpgradeCheck = 0820; 109 | TargetAttributes = { 110 | 9E9BDAA31E7982F10031B02C = { 111 | CreatedOnToolsVersion = 8.2.1; 112 | ProvisioningStyle = Automatic; 113 | }; 114 | }; 115 | }; 116 | buildConfigurationList = 9E9BDA9D1E7981A60031B02C /* Build configuration list for PBXProject "TestProject" */; 117 | compatibilityVersion = "Xcode 3.2"; 118 | developmentRegion = English; 119 | hasScannedForEncodings = 0; 120 | knownRegions = ( 121 | en, 122 | ); 123 | mainGroup = 9E9BDA991E7981A60031B02C; 124 | productRefGroup = 9E9BDAA51E7982F10031B02C /* Products */; 125 | projectDirPath = ""; 126 | projectRoot = ""; 127 | targets = ( 128 | 9E9BDAA31E7982F10031B02C /* Tests */, 129 | ); 130 | }; 131 | /* End PBXProject section */ 132 | 133 | /* Begin PBXResourcesBuildPhase section */ 134 | 9E9BDAA21E7982F10031B02C /* Resources */ = { 135 | isa = PBXResourcesBuildPhase; 136 | buildActionMask = 2147483647; 137 | files = ( 138 | ); 139 | runOnlyForDeploymentPostprocessing = 0; 140 | }; 141 | /* End PBXResourcesBuildPhase section */ 142 | 143 | /* Begin PBXShellScriptBuildPhase section */ 144 | 08BD843668D5CB0F7D21D38C /* [CP] Embed Pods Frameworks */ = { 145 | isa = PBXShellScriptBuildPhase; 146 | buildActionMask = 2147483647; 147 | files = ( 148 | ); 149 | inputPaths = ( 150 | ); 151 | name = "[CP] Embed Pods Frameworks"; 152 | outputPaths = ( 153 | ); 154 | runOnlyForDeploymentPostprocessing = 0; 155 | shellPath = /bin/sh; 156 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Tests/Pods-Tests-frameworks.sh\"\n"; 157 | showEnvVarsInLog = 0; 158 | }; 159 | B6E96878860E900085C2F4D0 /* [CP] Check Pods Manifest.lock */ = { 160 | isa = PBXShellScriptBuildPhase; 161 | buildActionMask = 2147483647; 162 | files = ( 163 | ); 164 | inputPaths = ( 165 | ); 166 | name = "[CP] Check Pods Manifest.lock"; 167 | outputPaths = ( 168 | ); 169 | runOnlyForDeploymentPostprocessing = 0; 170 | shellPath = /bin/sh; 171 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; 172 | showEnvVarsInLog = 0; 173 | }; 174 | EC436F7897D37E7B0AEA4FAD /* [CP] Copy Pods Resources */ = { 175 | isa = PBXShellScriptBuildPhase; 176 | buildActionMask = 2147483647; 177 | files = ( 178 | ); 179 | inputPaths = ( 180 | ); 181 | name = "[CP] Copy Pods Resources"; 182 | outputPaths = ( 183 | ); 184 | runOnlyForDeploymentPostprocessing = 0; 185 | shellPath = /bin/sh; 186 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Tests/Pods-Tests-resources.sh\"\n"; 187 | showEnvVarsInLog = 0; 188 | }; 189 | /* End PBXShellScriptBuildPhase section */ 190 | 191 | /* Begin PBXSourcesBuildPhase section */ 192 | 9E9BDAA01E7982F10031B02C /* Sources */ = { 193 | isa = PBXSourcesBuildPhase; 194 | buildActionMask = 2147483647; 195 | files = ( 196 | 9E9BDAA81E7982F10031B02C /* Tests.m in Sources */, 197 | ); 198 | runOnlyForDeploymentPostprocessing = 0; 199 | }; 200 | /* End PBXSourcesBuildPhase section */ 201 | 202 | /* Begin XCBuildConfiguration section */ 203 | 9E9BDA9E1E7981A60031B02C /* Debug */ = { 204 | isa = XCBuildConfiguration; 205 | buildSettings = { 206 | CLANG_WARN_BOOL_CONVERSION = YES; 207 | CLANG_WARN_CONSTANT_CONVERSION = YES; 208 | CLANG_WARN_EMPTY_BODY = YES; 209 | CLANG_WARN_ENUM_CONVERSION = YES; 210 | CLANG_WARN_INFINITE_RECURSION = YES; 211 | CLANG_WARN_INT_CONVERSION = YES; 212 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 213 | CLANG_WARN_UNREACHABLE_CODE = YES; 214 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 215 | ENABLE_STRICT_OBJC_MSGSEND = YES; 216 | GCC_NO_COMMON_BLOCKS = YES; 217 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 218 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 219 | GCC_WARN_UNDECLARED_SELECTOR = YES; 220 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 221 | GCC_WARN_UNUSED_FUNCTION = YES; 222 | GCC_WARN_UNUSED_VARIABLE = YES; 223 | }; 224 | name = Debug; 225 | }; 226 | 9E9BDA9F1E7981A60031B02C /* Release */ = { 227 | isa = XCBuildConfiguration; 228 | buildSettings = { 229 | CLANG_WARN_BOOL_CONVERSION = YES; 230 | CLANG_WARN_CONSTANT_CONVERSION = YES; 231 | CLANG_WARN_EMPTY_BODY = YES; 232 | CLANG_WARN_ENUM_CONVERSION = YES; 233 | CLANG_WARN_INFINITE_RECURSION = YES; 234 | CLANG_WARN_INT_CONVERSION = YES; 235 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 236 | CLANG_WARN_UNREACHABLE_CODE = YES; 237 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 238 | ENABLE_STRICT_OBJC_MSGSEND = YES; 239 | GCC_NO_COMMON_BLOCKS = YES; 240 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 241 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 242 | GCC_WARN_UNDECLARED_SELECTOR = YES; 243 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 244 | GCC_WARN_UNUSED_FUNCTION = YES; 245 | GCC_WARN_UNUSED_VARIABLE = YES; 246 | }; 247 | name = Release; 248 | }; 249 | 9E9BDAAA1E7982F10031B02C /* Debug */ = { 250 | isa = XCBuildConfiguration; 251 | baseConfigurationReference = F715685C59413BB311540C7B /* Pods-Tests.debug.xcconfig */; 252 | buildSettings = { 253 | ALWAYS_SEARCH_USER_PATHS = NO; 254 | CLANG_ANALYZER_NONNULL = YES; 255 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 256 | CLANG_CXX_LIBRARY = "libc++"; 257 | CLANG_ENABLE_MODULES = YES; 258 | CLANG_ENABLE_OBJC_ARC = YES; 259 | CLANG_WARN_BOOL_CONVERSION = YES; 260 | CLANG_WARN_CONSTANT_CONVERSION = YES; 261 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 262 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 263 | CLANG_WARN_EMPTY_BODY = YES; 264 | CLANG_WARN_ENUM_CONVERSION = YES; 265 | CLANG_WARN_INFINITE_RECURSION = YES; 266 | CLANG_WARN_INT_CONVERSION = YES; 267 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 268 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 269 | CLANG_WARN_UNREACHABLE_CODE = YES; 270 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 271 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 272 | COPY_PHASE_STRIP = NO; 273 | DEBUG_INFORMATION_FORMAT = dwarf; 274 | ENABLE_STRICT_OBJC_MSGSEND = YES; 275 | ENABLE_TESTABILITY = YES; 276 | GCC_C_LANGUAGE_STANDARD = gnu99; 277 | GCC_DYNAMIC_NO_PIC = NO; 278 | GCC_NO_COMMON_BLOCKS = YES; 279 | GCC_OPTIMIZATION_LEVEL = 0; 280 | GCC_PREPROCESSOR_DEFINITIONS = ( 281 | "DEBUG=1", 282 | "$(inherited)", 283 | ); 284 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 285 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 286 | GCC_WARN_UNDECLARED_SELECTOR = YES; 287 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 288 | GCC_WARN_UNUSED_FUNCTION = YES; 289 | GCC_WARN_UNUSED_VARIABLE = YES; 290 | INFOPLIST_FILE = Tests/Info.plist; 291 | IPHONEOS_DEPLOYMENT_TARGET = 10.2; 292 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 293 | MTL_ENABLE_DEBUG_INFO = YES; 294 | ONLY_ACTIVE_ARCH = YES; 295 | PRODUCT_BUNDLE_IDENTIFIER = com.paulmelnikow.Tests; 296 | PRODUCT_NAME = "$(TARGET_NAME)"; 297 | SDKROOT = iphoneos; 298 | }; 299 | name = Debug; 300 | }; 301 | 9E9BDAAB1E7982F10031B02C /* Release */ = { 302 | isa = XCBuildConfiguration; 303 | baseConfigurationReference = 38550BECD10EC4FF6335C28C /* Pods-Tests.release.xcconfig */; 304 | buildSettings = { 305 | ALWAYS_SEARCH_USER_PATHS = NO; 306 | CLANG_ANALYZER_NONNULL = YES; 307 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 308 | CLANG_CXX_LIBRARY = "libc++"; 309 | CLANG_ENABLE_MODULES = YES; 310 | CLANG_ENABLE_OBJC_ARC = YES; 311 | CLANG_WARN_BOOL_CONVERSION = YES; 312 | CLANG_WARN_CONSTANT_CONVERSION = YES; 313 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 314 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 315 | CLANG_WARN_EMPTY_BODY = YES; 316 | CLANG_WARN_ENUM_CONVERSION = YES; 317 | CLANG_WARN_INFINITE_RECURSION = YES; 318 | CLANG_WARN_INT_CONVERSION = YES; 319 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 320 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 321 | CLANG_WARN_UNREACHABLE_CODE = YES; 322 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 323 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 324 | COPY_PHASE_STRIP = NO; 325 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 326 | ENABLE_NS_ASSERTIONS = NO; 327 | ENABLE_STRICT_OBJC_MSGSEND = YES; 328 | GCC_C_LANGUAGE_STANDARD = gnu99; 329 | GCC_NO_COMMON_BLOCKS = YES; 330 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 331 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 332 | GCC_WARN_UNDECLARED_SELECTOR = YES; 333 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 334 | GCC_WARN_UNUSED_FUNCTION = YES; 335 | GCC_WARN_UNUSED_VARIABLE = YES; 336 | INFOPLIST_FILE = Tests/Info.plist; 337 | IPHONEOS_DEPLOYMENT_TARGET = 10.2; 338 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 339 | MTL_ENABLE_DEBUG_INFO = NO; 340 | PRODUCT_BUNDLE_IDENTIFIER = com.paulmelnikow.Tests; 341 | PRODUCT_NAME = "$(TARGET_NAME)"; 342 | SDKROOT = iphoneos; 343 | VALIDATE_PRODUCT = YES; 344 | }; 345 | name = Release; 346 | }; 347 | /* End XCBuildConfiguration section */ 348 | 349 | /* Begin XCConfigurationList section */ 350 | 9E9BDA9D1E7981A60031B02C /* Build configuration list for PBXProject "TestProject" */ = { 351 | isa = XCConfigurationList; 352 | buildConfigurations = ( 353 | 9E9BDA9E1E7981A60031B02C /* Debug */, 354 | 9E9BDA9F1E7981A60031B02C /* Release */, 355 | ); 356 | defaultConfigurationIsVisible = 0; 357 | defaultConfigurationName = Release; 358 | }; 359 | 9E9BDAAC1E7982F10031B02C /* Build configuration list for PBXNativeTarget "Tests" */ = { 360 | isa = XCConfigurationList; 361 | buildConfigurations = ( 362 | 9E9BDAAA1E7982F10031B02C /* Debug */, 363 | 9E9BDAAB1E7982F10031B02C /* Release */, 364 | ); 365 | defaultConfigurationIsVisible = 0; 366 | defaultConfigurationName = Release; 367 | }; 368 | /* End XCConfigurationList section */ 369 | }; 370 | rootObject = 9E9BDA9A1E7981A60031B02C /* Project object */; 371 | } 372 | -------------------------------------------------------------------------------- /3.x/TestProject/TestProject.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /3.x/TestProject/TestProject.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 14 | 15 | 17 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 39 | 40 | 41 | 42 | 48 | 49 | 51 | 52 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /3.x/TestProject/TestProject.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /3.x/TestProject/Tests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /3.x/TestProject/Tests/Tests.m: -------------------------------------------------------------------------------- 1 | @import Specta; 2 | @import Expecta; 3 | #import "AFNetworking.h" 4 | #import "AFHTTPSessionManager+Synchronous.h" 5 | 6 | @interface Helpers : NSObject 7 | @end 8 | @implementation Helpers 9 | + (NSURL *) baseURL { 10 | NSDictionary *environment = [[NSProcessInfo processInfo] environment]; 11 | return [NSURL URLWithString:environment[@"HTTPBIN_BASE_URL"] ?: @"https://httpbin.org"]; 12 | } 13 | 14 | + (AFHTTPSessionManager *) manager { 15 | AFHTTPSessionManager *manager = 16 | [[AFHTTPSessionManager alloc] initWithBaseURL:self.baseURL]; 17 | manager.completionQueue = dispatch_queue_create("AFNetworking+Synchronous", NULL); 18 | return manager; 19 | } 20 | @end 21 | 22 | SpecBegin(AFNetworking1x) 23 | 24 | describe(@"AFHTTPClient+Synchronous", ^{ 25 | 26 | __block NSError *error; 27 | __block AFHTTPSessionManager *manager; 28 | beforeEach(^{ 29 | manager = [Helpers manager]; 30 | error = nil; 31 | }); 32 | 33 | describe(@"For a successful request", ^{ 34 | 35 | it(@"can GET", ^{ 36 | // Execute. 37 | id result = [manager syncGET:@"get" 38 | parameters:nil 39 | task:NULL 40 | error:&error]; 41 | // Confidence check. 42 | expect(error).to.beNil(); 43 | 44 | // Test. 45 | expect(result).notTo.beNil(); 46 | }); 47 | 48 | it(@"passes parameters to the request", ^{ 49 | // Setup. 50 | NSDictionary *params = @{@"foo": @"bar", @"baz": @"123"}; 51 | 52 | // Execute. 53 | id result = [manager syncGET:@"get" 54 | parameters:params 55 | task:NULL 56 | error:&error]; 57 | // Confidence check. 58 | expect(error).to.beNil(); 59 | expect(result).notTo.beNil(); 60 | 61 | // Test. 62 | expect(result[@"args"]).to.equal(params); 63 | }); 64 | 65 | it(@"sets the task pointer", ^{ 66 | // Setup. 67 | NSURLSessionDataTask *task = nil; 68 | 69 | // Execute. 70 | id result = [manager syncGET:@"get" 71 | parameters:nil 72 | task:&task 73 | error:&error]; 74 | // Confidence check. 75 | expect(result).notTo.beNil(); 76 | 77 | // Test. 78 | expect(task).to.beKindOf([NSURLSessionDataTask class]); 79 | }); 80 | }); 81 | 82 | describe(@"For a failed request", ^{ 83 | 84 | it(@"returns nil and sets the error pointer", ^{ 85 | // Execute. 86 | id result = [manager syncGET:@"status/503" 87 | parameters:nil 88 | task:NULL 89 | error:&error]; 90 | // Test. 91 | expect(result).to.beNil(); 92 | expect(error).to.beInstanceOf([NSError class]); 93 | expect(error.localizedDescription).to. 94 | equal(@"Request failed: service unavailable (503)"); 95 | }); 96 | 97 | }); 98 | 99 | describe(@"When running on the main thread", ^{ 100 | 101 | it(@"throws an exception when the completion queue is the main queue", ^{ 102 | // Setup. 103 | manager.completionQueue = dispatch_get_main_queue(); 104 | 105 | // Test. 106 | expect(^{ 107 | [manager syncGET:@"get" parameters:nil task:NULL error:&error]; 108 | }).to.raise(NSInvalidArgumentException); 109 | }); 110 | 111 | it(@"throws an exception when the completion queue is the default", ^{ 112 | // Setup. 113 | manager.completionQueue = nil; 114 | 115 | // Test. 116 | expect(^{ 117 | [manager syncGET:@"get" parameters:nil task:NULL error:&error]; 118 | }).to.raise(NSInvalidArgumentException); 119 | }); 120 | 121 | }); 122 | 123 | }); 124 | 125 | SpecEnd 126 | -------------------------------------------------------------------------------- /4.x/AFHTTPSessionManager+Synchronous.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | /** 4 | A minimal category which extends AFHTTPSessionManager to support 5 | synchronous requests. 6 | 7 | **This category is for AFNetworking 4.x.** 8 | */ 9 | @interface AFHTTPSessionManager (Synchronous) 10 | 11 | /** 12 | Creates and runs an NSURLSessionDataTask with a GET request. 13 | 14 | @param URLString The URL string used to create the request URL. 15 | @param parameters The parameters to be encoded according to the client 16 | request serializer. 17 | @param headers The headers appended to the default headers for this request. 18 | @param taskPtr The address at which a pointer to the NSURLSessionDataTask is placed. 19 | @param outError The address at which a pointer to an error object is placed 20 | when the request operation finishes unsucessfully. 21 | 22 | @return The response object created by the client response serializer. 23 | */ 24 | - (id)syncGET:(NSString *)URLString 25 | parameters:(NSDictionary *)parameters 26 | headers:(NSDictionary *)headers 27 | task:(NSURLSessionDataTask *__autoreleasing *)taskPtr 28 | error:(NSError *__autoreleasing *)outError; 29 | 30 | /** 31 | Creates and runs an NSURLSessionDataTask with a POST request. 32 | 33 | @param URLString The URL string used to create the request URL. 34 | @param parameters The parameters to be encoded according to the client 35 | request serializer. 36 | @param headers The headers appended to the default headers for this request. 37 | @param taskPtr The address at which a pointer to the NSURLSessionDataTask is placed. 38 | @param outError The address at which a pointer to an error object is placed 39 | when the request operation finishes unsucessfully. 40 | 41 | @return The response object created by the client response serializer. 42 | */ 43 | - (id)syncPOST:(NSString *)URLString 44 | parameters:(NSDictionary *)parameters 45 | headers:(NSDictionary *)headers 46 | task:(NSURLSessionDataTask *__autoreleasing *)taskPtr 47 | error:(NSError *__autoreleasing *) outError; 48 | 49 | /** 50 | Creates and runs an NSURLSessionDataTask with a PUT request. 51 | 52 | @param URLString The URL string used to create the request URL. 53 | @param parameters The parameters to be encoded according to the client 54 | request serializer. 55 | @param headers The headers appended to the default headers for this request. 56 | @param taskPtr The address at which a pointer to the NSURLSessionDataTask is placed. 57 | @param outError The address at which a pointer to an error object is placed 58 | when the request operation finishes unsucessfully. 59 | 60 | @return The response object created by the client response serializer. 61 | */ 62 | - (id)syncPUT:(NSString *)URLString 63 | parameters:(NSDictionary *)parameters 64 | headers:(NSDictionary *)headers 65 | task:(NSURLSessionDataTask *__autoreleasing *)taskPtr 66 | error:(NSError *__autoreleasing *) outError; 67 | /** 68 | Creates and runs an NSURLSessionDataTask with a DELETE request. 69 | 70 | @param URLString The URL string used to create the request URL. 71 | @param parameters The parameters to be encoded according to the client 72 | request serializer. 73 | @param headers The headers appended to the default headers for this request. 74 | @param taskPtr The address at which a pointer to the NSURLSessionDataTask is placed. 75 | @param outError The address at which a pointer to an error object is placed 76 | when the request operation finishes unsucessfully. 77 | 78 | @return The response object created by the client response serializer. 79 | */ 80 | - (id)syncDELETE:(NSString *)URLString 81 | parameters:(NSDictionary *)parameters 82 | headers:(NSDictionary *)headers 83 | task:(NSURLSessionDataTask *__autoreleasing *)taskPtr 84 | error:(NSError *__autoreleasing *) outError; 85 | 86 | /** 87 | Creates and runs an NSURLSessionDataTask with a PATCH request. 88 | 89 | @param URLString The URL string used to create the request URL. 90 | @param parameters The parameters to be encoded according to the client 91 | request serializer. 92 | @param headers The headers appended to the default headers for this request. 93 | @param taskPtr The address at which a pointer to the NSURLSessionDataTask is placed. 94 | @param outError The address at which a pointer to an error object is placed 95 | when the request operation finishes unsucessfully. 96 | 97 | @return The response object created by the client response serializer. 98 | */ 99 | - (id)syncPATCH:(NSString *)URLString 100 | parameters:(NSDictionary *)parameters 101 | headers:(NSDictionary *)headers 102 | task:(NSURLSessionDataTask *__autoreleasing *)taskPtr 103 | error:(NSError *__autoreleasing *) outError; 104 | 105 | /** 106 | Enqueue an NSURLSessionDataTask with a request for the given HTTP method. 107 | 108 | @param method The HTTP method. 109 | @param URLString The URL string used to create the request URL. 110 | @param parameters The parameters to be encoded and set in the request HTTP body. 111 | @param headers The headers appended to the default headers for this request. 112 | @param taskPtr The address at which a pointer to the NSURLSessionDataTask is placed. 113 | @param outError The address at which a pointer to an error object is placed 114 | when the request operation finishes unsucessfully. 115 | 116 | @return The object created from the response data of the request. 117 | */ 118 | - (id)synchronouslyPerformMethod:(NSString *)method 119 | URLString:(NSString *)URLString 120 | parameters:(NSDictionary *)parameters 121 | headers:(NSDictionary *)headers 122 | task:(NSURLSessionDataTask *__autoreleasing *)taskPtr 123 | error:(NSError *__autoreleasing *)outError; 124 | 125 | @end 126 | -------------------------------------------------------------------------------- /4.x/AFHTTPSessionManager+Synchronous.m: -------------------------------------------------------------------------------- 1 | #import "AFHTTPSessionManager+Synchronous.h" 2 | 3 | @interface AFHTTPSessionManager (Private) 4 | - (NSURLSessionDataTask *)dataTaskWithHTTPMethod:(NSString *)method 5 | URLString:(NSString *)URLString 6 | parameters:(id)parameters 7 | headers:(NSDictionary *)headers 8 | uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgress 9 | downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgress 10 | success:(void (^)(NSURLSessionDataTask *, id))success 11 | failure:(void (^)(NSURLSessionDataTask *, NSError *))failure; 12 | @end 13 | 14 | @implementation AFHTTPSessionManager (Synchronous) 15 | 16 | - (id)synchronouslyPerformMethod:(NSString *)method 17 | URLString:(NSString *)URLString 18 | parameters:(NSDictionary *)parameters 19 | headers:(NSDictionary *)headers 20 | task:(NSURLSessionDataTask *__autoreleasing *)taskPtr 21 | error:(NSError *__autoreleasing *)outError { 22 | 23 | // Prevent the most common deadlock. When this method is invoked from the main 24 | // thread, and the session manager's completion queue is the main queue, the 25 | // semaphore will not be released. This method will never return. 26 | // 27 | // You really should not perform a synchronous network request on the main 28 | // thread on iOS, as it's likely to cause a crash when run outside the debugger. 29 | // You probably should not on OS X either, as it's likely to cause lags in the 30 | // UI. 31 | // 32 | // If you must dispatch from the main queue, create a new queue for the 33 | // completion handler: 34 | // 35 | // manager.completionQueue = dispatch_queue_create("AFNetworking+Synchronous", NULL); 36 | // 37 | if ([NSThread isMainThread]) { 38 | if (self.completionQueue == nil || self.completionQueue == dispatch_get_main_queue()) { 39 | @throw 40 | [NSException exceptionWithName:NSInvalidArgumentException 41 | reason:@"Can't make a synchronous request on the same queue as the completion handler" 42 | userInfo:nil]; 43 | } 44 | } 45 | 46 | __block id responseObject = nil; 47 | __block NSError *error = nil; 48 | 49 | // Thanks @tewha for this suggestion. 50 | // https://github.com/AFNetworking/AFNetworking/issues/1804#issuecomment-100396741 51 | dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); 52 | NSURLSessionDataTask *task = 53 | [self dataTaskWithHTTPMethod:method 54 | URLString:URLString 55 | parameters:parameters 56 | headers:headers 57 | uploadProgress:nil 58 | downloadProgress:nil 59 | success: 60 | ^(NSURLSessionDataTask * _Nonnull unusedTask, id _Nullable resp) { 61 | responseObject = resp; 62 | dispatch_semaphore_signal(semaphore); 63 | } 64 | failure: 65 | ^(NSURLSessionDataTask * _Nullable unusedTask, NSError * _Nonnull err) { 66 | error = err; 67 | dispatch_semaphore_signal(semaphore); 68 | }]; 69 | 70 | [task resume]; 71 | dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); 72 | 73 | if (taskPtr != nil) *taskPtr = task; 74 | if (outError != nil) *outError = error; 75 | 76 | return responseObject; 77 | } 78 | 79 | - (id)syncGET:(NSString *)URLString 80 | parameters:(NSDictionary *)parameters 81 | headers:(NSDictionary *)headers 82 | task:(NSURLSessionDataTask *__autoreleasing *)taskPtr 83 | error:(NSError *__autoreleasing *)outError 84 | { 85 | return [self synchronouslyPerformMethod:@"GET" 86 | URLString:URLString 87 | parameters:parameters 88 | headers:headers 89 | task:taskPtr 90 | error:outError]; 91 | } 92 | 93 | - (id)syncPOST:(NSString *)URLString 94 | parameters:(NSDictionary *)parameters 95 | headers:(NSDictionary *)headers 96 | task:(NSURLSessionDataTask *__autoreleasing *)taskPtr 97 | error:(NSError *__autoreleasing *) outError 98 | { 99 | return [self synchronouslyPerformMethod:@"POST" 100 | URLString:URLString 101 | parameters:parameters 102 | headers:headers 103 | task:taskPtr 104 | error:outError]; 105 | } 106 | 107 | - (id)syncPUT:(NSString *)URLString 108 | parameters:(NSDictionary *)parameters 109 | headers:(NSDictionary *)headers 110 | task:(NSURLSessionDataTask *__autoreleasing *)taskPtr 111 | error:(NSError *__autoreleasing *) outError 112 | { 113 | return [self synchronouslyPerformMethod:@"PUT" 114 | URLString:URLString 115 | parameters:parameters 116 | headers:headers 117 | task:taskPtr 118 | error:outError]; 119 | } 120 | 121 | - (id)syncDELETE:(NSString *)URLString 122 | parameters:(NSDictionary *)parameters 123 | headers:(NSDictionary *)headers 124 | task:(NSURLSessionDataTask *__autoreleasing *)taskPtr 125 | error:(NSError *__autoreleasing *) outError 126 | { 127 | return [self synchronouslyPerformMethod:@"DELETE" 128 | URLString:URLString 129 | parameters:parameters 130 | headers:headers 131 | task:taskPtr 132 | error:outError]; 133 | } 134 | 135 | - (id)syncPATCH:(NSString *)URLString 136 | parameters:(NSDictionary *)parameters 137 | headers:(NSDictionary *)headers 138 | task:(NSURLSessionDataTask *__autoreleasing *)taskPtr 139 | error:(NSError *__autoreleasing *) outError 140 | { 141 | return [self synchronouslyPerformMethod:@"PATCH" 142 | URLString:URLString 143 | parameters:parameters 144 | headers:headers 145 | task:taskPtr 146 | error:outError]; 147 | } 148 | 149 | @end 150 | -------------------------------------------------------------------------------- /4.x/TestProject/Podfile: -------------------------------------------------------------------------------- 1 | use_frameworks! 2 | target 'Tests' do 3 | pod 'AFNetworking-Synchronous/3.x', :path => '../../' 4 | 5 | pod 'Specta' 6 | pod 'Expecta' 7 | end 8 | 9 | -------------------------------------------------------------------------------- /4.x/TestProject/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - AFNetworking (3.1.0): 3 | - AFNetworking/NSURLSession (= 3.1.0) 4 | - AFNetworking/Reachability (= 3.1.0) 5 | - AFNetworking/Security (= 3.1.0) 6 | - AFNetworking/Serialization (= 3.1.0) 7 | - AFNetworking/UIKit (= 3.1.0) 8 | - AFNetworking-Synchronous/3.x (2.0.0-dev): 9 | - AFNetworking (~> 3.0) 10 | - AFNetworking/NSURLSession (3.1.0): 11 | - AFNetworking/Reachability 12 | - AFNetworking/Security 13 | - AFNetworking/Serialization 14 | - AFNetworking/Reachability (3.1.0) 15 | - AFNetworking/Security (3.1.0) 16 | - AFNetworking/Serialization (3.1.0) 17 | - AFNetworking/UIKit (3.1.0): 18 | - AFNetworking/NSURLSession 19 | - Expecta (1.0.5) 20 | - Specta (1.0.6) 21 | 22 | DEPENDENCIES: 23 | - AFNetworking-Synchronous/3.x (from `../../`) 24 | - Expecta 25 | - Specta 26 | 27 | EXTERNAL SOURCES: 28 | AFNetworking-Synchronous: 29 | :path: "../../" 30 | 31 | SPEC CHECKSUMS: 32 | AFNetworking: 5e0e199f73d8626b11e79750991f5d173d1f8b67 33 | AFNetworking-Synchronous: 7993907e716221b1660feb98447d504cb4645c82 34 | Expecta: e1c022fcd33910b6be89c291d2775b3fe27a89fe 35 | Specta: f506f3a8361de16bc0dcf3b17b75e269072ba465 36 | 37 | PODFILE CHECKSUM: 2cd42aaceb64b06d36f7d78000de64d42cb0d406 38 | 39 | COCOAPODS: 1.2.0 40 | -------------------------------------------------------------------------------- /4.x/TestProject/TestProject.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 2ECD212AF18571ED7786CC69 /* Pods_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6DCCCE739AB09E4629043F98 /* Pods_Tests.framework */; }; 11 | 9E9BDAA81E7982F10031B02C /* Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 9E9BDAA71E7982F10031B02C /* Tests.m */; }; 12 | /* End PBXBuildFile section */ 13 | 14 | /* Begin PBXFileReference section */ 15 | 38550BECD10EC4FF6335C28C /* Pods-Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-Tests/Pods-Tests.release.xcconfig"; sourceTree = ""; }; 16 | 6DCCCE739AB09E4629043F98 /* Pods_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 17 | 9E9BDAA41E7982F10031B02C /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 18 | 9E9BDAA71E7982F10031B02C /* Tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Tests.m; sourceTree = ""; }; 19 | 9E9BDAA91E7982F10031B02C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 20 | F715685C59413BB311540C7B /* Pods-Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Tests/Pods-Tests.debug.xcconfig"; sourceTree = ""; }; 21 | /* End PBXFileReference section */ 22 | 23 | /* Begin PBXFrameworksBuildPhase section */ 24 | 9E9BDAA11E7982F10031B02C /* Frameworks */ = { 25 | isa = PBXFrameworksBuildPhase; 26 | buildActionMask = 2147483647; 27 | files = ( 28 | 2ECD212AF18571ED7786CC69 /* Pods_Tests.framework in Frameworks */, 29 | ); 30 | runOnlyForDeploymentPostprocessing = 0; 31 | }; 32 | /* End PBXFrameworksBuildPhase section */ 33 | 34 | /* Begin PBXGroup section */ 35 | 854103492BD3D5298BD37401 /* Pods */ = { 36 | isa = PBXGroup; 37 | children = ( 38 | F715685C59413BB311540C7B /* Pods-Tests.debug.xcconfig */, 39 | 38550BECD10EC4FF6335C28C /* Pods-Tests.release.xcconfig */, 40 | ); 41 | name = Pods; 42 | sourceTree = ""; 43 | }; 44 | 9C5B2A581FCB18A2F3F9F534 /* Frameworks */ = { 45 | isa = PBXGroup; 46 | children = ( 47 | 6DCCCE739AB09E4629043F98 /* Pods_Tests.framework */, 48 | ); 49 | name = Frameworks; 50 | sourceTree = ""; 51 | }; 52 | 9E9BDA991E7981A60031B02C = { 53 | isa = PBXGroup; 54 | children = ( 55 | 9E9BDAA61E7982F10031B02C /* Tests */, 56 | 9E9BDAA51E7982F10031B02C /* Products */, 57 | 854103492BD3D5298BD37401 /* Pods */, 58 | 9C5B2A581FCB18A2F3F9F534 /* Frameworks */, 59 | ); 60 | sourceTree = ""; 61 | }; 62 | 9E9BDAA51E7982F10031B02C /* Products */ = { 63 | isa = PBXGroup; 64 | children = ( 65 | 9E9BDAA41E7982F10031B02C /* Tests.xctest */, 66 | ); 67 | name = Products; 68 | sourceTree = ""; 69 | }; 70 | 9E9BDAA61E7982F10031B02C /* Tests */ = { 71 | isa = PBXGroup; 72 | children = ( 73 | 9E9BDAA71E7982F10031B02C /* Tests.m */, 74 | 9E9BDAA91E7982F10031B02C /* Info.plist */, 75 | ); 76 | path = Tests; 77 | sourceTree = ""; 78 | }; 79 | /* End PBXGroup section */ 80 | 81 | /* Begin PBXNativeTarget section */ 82 | 9E9BDAA31E7982F10031B02C /* Tests */ = { 83 | isa = PBXNativeTarget; 84 | buildConfigurationList = 9E9BDAAC1E7982F10031B02C /* Build configuration list for PBXNativeTarget "Tests" */; 85 | buildPhases = ( 86 | B6E96878860E900085C2F4D0 /* [CP] Check Pods Manifest.lock */, 87 | 9E9BDAA01E7982F10031B02C /* Sources */, 88 | 9E9BDAA11E7982F10031B02C /* Frameworks */, 89 | 9E9BDAA21E7982F10031B02C /* Resources */, 90 | 08BD843668D5CB0F7D21D38C /* [CP] Embed Pods Frameworks */, 91 | EC436F7897D37E7B0AEA4FAD /* [CP] Copy Pods Resources */, 92 | ); 93 | buildRules = ( 94 | ); 95 | dependencies = ( 96 | ); 97 | name = Tests; 98 | productName = Tests; 99 | productReference = 9E9BDAA41E7982F10031B02C /* Tests.xctest */; 100 | productType = "com.apple.product-type.bundle.unit-test"; 101 | }; 102 | /* End PBXNativeTarget section */ 103 | 104 | /* Begin PBXProject section */ 105 | 9E9BDA9A1E7981A60031B02C /* Project object */ = { 106 | isa = PBXProject; 107 | attributes = { 108 | LastUpgradeCheck = 0820; 109 | TargetAttributes = { 110 | 9E9BDAA31E7982F10031B02C = { 111 | CreatedOnToolsVersion = 8.2.1; 112 | ProvisioningStyle = Automatic; 113 | }; 114 | }; 115 | }; 116 | buildConfigurationList = 9E9BDA9D1E7981A60031B02C /* Build configuration list for PBXProject "TestProject" */; 117 | compatibilityVersion = "Xcode 3.2"; 118 | developmentRegion = English; 119 | hasScannedForEncodings = 0; 120 | knownRegions = ( 121 | en, 122 | ); 123 | mainGroup = 9E9BDA991E7981A60031B02C; 124 | productRefGroup = 9E9BDAA51E7982F10031B02C /* Products */; 125 | projectDirPath = ""; 126 | projectRoot = ""; 127 | targets = ( 128 | 9E9BDAA31E7982F10031B02C /* Tests */, 129 | ); 130 | }; 131 | /* End PBXProject section */ 132 | 133 | /* Begin PBXResourcesBuildPhase section */ 134 | 9E9BDAA21E7982F10031B02C /* Resources */ = { 135 | isa = PBXResourcesBuildPhase; 136 | buildActionMask = 2147483647; 137 | files = ( 138 | ); 139 | runOnlyForDeploymentPostprocessing = 0; 140 | }; 141 | /* End PBXResourcesBuildPhase section */ 142 | 143 | /* Begin PBXShellScriptBuildPhase section */ 144 | 08BD843668D5CB0F7D21D38C /* [CP] Embed Pods Frameworks */ = { 145 | isa = PBXShellScriptBuildPhase; 146 | buildActionMask = 2147483647; 147 | files = ( 148 | ); 149 | inputPaths = ( 150 | ); 151 | name = "[CP] Embed Pods Frameworks"; 152 | outputPaths = ( 153 | ); 154 | runOnlyForDeploymentPostprocessing = 0; 155 | shellPath = /bin/sh; 156 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Tests/Pods-Tests-frameworks.sh\"\n"; 157 | showEnvVarsInLog = 0; 158 | }; 159 | B6E96878860E900085C2F4D0 /* [CP] Check Pods Manifest.lock */ = { 160 | isa = PBXShellScriptBuildPhase; 161 | buildActionMask = 2147483647; 162 | files = ( 163 | ); 164 | inputPaths = ( 165 | ); 166 | name = "[CP] Check Pods Manifest.lock"; 167 | outputPaths = ( 168 | ); 169 | runOnlyForDeploymentPostprocessing = 0; 170 | shellPath = /bin/sh; 171 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; 172 | showEnvVarsInLog = 0; 173 | }; 174 | EC436F7897D37E7B0AEA4FAD /* [CP] Copy Pods Resources */ = { 175 | isa = PBXShellScriptBuildPhase; 176 | buildActionMask = 2147483647; 177 | files = ( 178 | ); 179 | inputPaths = ( 180 | ); 181 | name = "[CP] Copy Pods Resources"; 182 | outputPaths = ( 183 | ); 184 | runOnlyForDeploymentPostprocessing = 0; 185 | shellPath = /bin/sh; 186 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Tests/Pods-Tests-resources.sh\"\n"; 187 | showEnvVarsInLog = 0; 188 | }; 189 | /* End PBXShellScriptBuildPhase section */ 190 | 191 | /* Begin PBXSourcesBuildPhase section */ 192 | 9E9BDAA01E7982F10031B02C /* Sources */ = { 193 | isa = PBXSourcesBuildPhase; 194 | buildActionMask = 2147483647; 195 | files = ( 196 | 9E9BDAA81E7982F10031B02C /* Tests.m in Sources */, 197 | ); 198 | runOnlyForDeploymentPostprocessing = 0; 199 | }; 200 | /* End PBXSourcesBuildPhase section */ 201 | 202 | /* Begin XCBuildConfiguration section */ 203 | 9E9BDA9E1E7981A60031B02C /* Debug */ = { 204 | isa = XCBuildConfiguration; 205 | buildSettings = { 206 | CLANG_WARN_BOOL_CONVERSION = YES; 207 | CLANG_WARN_CONSTANT_CONVERSION = YES; 208 | CLANG_WARN_EMPTY_BODY = YES; 209 | CLANG_WARN_ENUM_CONVERSION = YES; 210 | CLANG_WARN_INFINITE_RECURSION = YES; 211 | CLANG_WARN_INT_CONVERSION = YES; 212 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 213 | CLANG_WARN_UNREACHABLE_CODE = YES; 214 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 215 | ENABLE_STRICT_OBJC_MSGSEND = YES; 216 | GCC_NO_COMMON_BLOCKS = YES; 217 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 218 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 219 | GCC_WARN_UNDECLARED_SELECTOR = YES; 220 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 221 | GCC_WARN_UNUSED_FUNCTION = YES; 222 | GCC_WARN_UNUSED_VARIABLE = YES; 223 | }; 224 | name = Debug; 225 | }; 226 | 9E9BDA9F1E7981A60031B02C /* Release */ = { 227 | isa = XCBuildConfiguration; 228 | buildSettings = { 229 | CLANG_WARN_BOOL_CONVERSION = YES; 230 | CLANG_WARN_CONSTANT_CONVERSION = YES; 231 | CLANG_WARN_EMPTY_BODY = YES; 232 | CLANG_WARN_ENUM_CONVERSION = YES; 233 | CLANG_WARN_INFINITE_RECURSION = YES; 234 | CLANG_WARN_INT_CONVERSION = YES; 235 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 236 | CLANG_WARN_UNREACHABLE_CODE = YES; 237 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 238 | ENABLE_STRICT_OBJC_MSGSEND = YES; 239 | GCC_NO_COMMON_BLOCKS = YES; 240 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 241 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 242 | GCC_WARN_UNDECLARED_SELECTOR = YES; 243 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 244 | GCC_WARN_UNUSED_FUNCTION = YES; 245 | GCC_WARN_UNUSED_VARIABLE = YES; 246 | }; 247 | name = Release; 248 | }; 249 | 9E9BDAAA1E7982F10031B02C /* Debug */ = { 250 | isa = XCBuildConfiguration; 251 | baseConfigurationReference = F715685C59413BB311540C7B /* Pods-Tests.debug.xcconfig */; 252 | buildSettings = { 253 | ALWAYS_SEARCH_USER_PATHS = NO; 254 | CLANG_ANALYZER_NONNULL = YES; 255 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 256 | CLANG_CXX_LIBRARY = "libc++"; 257 | CLANG_ENABLE_MODULES = YES; 258 | CLANG_ENABLE_OBJC_ARC = YES; 259 | CLANG_WARN_BOOL_CONVERSION = YES; 260 | CLANG_WARN_CONSTANT_CONVERSION = YES; 261 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 262 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 263 | CLANG_WARN_EMPTY_BODY = YES; 264 | CLANG_WARN_ENUM_CONVERSION = YES; 265 | CLANG_WARN_INFINITE_RECURSION = YES; 266 | CLANG_WARN_INT_CONVERSION = YES; 267 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 268 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 269 | CLANG_WARN_UNREACHABLE_CODE = YES; 270 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 271 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 272 | COPY_PHASE_STRIP = NO; 273 | DEBUG_INFORMATION_FORMAT = dwarf; 274 | ENABLE_STRICT_OBJC_MSGSEND = YES; 275 | ENABLE_TESTABILITY = YES; 276 | GCC_C_LANGUAGE_STANDARD = gnu99; 277 | GCC_DYNAMIC_NO_PIC = NO; 278 | GCC_NO_COMMON_BLOCKS = YES; 279 | GCC_OPTIMIZATION_LEVEL = 0; 280 | GCC_PREPROCESSOR_DEFINITIONS = ( 281 | "DEBUG=1", 282 | "$(inherited)", 283 | ); 284 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 285 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 286 | GCC_WARN_UNDECLARED_SELECTOR = YES; 287 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 288 | GCC_WARN_UNUSED_FUNCTION = YES; 289 | GCC_WARN_UNUSED_VARIABLE = YES; 290 | INFOPLIST_FILE = Tests/Info.plist; 291 | IPHONEOS_DEPLOYMENT_TARGET = 10.2; 292 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 293 | MTL_ENABLE_DEBUG_INFO = YES; 294 | ONLY_ACTIVE_ARCH = YES; 295 | PRODUCT_BUNDLE_IDENTIFIER = com.paulmelnikow.Tests; 296 | PRODUCT_NAME = "$(TARGET_NAME)"; 297 | SDKROOT = iphoneos; 298 | }; 299 | name = Debug; 300 | }; 301 | 9E9BDAAB1E7982F10031B02C /* Release */ = { 302 | isa = XCBuildConfiguration; 303 | baseConfigurationReference = 38550BECD10EC4FF6335C28C /* Pods-Tests.release.xcconfig */; 304 | buildSettings = { 305 | ALWAYS_SEARCH_USER_PATHS = NO; 306 | CLANG_ANALYZER_NONNULL = YES; 307 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 308 | CLANG_CXX_LIBRARY = "libc++"; 309 | CLANG_ENABLE_MODULES = YES; 310 | CLANG_ENABLE_OBJC_ARC = YES; 311 | CLANG_WARN_BOOL_CONVERSION = YES; 312 | CLANG_WARN_CONSTANT_CONVERSION = YES; 313 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 314 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 315 | CLANG_WARN_EMPTY_BODY = YES; 316 | CLANG_WARN_ENUM_CONVERSION = YES; 317 | CLANG_WARN_INFINITE_RECURSION = YES; 318 | CLANG_WARN_INT_CONVERSION = YES; 319 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 320 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 321 | CLANG_WARN_UNREACHABLE_CODE = YES; 322 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 323 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 324 | COPY_PHASE_STRIP = NO; 325 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 326 | ENABLE_NS_ASSERTIONS = NO; 327 | ENABLE_STRICT_OBJC_MSGSEND = YES; 328 | GCC_C_LANGUAGE_STANDARD = gnu99; 329 | GCC_NO_COMMON_BLOCKS = YES; 330 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 331 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 332 | GCC_WARN_UNDECLARED_SELECTOR = YES; 333 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 334 | GCC_WARN_UNUSED_FUNCTION = YES; 335 | GCC_WARN_UNUSED_VARIABLE = YES; 336 | INFOPLIST_FILE = Tests/Info.plist; 337 | IPHONEOS_DEPLOYMENT_TARGET = 10.2; 338 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 339 | MTL_ENABLE_DEBUG_INFO = NO; 340 | PRODUCT_BUNDLE_IDENTIFIER = com.paulmelnikow.Tests; 341 | PRODUCT_NAME = "$(TARGET_NAME)"; 342 | SDKROOT = iphoneos; 343 | VALIDATE_PRODUCT = YES; 344 | }; 345 | name = Release; 346 | }; 347 | /* End XCBuildConfiguration section */ 348 | 349 | /* Begin XCConfigurationList section */ 350 | 9E9BDA9D1E7981A60031B02C /* Build configuration list for PBXProject "TestProject" */ = { 351 | isa = XCConfigurationList; 352 | buildConfigurations = ( 353 | 9E9BDA9E1E7981A60031B02C /* Debug */, 354 | 9E9BDA9F1E7981A60031B02C /* Release */, 355 | ); 356 | defaultConfigurationIsVisible = 0; 357 | defaultConfigurationName = Release; 358 | }; 359 | 9E9BDAAC1E7982F10031B02C /* Build configuration list for PBXNativeTarget "Tests" */ = { 360 | isa = XCConfigurationList; 361 | buildConfigurations = ( 362 | 9E9BDAAA1E7982F10031B02C /* Debug */, 363 | 9E9BDAAB1E7982F10031B02C /* Release */, 364 | ); 365 | defaultConfigurationIsVisible = 0; 366 | defaultConfigurationName = Release; 367 | }; 368 | /* End XCConfigurationList section */ 369 | }; 370 | rootObject = 9E9BDA9A1E7981A60031B02C /* Project object */; 371 | } 372 | -------------------------------------------------------------------------------- /4.x/TestProject/TestProject.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /4.x/TestProject/TestProject.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /4.x/TestProject/TestProject.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 14 | 15 | 17 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 39 | 40 | 41 | 42 | 48 | 49 | 51 | 52 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /4.x/TestProject/TestProject.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /4.x/TestProject/Tests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /4.x/TestProject/Tests/Tests.m: -------------------------------------------------------------------------------- 1 | @import Specta; 2 | @import Expecta; 3 | #import "AFNetworking.h" 4 | #import "AFHTTPSessionManager+Synchronous.h" 5 | 6 | @interface Helpers : NSObject 7 | @end 8 | @implementation Helpers 9 | + (NSURL *) baseURL { 10 | NSDictionary *environment = [[NSProcessInfo processInfo] environment]; 11 | return [NSURL URLWithString:environment[@"HTTPBIN_BASE_URL"] ?: @"https://httpbin.org"]; 12 | } 13 | 14 | + (AFHTTPSessionManager *) manager { 15 | AFHTTPSessionManager *manager = 16 | [[AFHTTPSessionManager alloc] initWithBaseURL:self.baseURL]; 17 | manager.completionQueue = dispatch_queue_create("AFNetworking+Synchronous", NULL); 18 | return manager; 19 | } 20 | @end 21 | 22 | SpecBegin(AFNetworking1x) 23 | 24 | describe(@"AFHTTPClient+Synchronous", ^{ 25 | 26 | __block NSError *error; 27 | __block AFHTTPSessionManager *manager; 28 | beforeEach(^{ 29 | manager = [Helpers manager]; 30 | error = nil; 31 | }); 32 | 33 | describe(@"For a successful request", ^{ 34 | 35 | it(@"can GET", ^{ 36 | // Execute. 37 | id result = [manager syncGET:@"get" 38 | parameters:nil 39 | headers:nil 40 | task:NULL 41 | error:&error]; 42 | // Confidence check. 43 | expect(error).to.beNil(); 44 | 45 | // Test. 46 | expect(result).notTo.beNil(); 47 | }); 48 | 49 | it(@"passes parameters to the request", ^{ 50 | // Setup. 51 | NSDictionary *params = @{@"foo": @"bar", @"baz": @"123"}; 52 | 53 | // Execute. 54 | id result = [manager syncGET:@"get" 55 | parameters:params 56 | headers:nil 57 | task:NULL 58 | error:&error]; 59 | // Confidence check. 60 | expect(error).to.beNil(); 61 | expect(result).notTo.beNil(); 62 | 63 | // Test. 64 | expect(result[@"args"]).to.equal(params); 65 | }); 66 | 67 | it(@"sets the task pointer", ^{ 68 | // Setup. 69 | NSURLSessionDataTask *task = nil; 70 | 71 | // Execute. 72 | id result = [manager syncGET:@"get" 73 | parameters:nil 74 | headers:nil 75 | task:&task 76 | error:&error]; 77 | // Confidence check. 78 | expect(result).notTo.beNil(); 79 | 80 | // Test. 81 | expect(task).to.beKindOf([NSURLSessionDataTask class]); 82 | }); 83 | }); 84 | 85 | describe(@"For a failed request", ^{ 86 | 87 | it(@"returns nil and sets the error pointer", ^{ 88 | // Execute. 89 | id result = [manager syncGET:@"status/503" 90 | parameters:nil 91 | headers:nil 92 | task:NULL 93 | error:&error]; 94 | // Test. 95 | expect(result).to.beNil(); 96 | expect(error).to.beInstanceOf([NSError class]); 97 | expect(error.localizedDescription).to. 98 | equal(@"Request failed: service unavailable (503)"); 99 | }); 100 | 101 | }); 102 | 103 | describe(@"When running on the main thread", ^{ 104 | 105 | it(@"throws an exception when the completion queue is the main queue", ^{ 106 | // Setup. 107 | manager.completionQueue = dispatch_get_main_queue(); 108 | 109 | // Test. 110 | expect(^{ 111 | [manager syncGET:@"get" parameters:nil task:NULL error:&error]; 112 | }).to.raise(NSInvalidArgumentException); 113 | }); 114 | 115 | it(@"throws an exception when the completion queue is the default", ^{ 116 | // Setup. 117 | manager.completionQueue = nil; 118 | 119 | // Test. 120 | expect(^{ 121 | [manager syncGET:@"get" parameters:nil task:NULL error:&error]; 122 | }).to.raise(NSInvalidArgumentException); 123 | }); 124 | 125 | }); 126 | 127 | }); 128 | 129 | SpecEnd 130 | -------------------------------------------------------------------------------- /AFNetworking-Synchronous.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'AFNetworking-Synchronous' 3 | s.version = '2.0.0-dev' 4 | s.summary = 'Synchronous requests for AFNetworking' 5 | s.description = <<-DESC 6 | A minimal category which extends AFNetworking to support synchronous 7 | requests. Supports AFNetworking 1.x, 2.x, 3.x, and 4.x. 8 | DESC 9 | s.homepage = 'https://github.com/paulmelnikow/AFNetworking-Synchronous' 10 | s.license = 'MIT' 11 | s.author = { "Paul Melnikow" => "github@paulmelnikow.com" } 12 | s.source = { :git => 'https://github.com/paulmelnikow/AFNetworking-Synchronous.git', 13 | :tag => "#{s.version}" } 14 | 15 | s.requires_arc = true 16 | 17 | s.ios.deployment_target = '7.0' 18 | s.osx.deployment_target = '10.9' 19 | s.watchos.deployment_target = '2.0' 20 | s.tvos.deployment_target = '9.0' 21 | 22 | s.subspec '4.x' do |sp| 23 | sp.source_files = '4.x/*.{h,m}' 24 | sp.dependency 'AFNetworking', '~> 4.0' 25 | end 26 | 27 | s.subspec '3.x' do |sp| 28 | sp.source_files = '3.x/*.{h,m}' 29 | sp.dependency 'AFNetworking', '~> 3.0' 30 | end 31 | 32 | s.subspec '2.x' do |sp| 33 | sp.ios.deployment_target = '6.0' 34 | sp.osx.deployment_target = '10.8' 35 | sp.source_files = '2.x/*.{h,m}' 36 | sp.dependency 'AFNetworking', '~> 2.0' 37 | end 38 | 39 | s.subspec '1.x' do |sp| 40 | sp.ios.deployment_target = '6.0' 41 | sp.osx.deployment_target = '10.7' 42 | sp.source_files = '1.x/*.{h,m}' 43 | sp.dependency 'AFNetworking', '~> 1.0' 44 | end 45 | 46 | s.default_subspec = '3.x' 47 | 48 | end 49 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # AFNetworking-Synchronous Changelog 2 | 3 | ## 1.1.0 4 | March 15, 2017 5 | 6 | Add support for AFNetworking 3.x. 7 | 8 | ```rb 9 | pod 'AFNetworking', '~> 3.0' 10 | pod 'AFNetworking-Synchronous/3.x' 11 | ``` 12 | 13 | 14 | ## 1.0.0 15 | March 14, 2017 16 | 17 | The API is identical to 0.3.x, which has been stable for some time. 18 | 19 | Clean up documentation. 20 | 21 | 22 | ## 0.3.1 23 | February 24, 2015 24 | 25 | Fix issue in 2.x where method is always GET. 26 | 27 | 28 | ## 0.3.0 29 | December 26, 2014 30 | 31 | Add support for AFNetworking 2.x. 32 | 33 | BREAKING CHANGE: 34 | 35 | Synchronous support for 1.x and 2.x are implemented in two [subspecs][]. 36 | In your Podfile, you must specify the one you need. 37 | 38 | ```rb 39 | pod 'AFNetworking', '~> 1.0' 40 | pod 'AFNetworking-Synchronous/1.x' 41 | ``` 42 | 43 | ```rb 44 | pod 'AFNetworking', '~> 2.0' 45 | pod 'AFNetworking-Synchronous/2.x' 46 | ``` 47 | 48 | Thanks [@EliSchleifer][] for contributing this functionality. 49 | 50 | 51 | ## 0.2.0 52 | November 5, 2013 53 | 54 | Return `-responseData` for instances of `AFHTTPRequestOperation`. 55 | 56 | 57 | ## 0.1.0 58 | September 29, 2013 59 | 60 | Initial release, Cocoapods support. 61 | 62 | 63 | [subspecs]: http://guides.cocoapods.org/syntax/podspec.html#subspec 64 | [@EliSchleifer]: https://github.com/EliSchleifer 65 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013-2017 Paul Melnikow 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | AFNetworking-Synchronous 2 | ======================== 3 | 4 | A minimal category which extends [AFNetworking][] to support synchronous 5 | requests. 6 | 7 | [![Version](https://img.shields.io/cocoapods/v/AFNetworking-Synchronous.svg)](http://cocoapods.org/pods/AFNetworking-Synchronous) 8 | [![License](https://img.shields.io/cocoapods/l/AFNetworking-Synchronous.svg?style=flat)](http://cocoapods.org/pods/AFNetworking-Synchronous) 9 | [![Platform](https://img.shields.io/cocoapods/p/AFNetworking-Synchronous.svg?style=flat)](http://cocoapods.org/pods/AFNetworking-Synchronous) 10 | [![Downloads](https://img.shields.io/cocoapods/dm/AFNetworking-Synchronous.svg)](http://cocoapods.org/pods/AFNetworking-Synchronous) 11 | [![Build](https://img.shields.io/travis/paulmelnikow/AFNetworking-Synchronous.svg)](https://travis-ci.org/paulmelnikow/AFNetworking-Synchronous) 12 | 13 | ![It's synchronous](https://raw.githubusercontent.com/paulmelnikow/AFNetworking-Synchronous/assets/synchronized_diving.gif) 14 | 15 | 16 | Usage 17 | ----- 18 | 19 | ### 4.x 20 | 21 | ```rb 22 | pod 'AFNetworking', '~> 4.0' 23 | pod 'AFNetworking-Synchronous/4.x' 24 | ``` 25 | 26 | ```objective-c 27 | #import 28 | #import 29 | 30 | AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; 31 | NSError *error = nil; 32 | NSData *result = [manager syncGET:@"/document/123" 33 | parameters:paramDict 34 | headers:headerDict 35 | task:NULL 36 | error:&error]; 37 | ``` 38 | 39 | Your synchronous request will never return if it is dispatched on the session 40 | manager's completion queue. 41 | 42 | You really should not perform a synchronous network request on the main thread 43 | on iOS, as it's likely to cause a crash when run outside the debugger. You 44 | probably should not on OS X either, as it's likely to cause lags in the UI. 45 | 46 | If you must do so, create a separate queue for the completion handlers: 47 | 48 | ```objective-c 49 | manager.completionQueue = dispatch_queue_create("AFNetworking+Synchronous", NULL); 50 | ``` 51 | 52 | 53 | ### 3.x 54 | 55 | ```rb 56 | pod 'AFNetworking', '~> 3.0' 57 | pod 'AFNetworking-Synchronous/3.x' 58 | ``` 59 | 60 | ```objective-c 61 | #import 62 | #import 63 | 64 | AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; 65 | NSError *error = nil; 66 | NSData *result = [manager syncGET:@"/document/123" 67 | parameters:paramDict 68 | task:NULL 69 | error:&error]; 70 | ``` 71 | 72 | Your synchronous request will never return if it is dispatched on the session 73 | manager's completion queue. 74 | 75 | You really should not perform a synchronous network request on the main thread 76 | on iOS, as it's likely to cause a crash when run outside the debugger. You 77 | probably should not on OS X either, as it's likely to cause lags in the UI. 78 | 79 | If you must do so, create a separate queue for the completion handlers: 80 | 81 | ```objective-c 82 | manager.completionQueue = dispatch_queue_create("AFNetworking+Synchronous", NULL); 83 | ``` 84 | 85 | ### 2.x 86 | 87 | ```rb 88 | pod 'AFNetworking', '~> 2.0' 89 | pod 'AFNetworking-Synchronous/2.x' 90 | ``` 91 | 92 | ```objective-c 93 | #import 94 | #import 95 | 96 | AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; 97 | NSError *error = nil; 98 | NSData *result = [manager syncGET:@"/document/123" 99 | parameters:paramDict 100 | operation:NULL 101 | error:&error]; 102 | ``` 103 | 104 | Currently there is no support for AFHTTPSessionManager. 105 | 106 | ### 1.x 107 | 108 | ```rb 109 | pod 'AFNetworking', '~> 1.0' 110 | pod 'AFNetworking-Synchronous/1.x' 111 | ``` 112 | 113 | ```objective-c 114 | #import 115 | #import 116 | 117 | AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:...]; 118 | NSError *error = nil; 119 | NSData *result = [client synchronouslyGetPath:@"/document/123" 120 | parameters:paramDict 121 | operation:NULL 122 | error:&error]; 123 | ``` 124 | 125 | 126 | Discussion 127 | ---------- 128 | 129 | ### First, consider adopting an asynchronous design 130 | 131 | Before you decide to use this category, consider whether you can adopt an 132 | asynchronous design instead. As @mattt wrote, asynchronism a tough thing to 133 | get your head around, but it's well worth the mental overhead. Rather than 134 | creating methods that fetch and return network data, use blocks or delegate 135 | methods to call back with the results when you have them. 136 | 137 | Using the asynchronous API has many advantages: 138 | 139 | - When you start an operation on the main thread, you return control to the 140 | run loop immediately, so your UI can remains responsive. Blocking the main 141 | thread for a long time is never a good idea. "Be responsive," Apple urges 142 | in the OS X user experience guidelines. Asynchronous network operations 143 | allow you to do that. 144 | - AFNetworking makes asynchronous code easy to write and easy to read. With 145 | block-based success and failure handlers, you don't need to implement 146 | delegate protocols or provide selectors for callbacks. 147 | - AFNetworking and Grand Central Dispatch take care of threading for you, so 148 | your code does not need to manage threads, run selectors in the background, 149 | or invoke dispatch_async. Your completion blocks will be executed on the 150 | main thread (unless you configure the operations otherwise). 151 | - You can provide a better user experience while waiting for a response. 152 | Networks are unreliable, particularly for mobile users, and servers can be 153 | bogged down. Your users' experiences will be better if you design for a slow 154 | connection, which you can only do asynchronously. 155 | 156 | However, in some cases, a synchronous response is better, such as when the 157 | document architecture or another framework is handling the multithreading for 158 | you, and expects a synchronous result. This code attempts to provide a safe 159 | and reliable way to use the framework synchronously. 160 | 161 | While it overrides the default success and failure queues to avoid a deadlock, 162 | it can't anticipate every possible situation. In particular, you should not 163 | set the queue from which you're invoking as the processing queue, which will 164 | cause a deadlock. 165 | 166 | ### The main thread 167 | 168 | You shouldn't call these methods from the main thread. On iOS, if your 169 | application enters the background while one of these methods is running on the 170 | main thread, a deadlock may result and your application could be terminated. 171 | 172 | ### AFImageRequestOperation processingBlock and custom operation subclasses 173 | 174 | This category is suitable for most of the request operation subclasses built 175 | into AFNetworking, which process their response objects synchronously. 176 | 177 | **If you're using the processingBlock on AFImageRequestOperation, which 178 | contains essential processing in the completion handler, or your subclass 179 | performs other asynchronous processing in the completion handler, use the 180 | version in the [using-completion-blocks branch][using-completion-blocks].** 181 | 182 | All custom subclasses must override `-responseObject`. See `AFHTTPRequestOperation+ResponseObject.h` for more information. 183 | 184 | 185 | Development 186 | ----------- 187 | 188 | This project includes integration tests which use the delightful service 189 | [httpbin][]. To run them, run `pod install` inside the `TestProject` folder, 190 | then load the workspace and execute the test action. 191 | 192 | [httpbin]: https://httpbin.org/ 193 | 194 | 195 | Acknowledgements 196 | ---------------- 197 | 198 | - [EliSchleifer][] for AFNetworking 2.x support 199 | 200 | 201 | License 202 | ------- 203 | 204 | This project is licensed under the MIT license. 205 | 206 | 207 | [EliSchleifer]: https://github.com/EliSchleifer 208 | [AFNetworking]: https://github.com/AFNetworking/AFNetworking 209 | [using-completion-blocks]: https://github.com/paulmelnikow/AFNetworking-Synchronous/tree/using-completion-blocks 210 | --------------------------------------------------------------------------------