如何在objective-c ios中等待完成块完成[重复]

Posted

技术标签:

【中文标题】如何在objective-c ios中等待完成块完成[重复]【英文标题】:How can I wait for a completion block to finish in objective-c ios [duplicate] 【发布时间】:2016-07-03 07:22:05 【问题描述】:

我有一个有两种方法的子类:

- (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]; 并希望它等到返回答案。在视图控制器中调用它之前,UI 会使用活动指示器进行处理,因此我们可以等待。如何等待两个完成块返回?

【问题讨论】:

这是一个快速的答案,我正在使用objective-c 是的,但是那里的想法以及下面的两个答案是您正在调用异步方法,因此您应该自己采用异步模式,而不是等待响应,并使用您的自己的完成处理程序模式。 什么是异步模式? (我不知道 swift 所以对我来说很难阅读) 另见Returning method object from inside block @cdub - 异步模式只是一种用于解决特定类别问题的设计,在这种情况下,是异步编程。最常见的异步模式之一是完成处理程序模式,即方法异步运行,但提供完成处理程序参数,调用者可以通过该参数指定异步任务完成时应执行的代码。事实上,dataTaskWithRequestaPostRequest 都采用了这种模式,我们都建议您自己的 verifyUnique 也这样做。 【参考方案1】:
- (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);
];

【讨论】:

所以如果我想在 if 语句中使用上面的结果,它必须在该块内正确吗?比如 if (result == @Yes【参考方案2】:

您可以在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) 

];

【讨论】:

检查我编辑的答案。

以上是关于如何在objective-c ios中等待完成块完成[重复]的主要内容,如果未能解决你的问题,请参考以下文章

Objective-C 完成调用永远不会完成

IOS/Objective-C:从完成块中检索 NSArray

如何从Javascript调用Objective-C方法并将数据发送回iOS中的Javascript?

如何等待 WEBdriver.io 的 Ajax 调用完成

iOS - 如何延迟显示消息“购买成功”以等待验证收据完成

IOS/Objective-C:调用完成块的语法