PromiseKit+AFNetworking is a small category addition to the delightful PromiseKit, enabling it to work with AFNetworking
Objective-C Ruby
Latest commit fa77805 Feb 3, 2017 @csotiriou committed on GitHub Merge pull request #17 from MichiganLabs/master
Bump PromiseKit/CorePromise

PromiseKit+AFNetworking {#welcome}

PromiseKit+AFNetworking is a small category addition to the delightful PromiseKit, enabling it to work with the widely used AFNetworking v 2.0

For the time being, it's a small category addition to the core AFNetworking, facilitating development with the plain AFHTTPRequestOperation and with the AFHTTPRequestOperationManager.

Note regarding PromiseKit 2.0:

PromiseKit+AFNetworking now supports PromiseKit 2.0. Therefore, support for iOS 7 is dropped. If you wish to have PromiseKit + AFNetworking + iOS 7 support, please use a version of ‘AFNetworking-PromiseKit’ earlier than 0.5.0

Note regarding PromiseKit 3.0:

PromiseKit+AFNetworking now supports PromiseKit 3.0. For PromiseKit 3.0, the ambiguity between PMKPromise and AnyPromise has been resolved, and only AnyPromise is used from now on. If you wish to have PromiseKit + AFNetworking + PromiseKit 2.0 support, please use a version of ‘AFNetworking-PromiseKit’ earlier than 0.6.0


You have two options: Either use cocoapods (look into the appropriate section below), or just copy AFNetworking+PromiseKit.h and AFNetworking+PromiseKit.m in your project and use them.

Sample Uses:

Plain HTTP Request

[AFHTTPRequestOperation request:[NSURLRequest requestWithURL:[NSURL URLWithString:@""]]].then(^(id responseObject){
    NSLog(@"operation completed! %@", [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]);
}).catch(^(NSError *error){
    NSLog(@"error: %@", error.localizedDescription);
    NSLog(@"original operation: %@", error.userInfo[AFHTTPRequestOperationErrorKey]);

The above code will immediately execute the HTTP Request by adding it to the current queue, or the main queue if the current queue does not exist. You can also add it to a different queue (see the header file)


self.manager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:nil];
self.manager.responseSerializer = [AFHTTPResponseSerializer serializer];

[self.manager GET:@"" parameters:nil].then(^(id responseObject, AFHTTPRequestOperation *operation){
    NSLog(@"first request completed for operation: %@", operation.request.description);
    return [self.manager GET:@"" parameters:nil];
    NSLog(@"second request completed");
}).catch(^(NSError *error){
    NSLog(@"error happened: %@", error.localizedDescription);
    NSLog(@"original operation: %@", error.userInfo[AFHTTPRequestOperationErrorKey]);

Objects returned by the plain AFHTTPRequestOperationManager are also returned here, as optional arguments (a response object of type 'id' and the AFHTTPRequestOperation). In case of errors, you can use the "catch" command of PromiseKit, and get the error thrown by AFNetworking and the original operation that spawned the error with 'error.userInfo[AFHTTPRequestOperationErrorKey]'

Making concurrent operations is a simple matter of calling "-when" on PMKPromise as described in the official documentation.

[PMKPromise when:@[
    [self.operationManager GET:@"ip" parameters:nil].then(^(){numberOfOperationsCompleted ++;}),
    [self.operationManager GET:@"get" parameters:nil].then(^(){numberOfOperationsCompleted ++;})
        //do something when all operations are finished


New: Now AFHTTPSessionManager is supported, for use with AFNetworking 2.0 and iOS 7

Sample function that logins using an AFHTTPSessionManager below:

- (PMKPromise *)loginWithUserName:(NSString *)userName andPassword:(NSString *)password
    return [self.sessionManager POST:@"api/login" parameters:@{@"user": userName, @"password" : password}].then(^(id responseObject, NSURLSessionDataTask *dataTask){
        //responseObject holds the response returned by AFNetworking
        //dataDask will hold an NSURLSessionDataTask associated with this request, like it happens in AFHTTPSessionManager

Objects returned during these operations are optional here. Maximum arguments in "then()" blocks are "2", a responseObject (that has been deserialized by AFNetworking) and an NSURLSessionDataTask.

Of course, chaining and making concurrent operations work the same way as in AFHTTPRequestOperationManager.

when and getting the NSURLDataTask that initiated the request.

Now you can get the NSURLDataTask that initiated the request when performing multiple concurrent requests with when

[self.sessionManager GETMultiple:@[@"/", @"/", @"/", @"/"] parameters:@[@{},@{},@{},@{}]].then(^(NSArray * responsesArray){
    for (NSDictionary *responseDictionary in responsesArray){
        NSLog(@"task description: %@", responseDictionary[kPMKAFResponseTaskKey]);
        NSLog(@"response object description: %@", responseDictionary[kPMKAFResponseObjectKey]);
[self.operationManager GETMultiple:@[@"/", @"/", @"/", @"/"] parameters:@[@{},@{},@{},@{}]].then(^(NSArray * responsesArray){
    for (NSDictionary *responseDictionary in responsesArray){
        NSLog(@"operation description: %@", responseDictionary[kPMKAFResponseOperationKey]);
        NSLog(@"response object description: %@", responseDictionary[kPMKAFResponseObjectKey]);


Now unit tests are available, which demonstrate the basic functionality and give some basic examples on how to use this category. More unit tests are going to be added in the near future.

Pods integration

You can use the project with CocoaPods. Simply put this line into your podfile:

pod 'PromiseKit-AFNetworking', '~>0.6'

To Do

  • Add more unit tests
  • Add some goodies, in cases where they make sense.

Special Thanks

Special thanks to Jeff Miller ( ) for his fixes and podification of this repo

And, of course Max Howel, for PromiseKit (


I have created this small addition in order to use it in a project I am making. I have had the opportunity to test it in real-life situations, but AFHTTPRequestOperationManager is not tested for DELETE, and PUT operations. If you find a bug, please submit a bug report.

Something missing?

Of course something is missing. I have just began implementing this. If you have suggestions, additions, or you want to add a cool feature, I would be happy to hear about it. Please, please, please, leave your feedback and suggestions to the 'issues' section!