我必须同步来自RestAPI的大量信息。我必须执行6个RestAPI调用才能完成工作。我用Blocks设计了API调用,如果有的话返回NSError。
这些调用中的3个应该嵌套执行,因为第一个调用将信息提供给其他人并允许执行,而其他3个调用可以独立运行。
由于提高了网络性能,我将同步调用设计如下:

  • 1 NSBlockOperation,它包含第一个嵌套的3个块;
  • 1包含其他三个块的NSBlockOperation;
  • 1我用作“semphore”的NSBlockOperation,告诉我所有工作何时完成。

  • 最后一个NSBlockOperation依赖于前两个NSBlockOperation。

    我还有一个NSOperationQueue,它包含所有三个NSBlockOperation,其中信号灯NSBlockOperation被添加为队列中的最后一个。
    我要实现的结果是:并发调用前两个块,当它们工作完成时,将调用信号量NSBlockOperation并将控件返回给提供UIAlertMessage的用户。

    结果并非先前解释的那样:无需等待 syncAllBlocksInformation 块的结尾即可返回控件。

    在包含NSBlockOperation的代码下面:
    -(void)syncAllBlocksInformation:(void(^)(NSError *error))completion{
    
    __block NSError *blockError = nil;
    
    NSOperation *syncUserInfoOperation = [NSBlockOperation blockOperationWithBlock:^{
        [dataSync syncUserInfo:tfMail.text password:tfPassword.text completion:^(NSError *error, NSNumber *idUser) {
            if(!error){
                [dataSync syncUserfilesInfo:idUser completion:^(NSError *error) {
                    if(!error){
                        [dataSync syncUserBookings:^(NSError *error) {
                            if(error){
                                blockError = error;
                            }
                        }];
                    }
                    else{
                        blockError = error;
                    }
                }];
    
            }
            else{
                blockError = error;
            }
        }];
    }];
    
    
    
    NSBlockOperation *otherSyncOperations = [NSBlockOperation blockOperationWithBlock:^{
        [dataSync syncNewsInfo:^(NSError *error) {
            if(error){
                blockError = error;
                NSLog(@"error %@",error);
            }
        }];
    
    }];
    
    [otherSyncOperations addExecutionBlock:^{
        [dataSync syncLocationsInfo:^(NSError *error) {
            if(error){
                blockError = error;
                NSLog(@"error %@",error);
            }
        }];
    
    }];
    
    [otherSyncOperations addExecutionBlock:^{
        [dataSync syncExoticAnimalTypesAndAnimals:^(NSError *error) {
            if(error){
                blockError = error;
                NSLog(@"error %@",error);
            }
        }];
    }];
    
    
    NSOperation *completionOperation = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"END");
    }];
    
    [completionOperation setCompletionBlock:^{
        NSLog(@"Syc isEx %i",syncUserInfoOperation.isExecuting);
        NSLog(@"other isEx %i",otherSyncOperations.isExecuting);
        completion(blockError);
    }];
    
    NSOperationQueue *opQueue = [NSOperationQueue new];
    
    [completionOperation addDependency:syncUserInfoOperation];
    [completionOperation addDependency:otherSyncOperations];
    
    [opQueue addOperation:syncUserInfoOperation];
    [opQueue addOperation:otherSyncOperations];
    [opQueue addOperation:completionOperation];
    
    }
    

    在这里,在块上方调用的代码:
    -(IBAction)login:(id)sender{
    
    [self dismissKeyboardOpened:nil];
    
    hud=[MBProgressHUD showHUDAddedTo:self.view animated:YES];
    [hud setLabelText:NSLocalizedString(@"login_hud_message", login_hud_message )];
    [hud setMode:MBProgressHUDModeIndeterminate];
    
    [self showHudAndNetworkActivity:YES];
    
    [self syncAllBlocksInformation:^(NSError *error) {
    
        [self showHudAndNetworkActivity:NO];
    
        if(!error){
            NSLog(@"End LOGIN");
            [self showAlert:@"Login" message:@"Login OK" dismiss:YES];
        }
        else{
            [self showAlert:@"Error" message:@"Login NO" dismiss:NO];
        }
    
    }];
    }
    

    怎么了 ?

    最佳答案

    问题是NSBlockOperation用于同步块。一旦其块完成执行,它将为finished如果其块触发了异步方法,则这些异步方法将独立运行。

    例如,当执行syncUserInfoOperation的代码块时,它将触发[dataSync syncUserInfo:...],然后认为自己已完成;它不等待任何完成处理程序触发,或类似的事情。

    一个好的解决方案是创建自己的NSOperation子类。您可能希望为每种数据同步类型创建一个,以便更轻松地设置依赖关系等,但这取决于您。您可以阅读有关如何执行here的所有信息(请务必阅读有关“Configuring Operations for Concurrent Execution”的部分)。

    您还可以创建一个通用的NSOperation子类,该子类带有一个可以异步运行的块。这样做的主要问题是,它可能使您更难处理诸如取消操作之类的事情。

    关于ios - NSBlockOperation,NSOperationQueue和块,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25573374/

    10-12 14:33