0

Suppose I have a simple UIView class called 'ViewController' like this that access 'API' class for POST request.

@implementation ViewController
- (void)viewDidLoad {
    api = [[API alloc] init];
    [api postData];
}
@end

The API class will open the NSURLSession and post data

@implementation API
- (void)postData {
    [[session dataTaskWithRequest:rq completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

        // show Alert in ViewController if response code is 200

    }] resume];
}
@end

How can I show a simple alert (or modify any UIView related objects) from the completionHandler in API class? I'm quite new in block concept. What is the best way to solve this?

Best regards.

kaitosenpai
  • 973
  • 1
  • 7
  • 12

1 Answers1

1

There are more than one ways to do this, but here is one thing you can do: add a completion block to your postData method. Here is an example:

- (void)postDataWithCompletion:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completionBlock {
    [[session dataTaskWithRequest:rq completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        dispatch_async(dispatch_get_main_queue(), ^{
            if (completionBlock()) {
                completionBlock(data, response, error);
            }
        });
    }] resume];
}

This will allow you to call your postData method with a completion handler, so you can use the data returned on your view controller. Here is how your call would look in your view controller:

@implementation ViewController

- (void)viewDidLoad {
    api = [[API alloc] init];
    [api postDataWithCompletion:^(NSData *, NSURLResponse *, NSError *) {
        // update your view controller here with the right data
    }];
}

@end    

Please bear in mind that this is just an example of how to use blocks - returning raw NSData and NSURLSession objects to a view controller is bad practice, and you should write an API layer to transform your values to be friendly with your view controller.

dokun1
  • 2,120
  • 19
  • 37
  • Hmmm, in this way the completionHandler is exposed to the postDataWithCompletion method so it can be retrieved from the ViewController. I will give it a try. Btw, what does the if(completionBlock()) mean? – kaitosenpai May 10 '16 at 08:09
  • It should work fine - let me know how it goes. Checking to see if the completion block exists is common practice with block syntax. Often times, people will set completion blocks to nil in the implementation of a method, and this would cause a crash if you don't handle it properly. Just a matter of safeguarding. – dokun1 May 10 '16 at 08:11
  • Your code is working. Do you familiar with delegate and protocols? You said in your answers that there are many ways to solve this problem. Can you give me another solution in delegate and protocols perhaps? – kaitosenpai May 11 '16 at 03:23