Thursday, April 3, 2014

Blocks in Web Service Functions

Hi Everyone! It has been a very long while since I last posted in this blog. This time, I will be making a tutorial in using blocks when we are accessing our API or web services.

Disclaimer: I am also not that 'expert' when it comes to blocks. But I have learned this method throughout my career as an iOS Developer. This is a combination of what I learned from my senior teammates.

By the way, I am using the AFNetworking Framework.

Set up...

1. Create a singleton-patterned APIClient class which is a subclass of AFHTTPClient.

2. Our APIClient interface file should look like this...
#import <Foundation/Foundation.h>
#import "AFHTTPClient.h"

@interface APIClient : AFHTTPClient

+ (APIClient *)sharedClient;


3. And in our implementation file:
#import "APIClient.h"
#import "Constants.h"

@implementation GCAPIClient

We usually have our Development and Production API links, right? So to cater the changes in our Development and Production URLs, let's do this #if #else #endif preprocessor directives.

DevelopmentAPIURL and ProductionAPIURL values are defined in my Constants.h file
Example in Constants.h file:
#define DevelopmentAPIURL @"" 
#define ProductionAPIURL @""
+ (APIClient *)sharedClient 
    static APIClient *_sharedClient = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _sharedClient = [[APIClient alloc] initWithBaseURL:[NSURL URLWithString:DevelopmentAPIURL]];
        _sharedClient = [[APIClient alloc] initWithBaseURL:[NSURL URLWithString:ProductionAPIURL]];

    return _sharedClient;

