1

I have a subclass with two methods:

- (void) aPostRequest:(NSString *) urlStr andJSON:(NSMutableDictionary*) jsonDict completion:(void (^)(NSDictionary *, NSError *))completion
{
    NSError *error = nil;

    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
    NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
    NSURL *url = [NSURL URLWithString:urlStr];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];

    [request setHTTPMethod:@"POST"];

    [request addValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    [request addValue:@"application/json" forHTTPHeaderField:@"Accept"];

    // Set up the post data
    NSData *postData = [NSJSONSerialization dataWithJSONObject:jsonDict options:0 error:nil];
    [request setHTTPBody:postData];

    // dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

    NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
    {
        if (!error)
        {
            // convert the NSData response to a dictionary
            NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];

            if (error)
            {
                // There is a parse error
                completion(nil, error);
            }
            else
            {
                // Success
                completion(dictionary, nil);
            }
        }
        else
        {
            // Error from the session
            completion(nil, error);
        }
        // dispatch_semaphore_signal(semaphore);
    }];
    // dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    [postDataTask resume];
}

And this method that calls the method above:

- (NSString *) verifyUnique
{
    // JSON data
    __block NSString *verifyUnique = nil;

    // dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

    // URL string
    NSString *url = @"https://the-website-to-handle-this.com";
    NSMutableDictionary *json = [[NSMutableDictionary alloc] init];
    [json setValue:@"testing" forKey:@"name"];

    [self aPostRequest:url andJSON:json completion:^(NSDictionary *response, NSError *error)
     {
         // dispatch_semaphore_signal(semaphore);

         if (!error) {

         } else {  

             verifyUnique = [response objectForKey:@"uniqueness"]; 

             // return verifyUnique;
             // dispatch_semaphore_signal(semaphore);
         }
     }];

    // dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

    return verifyUnique;
}

I call the function from another view controller class and call [thisClass verifyUnique]; and want it to wait till the answer gets returned. Before it was called in the view controller the UI gets handled with an activity indicator so we can wait. How do I wait for both completion blocks to return?

Meet Doshi
  • 4,241
  • 10
  • 40
  • 81
cdub
  • 24,555
  • 57
  • 174
  • 303
  • That is a swift answer and I'm using objective-c – cdub Jul 03 '16 at 07:58
  • Yep, but the idea there, as well as two of the answers below, is that you're calling asynchronous method, so rather than waiting for response, you should adopt asynchronous patterns yourself, and employ your own completion handler pattern. – Rob Jul 03 '16 at 08:06
  • what's the async pattern? (i don't know swift so it's hard to read for me) – cdub Jul 03 '16 at 08:12
  • See also [Returning method object from inside block](http://stackoverflow.com/q/22267865) – jscs Jul 03 '16 at 16:44
  • 2
    @cdub - An asynchronous pattern is simply a design that is used to solve a particular class of problem, in this case, asynchronous programming. One of the most common asynchronous patterns is the completion handler pattern, i.e. where a method runs asynchronously, but provides a completion handler parameter by which the caller can specify what code should be performed when the asynchronous task completes. In fact, `dataTaskWithRequest` and `aPostRequest` both employ this pattern and we're all suggesting that your own `verifyUnique` just does the same. – Rob Jul 03 '16 at 18:38
  • Yeah that makes sense and I did that and all is smooth now! :) – cdub Jul 04 '16 at 07:31

2 Answers2

2
- (void *) verifyUniqueCompletion:(void (^)(NSString *result, NSError *error))completion
{
    // JSON data
    __block NSString *verifyUnique = nil;

    // dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

    // URL string
    NSString *url = @"https://the-website-to-handle-this.com";
    NSMutableDictionary *json = [[NSMutableDictionary alloc] init];
    [json setValue:@"testing" forKey:@"name"];

    [self aPostRequest:url andJSON:json completion:^(NSDictionary *response, NSError *error)
     {
         // dispatch_semaphore_signal(semaphore);

         if (!error) {
             completion(nil, error);
         } else {  

             verifyUnique = [response objectForKey:@"uniqueness"]; 

             completion(verifyUnique, nil);
             // return verifyUnique;
             // dispatch_semaphore_signal(semaphore);
         }
     }];

    // dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

}

Use this:

[thisClass verifyUniqueCompletion:^(NSString *result, NSError) {
    NSLog(@"result: ", result);
}];
Proton
  • 1,335
  • 1
  • 10
  • 16
  • So if I want to use result above in an if statement it has to be inside of that block correct? like if (result == @Yes – cdub Jul 03 '16 at 08:37
1

You can add completion block as a parameter in verifyUnique:

- (void)verifyUnique:(void (^)(NSString * str))handler{

     // JSON data
     __block NSString *verifyUnique = nil;

     // dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

    // URL string
    NSString *url = @"https://the-website-to-handle-this.com";
    NSMutableDictionary *json = [[NSMutableDictionary alloc] init];
   [json setValue:@"testing" forKey:@"name"];

   [self aPostRequest:url andJSON:json completion:^(NSDictionary *response, NSError *error)
 {
     // dispatch_semaphore_signal(semaphore);

     if (!error) {
          handler(@"");
     } else {  

         verifyUnique = [response objectForKey:@"uniqueness"]; 

         handler(verifyUnique);
     }
 }];


}

and you can use it like this:

[object verifyUnique:^(NSString *verifyUnique) {

}];
Hossam Ghareeb
  • 7,063
  • 3
  • 53
  • 64