iosobjective-csemaphorecompletionhandlercompletion-block

How can I wait for a completion block to finish in objective-c ios


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?


Solution

  • - (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);
    }];