- (id)initWithBaseURL:(NSURL *)url {
    self = [super initWithBaseURL:url];
    if (!self) {
        return nil;
    return self;

- (NSMutableURLRequest *)requestWithMethod:(NSString *)method path:(NSString *)path parameters:(NSDictionary *)parameters {
    NSMutableURLRequest *request = [super requestWithMethod:method path:path parameters:parameters];
    [request setTimeoutInterval:120];
    return request;



4. Next, I will setup my RequestManager class which is an NSObject subclass. So in my RequestManager.h file:
#import <Foundation/Foundation.h>
#import "AFJSONRequestOperation.h"

typedef void(^ResultBlock)(id results);
typedef void(^FailedBlock)(NSError *error);

@interface RequestManager : NSObject {
     AFJSONRequestOperation *operation;

//We'll get to know more of these later... These methods basically reports a success or fail back to the calling function right after the request has finished executing.
- (void)reportSuccess:(id)results; 
- (void)reportFailure:(NSError *)error;

//We'll also get to know more of these later. These methods will just set a completionBlock if the request reported a Success or failureBlock if the request reported a Failure.
- (void)setCompletionBlock:(ResultBlock)aCompletionBlock;
- (void)setFailedBlock:(FailedBlock)aFailedBlock;

- (void)start; //To Start the request
- (void)cancel; // To Cancel the request. This is important so we can stop the request whenever we want to.
- (BOOL)isExecuting; //To know if the request is being executed or is currently executing
- (BOOL)isFinished; //To know if the request has finished executing

- (void)showSuccessAlertViewWithSuccessMessage:(NSString *)successMessage;
- (void)showFailedAlertViewWithErrorMessage:(NSString *)errorMessage;


//RequestManager.m file
#import "RequestManager.h"
#import "APIClient.h"

@implementation RequestManager {
    ResultBlock completionBlock;
    FailedBlock failureBlock;

#pragma mark - Methods
- (void)reportSuccess:(id)results
    if (completionBlock) {
        dispatch_async(dispatch_get_main_queue(), ^{

- (void)reportFailure:(NSError *)error
    if (failureBlock) {
        dispatch_async(dispatch_get_main_queue(), ^{

#pragma mark - Block Setters
- (void)setCompletionBlock:(ResultBlock)aCompletionBlock
    completionBlock = [aCompletionBlock copy];

- (void)setFailedBlock:(FailedBlock)aFailedBlock
    failureBlock = [aFailedBlock copy];

#pragma mark - Public Methods

//Starts the operation.
- (void)start
    [[APIClient sharedClient] enqueueHTTPRequestOperation:operation];

//The operation has been canceled.
- (void)cancel
    [operation cancel];

//The operation is currently executing.
- (BOOL)isExecuting
    return [operation isExecuting];

// The operation has finished executing.
- (BOOL)isFinished
    return [operation isFinished];

#pragma mark - AlertViews
 Shows a Successful Message Alert
 @param successMessage, a string with Success-related message
- (void)showSuccessAlertViewWithSuccessMessage:(NSString *)successMessage
    UIAlertView *alertError = [[UIAlertView alloc] initWithTitle:@"Success!" message:successMessage delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
    [alertError show];

 Shows a Failed Message Alert
 @param errorMessage, a string with error message of what went wrong why the request failed
- (void)showFailedAlertViewWithErrorMessage:(NSString *)errorMessage
    UIAlertView *alertError = [[UIAlertView alloc] initWithTitle:@"Failed!" message:errorMessage delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
    [alertError show];


5. The last thing that we are going to prepare is our ResultSet. What I mean by ResultSet is that what do we usually RECEIVE from the API? There are results that totally look the same, so we will just have to create an object of what the API usually returns.

So you have to decide what your API usually returns and just modify the list. You can always add or remove variables on the list -- make it as flexible as possible. A flexible and easy to reuse codes are GOOD codes ;-)

Currently, in my part, our API usually returns the following so this is how my ResultSet class currently look like:
#import <Foundation/Foundation.h>

@interface EventResultSet : NSObject

@property NSInteger currentPage;
@property NSInteger resultPageCount;
@property NSInteger resultCount;
@property (nonatomic, strong) NSString *noResultFoundText;
@property (nonatomicstrongNSMutableArray *results;


#import "EventResultSet.h"

@implementation EventResultSet

//Just in case you still didn't know, in the new versions of Xcode, there was no need for us to synthesize the properties anymore. Ain't this nice?


Let the fun of calling API services using blocks begin! :D

Can we first imagine this scenario in our app? Most social applications will need to fetch FEEDS from their server. "Feeds" are the status messages/updates of our "friends" or the people we "follow" and even ourselves. So imagine we have to fetch Feeds from our server...

You may opt to just create a Request class for all the API request functions that we will be making but I suggest we create request classes according to our modules for easier editing in the future.

6. Let's create a FeedRequest class which is a subclass of RequestManager (the one that we did above) for our Feeds module.

This is how my FeedRequest interface file looks like:
#import <Foundation/Foundation.h>
#import "RequestManager.h"

 A customized request class for fetching feeds/feed-related fetches.
@interface FeedRequest : RequestManager

- (void)feedsWithParameters:(NSMutableDictionary *)parameters; //We will know later what the parameters will be.


7. And in my FeedRequest implementation file, I will implement the feedsWithParameters: method.
 Fetch list of events from the server. Increment currentPage in order to fetch more events.
 @param parameters, a dictionary of parameters that may include currentPage or page, and pageSize or limit of results.
- (void)feedsWithParameters:(NSMutableDictionary *)parameters
    ResultSet *resultSet = [[ResultSet alloc] init];
    if (! resultSet.results) {
        resultSet.results = [[NSMutableArray allocinit];

//Path is the string after our APIURL. From the API URL given above, if we get our list of feeds using the URL : then our path value will be "feeds"
NSMutableURLRequest *request = [[GCAPIClient sharedClient] requestWithMethod:@"GET" path:@"feeds" parameters:parameters];
operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
         //Assuming that the returned JSON looks like this. Do not include the texts on maroon to your code, this is just a sample response.
         JSON: {
        currentPage = 1;
        list =     (
            status = Test
            userId = 1234;
            userName = JennCurativo;
            status = Hello
            userId = 1002;
            userName = Polka;
            status = Test 3
            userId = 5688;
            userName = Demitria;
      pageCount = 1;
      resultCount = 6;

       //This is how we save the results:
        resultSet.currentPage = [JSON[@"currentPage"integerValue];
        resultSet.resultCount = [JSON[@"resultCount"integerValue];
        resultSet.resultPageCount = [JSON[@"pageCount"integerValue];
        NSArray *feeds = [JSON[@"list"allObjects];
        for (id result in feeds) {
            Feed *feed = [[Feed allocinit];
            //example on how to set feed values
            //feed.status = result[@"status"];
            [resultSet.results addObject:feed];
        if ([feeds count] == 0) {
            resultSet.noResultFoundText = JSON[@"message"];
        //Report success back to the calling function
        [self reportSuccessresultSet];
    } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
        //Report failure back to the calling function
        [self reportFailure:error];

        //[self showFailedAlertViewWithErrorMessage:error.localizedDescription];

Let's call this API method that we just created from our ViewController.

8. Hey, I'm assuming you have your view controllers ready. So what I'm gonna do is just simply make a function in calling our API method. :D

Inside our view controller .m file, we make a function:

- (void)fetchFeedsFromServer
        NSMutableDictionary *parameters = [[NSMutableDictionary alloc] init];
        parameters[@"pageSize"] = [NSNumber numberWithInt:20];
        parameters[@"page"] = [NSNumber numberWithInteger:++self.currentPage];
        //Add any other parameters needed for your API request

        FeedRequest *request = [[FeedRequest allocinit];
        [request feedsWithParameters:parameters];
        [request setCompletionBlock:^(id results) {
                //Remember the [self reportSuccessresultSet]; code above (#7)? Upon reportingSuccess, it will go inside this block. resultSet is received by results
                //Processing of fetched data.
                ResultSet *resultSet = (ResultSet *)results;
                self.resultPageCount = resultSet.resultPageCount;
                self.currentPage = resultSet.currentPage;
                for (int i = 0; i < [resultSet.results count]; i++) {
                    [self.feedsArray addObject:[resultSet.results objectAtIndex:i]];

                //Update our feeds tableview
               [self.tableView reloadData];
        [request setFailedBlock:^(NSError *error) {
                //If the request fails, the [self reportFailure:error]; will go inside this block.
        [request start];

There may be other BETTER way of doing this so if you have a better suggestion, feel free to comment below. I hope this somehow helps beginners in fetching data from the API.

Another blocks tutorial from one class to another - UP NEXT!


  1. Thank you, Jenn, your tutorial looks rather profound, congratulations! Read more here if you are interested in other tactics of blocking.

  2. Hello Jann,

    Your tutorial is very helpful for me....May i get code for this tutorial?


  3. Its a wonderful post and very helpful, thanks for all this information. You are including better information regarding this topic in an effective way.Thank you so much

    Personal Installment Loans
    Payday Cash Advance loan
    Title Car loan
    Cash Advance Loan

  4. Your posts is really helpful for me.Thanks for your wonderful post.It is really very helpful for us and I have gathered some important information from this blog. so keep sharing..
    Industrial Architecture
    Warehouse Architect
    Civil Engineering Consultants
    Office Interiors in Chennai