Git Product home page Git Product logo

afasyncnetworking's Introduction

AFAsyncNetworking

A collection of wrapper adapter classes that integrate AFNetworking 2.0 with iAsync library.

Note: We use a fork of AFNetworking since @mattt does not accept pull requests with a static library target.

License : BSD

Wrapping Around AFNetworking to Avoid Callback Hell.

AFNetworking is one of the most famous and widely used networking libraries for iOS. As of version 1.0 it was based on NSOperation API that was capable of managing dependencies between the operations. It was possible to manage execution order and get a single completion point of several parallel operations.

After switching to AFNetworking 2.0 you can only subscribe to NSURLSessionTaskDelegate events using block based callbacks. This means that you end up writing code like this :

NSString* geolocationUrl = [ NSString stringWithFormat: @"http://maps.googleapis.com/maps/api/geocode/json?sensor=true&address=%@", @"Kiev"];

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:geolocationUrl parameters:nil success:^(AFHTTPRequestOperation *operation, id jsonLocation) {
    dispatch_async( myBackgroundQueue, ^{
            NSError* parseError;
    
            id<AWCoordinatesParser> parser = [ AWParserFactory jsonCoordinatesParser ];
            AWCoordinates* coordinates = [ parser parseData: jsonLocation
                                                      error: &parseError ];
            if ( !coordinates )                                          
            {
                 [ self handleError: parseError ];
            }                                          
                                                     
            NSString* weatherUrl = [ NSString stringWithFormat: @"http://api.openweathermap.org/data/2.5/weather?lat=%1.2f&lon=%1.2f", coordinates.latitude, coordinates.longitude ];
            
            
            [manager GET:weatherUrl parameters:nil success:^(AFHTTPRequestOperation *operation, id jsonWeather) {
                  dispatch_async( myBackgroundQueue, ^{
                        NSError* parseError;
                        id<AWWeatherParser> parser = [ AWParserFactory jsonWeatherParser ];
                        AWWeatherInfo* weather = [ parser parseData: weatherJson
                                                              error: &parseError ];
                        if ( !weather )                                          
                        {
                            [ self handleError: parseError ];
                        }                                          
                        
                        dispatch_async( dispatch_get_main_queue(), ^{
                           [ self updateGuiWithWeatherInfo: weather ];
                        });
                  });
            } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                 [ self handleError: error ];
            }];
    });
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
     [ self handleError: error ];
}];

This code solves a typical task of retrieving and parsing weather information from two web services. As you can see, this code has 4 levels of nested callbacks and is hard to maitain. This is known as a "callback hell" problem.

With the help of functional programming ideas imlemented in iAsync library, the same code can be written in a declarative manner and effectively split into subtasks :

+(JFFAsyncOperation)asyncWeatherForAddress:( NSString* )userInput
{
   return bindSequenceOfAsyncOperationsArray
   (
      [ self asyncLocationForAddress: userInput ],
     @[
         [ self parseRawAddressBinder ],
         [ self getWeatherBinder      ],
         [ self parseWeatherBinder    ]
      ]
   );
}

Why Functional Progarmming?

This approach has some benefits over calback hell :

  1. Declarative programming - you perform task decomposition as opposed to having all logic in a bunch of nested blocks.
  2. Operations flow - you can manage operations flow and ensure they are executed in the right order.
  3. Performance - it is possible to cancel asynchronous operations that are no longer needed with the respect to their dependencies. This may be useful when the user leaves some view controller that launched a number of operations.

Creating AFNetworking Operations

It is really easy to create asynchronous operations that use AFNetworking under the hood. Let's take a look at the implementation of asyncLocationForAddress: function from the previous example :

+(JFFAsyncOperation)asyncLocationForAddress:( NSString* )userInput
{
   NSString* requestUrlBase = @"http://maps.googleapis.com/maps/api/geocode/json?sensor=true&address=";
   NSString* requestUrlString =  [ requestUrlBase stringByAppendingString: userInput ];
   
   NSURL* requestUrl = [ NSURL URLWithString: requestUrlString ];
   NSURLRequest* request = [ NSURLRequest requestWithURL: requestUrl ];
   NSParameterAssert( nil != request );   

   AFHTTPSessionManager* session = [ AFHTTPSessionManager manager ];
   session.responseSerializer = [ AFHTTPResponseSerializer serializer ];
   
   JFFAsyncOperation result =
   [ AFAsyncOperationFactory asyncDataTaskOperationFromRequest: request
                                                    andSession: session ];
   
   return [ result copy ];
}

Executing AFNetworking Operations

Invoking an asynchronous operation is as easy as using dispathc_async() API. See the example below :

-(IBAction)getWeatherButtonTapped:(id)sender
{
   [ self.txtAddress resignFirstResponder ];
   
   NSString* address = self.txtAddress.text;
   if ( ![ self validateAddress: address ] )
   {
	  // Handle validation error and show alert
      return;
   }
   
   
   JFFAsyncOperation loader = [ AWOperationsFactory asyncWeatherForAddress: address ];
   
   
   __weak ESViewController* weakSelf = self;
   JFFCancelAsyncOperationHandler onCancel = ^void(BOOL isOperationKeepGoing)
   {
      [ weakSelf onWeatherInfoRequestCancelled ];
   };
   JFFDidFinishAsyncOperationHandler onLoaded = ^void(id result, NSError *error)
   {
      [ weakSelf onWeatherInfoLoaded: result
                           withError: error ];
   };
   JFFCancelAsyncOperation cancelLoad = loader( nil, onCancel, onLoaded );
   self->_cancelLoad = cancelLoad;
   
   self.activityIndicator.hidden = NO;
   [ self.activityIndicator startAnimating ];
}

Useful Links

  1. AFNetworking home page - https://github.com/AFNetworking/AFNetworking
  2. iAsync home page - https://github.com/EmbeddedSources/iAsync
  3. Code examples repository - https://github.com/iAsync/weather-afasync
  4. Callback hell problem definition - http://tirania.org/blog/archive/2013/Aug-15.html
  5. Slides about iAsync library and functional programming in Objective-C - https://github.com/iAsync/iAsyncSlides/blob/master/iAsync-slides.pdf?raw=true

afasyncnetworking's People

Contributors

dodikk avatar

Watchers

Volodymyr Gorbenko avatar  avatar James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.