Как я могу дождаться завершения блока завершения в target-c ios

У меня есть подкласс с двумя методами:

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

И этот метод, который вызывает метод выше:

- (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;
}

Я вызываю функцию из другого класса контроллера представления и вызываю [thisClass verifyUnique]; и хочу, чтобы она ждала, пока не будет возвращен ответ. Прежде чем он был вызван в контроллере представления, пользовательский интерфейс обрабатывается индикатором активности, поэтому мы можем подождать. Как дождаться возврата обоих блоков завершения?


person cdub    schedule 03.07.2016    source источник
comment
Это быстрый ответ, и я использую Objective-C   -  person cdub    schedule 03.07.2016
comment
Да, но идея здесь, как и в двух ответах ниже, заключается в том, что вы вызываете асинхронный метод, поэтому вместо того, чтобы ждать ответа, вы должны сами принять асинхронные шаблоны и использовать свой собственный шаблон обработчика завершения.   -  person Rob    schedule 03.07.2016
comment
что такое асинхронный шаблон? (я не знаю Swift, поэтому мне трудно читать)   -  person cdub    schedule 03.07.2016
comment
См. также Возврат объекта метода из внутреннего блока   -  person jscs    schedule 03.07.2016
comment
@cdub — асинхронный шаблон — это просто дизайн, который используется для решения определенного класса задач, в данном случае асинхронного программирования. Одним из наиболее распространенных асинхронных шаблонов является шаблон обработчика завершения, т. е. когда метод запускается асинхронно, но предоставляет параметр обработчика завершения, с помощью которого вызывающая сторона может указать, какой код должен быть выполнен после завершения асинхронной задачи. На самом деле, dataTaskWithRequest и aPostRequest используют этот шаблон, и мы все предполагаем, что ваш собственный verifyUnique делает то же самое.   -  person Rob    schedule 03.07.2016
comment
Да, это имеет смысл, и я сделал это, и теперь все гладко! :)   -  person cdub    schedule 04.07.2016


Ответы (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);

}

Использовать этот:

[thisClass verifyUniqueCompletion:^(NSString *result, NSError) {
    NSLog(@"result: ", result);
}];
person Proton    schedule 03.07.2016
comment
Итак, если я хочу использовать приведенный выше результат в операторе if, он должен быть внутри этого блока правильно? нравится, если (результат == @Да - person cdub; 03.07.2016

Вы можете добавить блок завершения в качестве параметра в 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);
     }
 }];


}

и вы можете использовать его так:

[object verifyUnique:^(NSString *verifyUnique) {

}];
person Hossam Ghareeb    schedule 03.07.2016
comment
проверьте мой отредактированный ответ. - person Hossam Ghareeb; 03.07.2016