Nitish
Nitish

Reputation: 14113

Common API request handler

One of the request in my app looks like this :

-(void)login
{
    @try {
        NSString *str = [NSString stringWithFormat:TGURL_LOGIN];
        NSURL *url = [NSURL URLWithString:str];
        [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
        NSDictionary *requestData = @{@"---": ----,
                                      @"---": ----,
                                      @"OutResponse": [NSNumber numberWithInteger:0]};

        NSError *error;
        NSData *postData = [NSJSONSerialization dataWithJSONObject: requestData options:0 error:&error];

        NSString *postLength = [NSString stringWithFormat:@"%lu", (unsigned long)[postData length]];


        NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
        [request setURL:url];
        [request setHTTPMethod:@"POST"];
        [request setValue:@"application/json; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
        [request setValue:postLength forHTTPHeaderField:@"Content-Length"];
        [request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
        [request setHTTPBody:postData];

        NSOperationQueue *queue = [[NSOperationQueue alloc] init];
        __block int iSuccess = 0;

        [NSURLConnection
         sendAsynchronousRequest:request
         queue:queue
         completionHandler:^(NSURLResponse *response,
                             NSData *data,
                             NSError *error) {
             [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
             if ([data length] >0 && error == nil){
                 dispatch_async(dispatch_get_main_queue(), ^{
                     iSuccess = [self parseResponse:data];
                 });
                 dispatch_async(dispatch_get_main_queue(), ^{
                     if(iSuccess == 1)
                     {
                         [[NSUserDefaults standardUserDefaults] setObject:_email.text forKey:@"EmailText"];
                         [[NSUserDefaults standardUserDefaults] setObject:_password.text forKey:@"PasswordText"];
                         [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"User_Logged_In"];
                         [[NSUserDefaults standardUserDefaults]synchronize];

                         [TGProjectHandler saveCookiesToDefaults];
                         [self getUserID];
                     }
                     else if(iSuccess == 3)
                     {
                         [[NSUserDefaults standardUserDefaults] setObject:_email.text forKey:@"EmailText"];
                         [[NSUserDefaults standardUserDefaults] setObject:_password.text forKey:@"PasswordText"];
                         [[NSUserDefaults standardUserDefaults]synchronize];
                         [self.view endEditing:YES];
                         [TGProjectHandler saveCookiesToDefaults];
                         [TGProjectHandler removeLoadingIndicator];
                         [self performSegueWithIdentifier:@"ShowJoinGroup" sender:nil];
                     }
                     else
                     {
                         [[[UIAlertView alloc] initWithTitle: NSLocalizedString(@"Login_failed", nil)
                                                     message:NSLocalizedString(@"Invalid_credentials", nil)
                                                    delegate:nil
                                           cancelButtonTitle:@"OK"
                                           otherButtonTitles:nil] show];
                         [TGProjectHandler removeLoadingIndicator];
                         self.view.userInteractionEnabled = YES;
                     }
                 });
             }
             else if ([data length] == 0 && error == nil){
                 NSLog(@"Empty Response, not sure why?");
             }
             else if (error != nil){
                 NSLog(@"%@", error.description);
                 self.view.userInteractionEnabled = YES;
                 [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Login_failed", nil)
                                             message:error.localizedDescription
                                            delegate:nil
                                   cancelButtonTitle:@"OK"
                                   otherButtonTitles:nil] show];
                 [TGProjectHandler removeLoadingIndicator];
                 self.view.userInteractionEnabled = YES;
             }
         }];
    }
    @catch (NSException *exception) {
        [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
    }
}

This is just one of the service call. Have hundred's of them. Currently I am writing these in the controller itself (Bad approach, I know :)).
I am looking for a way where I can write all the request based code in a single class and access it everywhere.
For a moment I thought about creating Singleton. But I am not sure about creating Singleton for this.
Also thought about creating a protocol, but then finally I have to implement it in the controller.
What are the different patterns I can go for, so that I have a common class for the code I am repeating everywhere.

Upvotes: 0

Views: 660

Answers (3)

Rahul Patel
Rahul Patel

Reputation: 1832

I have done like this, I have made a utility class

this is my webservice.h file

#import <Foundation/Foundation.h>

typedef void (^webCompletionHandler)(NSData *data);
typedef void (^webFailuerHandler)(NSError *error);


@interface WebService : NSObject



-(BOOL)callPostWebService:(NSString *)methodURL
                    param:(NSMutableDictionary *)params
        completionHandler:(webCompletionHandler)completion
          failuerHandler:(webFailuerHandler)failuer;


-(BOOL)callgetWebService:(NSString *)methodURL
        completionHandler:(webCompletionHandler)completion
          failuerHandler:(webFailuerHandler)failuer;



@end

Here i have created two handlers one for completion and another for failure

and these are the two methods for Post and Get

-(void)getWebServiceCall:(NSString *)methodURL
              parameters:(NSMutableDictionary *)parameters
       completionHandler:(webCompletionHandler)completion
          faliureHandler:(webFailureHandler)failure;

-(void)postWebserviceCall:(NSString *)methodURL
                    param:(NSMutableDictionary *)params
        completionHandler:(webCompletionHandler)completion
           faliureHandler:(webFailureHandler)failure;

This is the post method i have used

-(void)callPostWebService:(NSString *)methodURL
                    param:(NSMutableDictionary *)params
        completionHandler:(webCompletionHandler)completion
          failuerHandler:(webFailuerHandler)failuer{

    if(![Utility isReachable]){
        DisplayLocalizedAlert(@"Network is not reachable");
        return;
    }


    NSLog(@"%@",methodURL);
    NSURLRequest *request = [self createRequest:params url:methodURL];

    NSURLSession *session = [NSURLSession sharedSession];
    NSURLSessionDataTask *dataTask =
    [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {


        dispatch_async(dispatch_get_main_queue(), ^{
            if(error != nil){
                failuer(error);
                return ;
            }
            else{

                NSError* error;
                NSDictionary* json = [NSJSONSerialization
                                      JSONObjectWithData:data
                                      options:kNilOptions 
                                      error:&error];
                NSLog(@"json %@",json);

                completion(data);
            }
        });
    }];
    [dataTask resume];

    return true;
}

Then where ever you need to call the webservice you can just call the post and gte method, whichever you require by passing the url and the parameters

[webService postWebserviceCall:strURL param:dicInfo completionHandler:^(id data) {

    } faliureHandler:^(NSError *error) {

    }];

In Swift:

import UIKit
import MobileCoreServices
import CoreLocation


typealias webCompletionHandler = (data : NSData) -> Void;
typealias webFailuerHandler = (error : NSError,isCustomError : Bool) -> Void;


let failureStatusCode = 0;
let successStatusCode = 200;

class WebServiceCall :NSObject {

    static var webService = WebServiceCall();

    override init() {

    }

func callPostWebService(methodURL methodURL :String, param:NSDictionary, completionHandler:webCompletionHandler, failureHandler: webFailuerHandler) -> Bool
    {
        if (isInternetHasConnectivity() == false ) {
            let myError = NSError(domain: "Internet is not available", code: 1001, userInfo: nil)
            failureHandler(error: myError, isCustomError: true);
//            AlertView.showMessageAlert(myError.domain)
            return false;
        }

        let request = self.createRequest(param, strURL: methodURL)

        let serviceTask = NSURLSession.sharedSession().dataTaskWithRequest(request, completionHandler: {
            data, response, error in

            dispatch_async(dispatch_get_main_queue(), { () -> Void in

                if(error != nil){

                    failureHandler(error: error!, isCustomError: false);
                }
                else{

                    let response = Utilities.parseData(data!)
                    let status = response.objectForKey("status") as! Int;

                    if(status == successStatusCode){
                        completionHandler(data: data!)
                    }
                    else {
                        let msg = response.objectForKey("message") as! String
                        let error = NSError(domain: msg, code: Int(status), userInfo: nil);
                        failureHandler(error: error, isCustomError: true);
                    }

                }

            })
        })
        serviceTask.resume();

        return true;
    }
}

Upvotes: 1

ruslan.musagitov
ruslan.musagitov

Reputation: 2124

  1. Create WebService which will handle logic for all requests.
  2. Extract code which repeating in each request.
  3. Move UI related code from WebService to UIViewController class.

Basically UIViewController doesn't know anything about request creation, it only makes a call to WebService and then handle the result.

Upvotes: 0

Santhosh
Santhosh

Reputation: 525

you can try using AFNetworking process to call an API . Here we can write the call in one viewController and can importing that VC , you can call any API any times you need .

Upvotes: 0

Related Questions