首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >嵌套完井块的NSBlockOperation

嵌套完井块的NSBlockOperation
EN

Stack Overflow用户
提问于 2015-10-21 14:39:44
回答 1查看 2.5K关注 0票数 2

应该有一个具有完成块的方法来执行:

代码语言:javascript
复制
[container insert:data
               completion:^(NSDictionary *result, NSError *error) {

               }];

我需要使用NSOperation (而不是GCD调度块,因为我需要更多地控制操作流和取消)来实现这个并发。

现在,假设要执行一个正常的完成块,我可以使用NSBlockOperation如下

代码语言:javascript
复制
- (NSOperation *)executeBlock:(void (^)(void))block
                    inQueue:(NSOperationQueue *)queue
                    completion:(void (^)(BOOL finished))completion
{
    NSOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:block];
    NSOperation *completionOperation = [NSBlockOperation blockOperationWithBlock:^{
        completion(blockOperation.isFinished);
    }];

    [completionOperation addDependency:blockOperation];

    [[NSOperationQueue currentQueue] addOperation:completionOperation];
    [queue addOperation:blockOperation];

    return blockOperation;
}

所以把它叫做

代码语言:javascript
复制
[self executeBlock:^{
        /// my sync code

    }   inQueue:operationQueue
        completion:^(BOOL finished) {

    }];

相反,存在异步代码的问题是:

代码语言:javascript
复制
void (^completionBlock)() = ^void() {
        // this is the NSOperation completion block where sync code is executed
    };

代码语言:javascript
复制
    void (^insertCompletionBlock)(NSDictionary *, NSError *) = ^void(NSDictionary *result, NSError *error) {
      // this is the insert api completion block 
   };

所以有

代码语言:javascript
复制
[container insert:data completion:insertCompletionBlock];

如果我执行嵌套调用,如

代码语言:javascript
复制
[self executeBlock:^{
    [container insert:data
           completion:^(NSDictionary *result, NSError *error) {

           }];

}   inQueue:operationQueue
    completion:^(BOOL finished) {

}];

NSOperation将立即结束,因为insert:completion:方法将在具有完成块的调用之后返回。

那么,如何序列化此执行,以便在执行嵌套的insert:completion:完成块之后调用insert:completion:

使用@Mozilla的解决方案更新了,我推出了一个自定义NSBlockOperation,用于在上面添加一些属性:

代码语言:javascript
复制
@interface MyCloudOperation: NSBlockOperation
@property(nonatomic,strong) id result;
@property(nonatomic,strong) NSError *error;
@end
@implementation MXMCloudOperation
@end

还有这个

代码语言:javascript
复制
MyCloudOperation *blockOp=[[MyCloudOperation alloc] init];
    __weak MXMCloudOperation *weakBlockOp=blockOp;
    [blockOp setCompletionBlock:^{
        if(completion) completion(weakBlockOp.result,weakBlockOp.error);
    }];
    [blockOp addExecutionBlock:^{
        dispatch_semaphore_t mutex = dispatch_semaphore_create(0);
        void (^insertCompletionBlock)(NSDictionary *, NSError *) = ^void(NSDictionary *result, NSError *error) {
            if(error) {
                weakBlockOp.error=error;
                NSLog(@"Error saving to %@ data\n%@", containerName,
                      error.localizedDescription);
            } else {
                weakBlockOp.result=result;
                NSLog(@"Data %@ sent", result);
            }
            dispatch_semaphore_signal(mutex);
        };
        [container insert:data completion:insertCompletionBlock];
        dispatch_semaphore_wait(mutex, DISPATCH_TIME_FOREVER);
    }];
    [operationQueue addOperation:blockOp];

这里我不喜欢的是引用我的NSBlockOperation来传递完成处理程序的参数,但是我现在没有找到更好的解决方案。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-10-22 11:26:58

我使用dispatch_semaphore_t解决了这个问题。

代码语言:javascript
复制
- (void)saveWebDataInternal:(ResponseModel *)data completion:(void(^)(NSArray *))completion
{
        NSBlockOperation *op = [[NSBlockOperation alloc] init];

        op.completionBlock = ^{
            dispatch_async(dispatch_get_main_queue(), ^{
                [self loadCachedDataInternal:completion];
            });
        };

        [op addExecutionBlock:^{
            dispatch_semaphore_t mutex = dispatch_semaphore_create(0);

            [self.cacheDAO asyncImport:data completion:^{
                dispatch_semaphore_signal(mutex);
            }];

            dispatch_semaphore_wait(mutex, DISPATCH_TIME_FOREVER);
        }];

        // start operation
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            [op start];
        });
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33262312

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档