1
\$\begingroup\$

I load some data from from my webservice via a method using blocks and callbacks.

From my ViewController I make a request to the data loading class and pass the callback block:

- (void)loadRadioStationList
{
    [self.radioDataLoader getRadioStationList:^(NSArray *data, NSDictionary *dictData){

        self.alphabetizedDictionary = [[NSDictionary alloc] initWithDictionary:dictData];
        self.sectionIndexTitles = [[NSArray alloc] initWithArray:data];

        [self.radioStationTableView reloadData];
    }];
}

Then in the dataloading class the method is as so:

-(void) getRadioStationList:(void (^)(NSArray *data, NSDictionary *dictData))callback
{

    NSString *string = RadioStationListURL;
    NSURL *url = [NSURL URLWithString:string];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
    operation.responseSerializer = [AFXMLParserResponseSerializer serializer];

    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {

        NSXMLParser *XMLParser = (NSXMLParser *)responseObject;
        [XMLParser setShouldProcessNamespaces:YES];
        XMLParser.delegate = self;
        [XMLParser parse];

         callback((NSArray*)self.sectionIndexTitles, (NSDictionary*)self.alphabetizedDictionary);

    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {

        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error Retrieving Radio List"
                                                            message:[error localizedDescription]
                                                           delegate:nil
                                                  cancelButtonTitle:@"Ok"
                                                  otherButtonTitles:nil];
        [alertView show];

    }];

    [operation start];

}

It loads the XML file and parses out the data and send the data back to my VC via the callback block.

I've a couple of questions:

  1. Is this an acceptable way of doing this? Would you prefer to see it done another (better) way?
  2. If I was to write an API, would passing the data from the API back to the calling class be a good way to work it, or is there a more suitable method for an API?
\$\endgroup\$
1
+50
\$\begingroup\$

Here is a way how I do it:

Create a class and name it like ClientApi. This class should be a singleton link and be absolutely independent. Also, create a class APIRouter which will return a path for a request. I'm using the AFNetworking framework for communication with different API etc. and JSONModel framework for mapping. Here you can find the full answer about network architecture in iOS apps.

@interface SFAPIClient ()

@property (nonatomic, strong) AFHTTPSessionManager *manager;

@end

@implementation SFAPIClient

+ (instancetype)sharedInstance
{
    static id _sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _sharedInstance = [[[self class] alloc] init];
    });

    return _sharedInstance;
}

If a request should return some data, pass block as a parameter to the method:

- (void)getAllChildsWithCompletion:(void(^)(NSArray *arr, NSError *error))completion
{
    NSString *url = [SFAPIRouter childRoute];
    [self setupRequestSerializer];

    [self.manager GET:url parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSError *error = nil;
        NSArray *arr = //map respons

        if (!error)//if everything good call block with data 
            completion(arr, nil);
        else
            completion(nil, error);


    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error)
     {
        if (completion)
            completion(nil, error);
    }];
}

APIRouter:

static NSString * const kSFServerURL = @"http://0.0.0.0/api/v1";

@implementation SFAPIRouter

+ (NSString *)saveMediaToListRoute
{
    return [kSFServerURL stringByAppendingString:@"/childs"];
}

And then in controller call function from your ClientApi class:

//show activity indicator
[[SFAPIClient sharedInstance] getAllChildsWithCompletion:^(NSArray *arr, NSError *error){
//stop showing activity indicator

if (error)
{
//show alert
return;
}
//do what you need
}];
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.