避免嵌套块

时间:2012-09-12 15:36:44

标签: objective-c ios uiviewcontroller block

如果有一个视图控制器想要一次执行一个基于块的任务,那么在完成块执行后如何将控制权返回给视图控制器。

让我们说ViewControllerOne想要执行许多任务,每个任务都依赖于前一个任务的结果,在每个完成块执行完毕后,如何将这个控件返回给viewcontroller?

我开始考虑这个问题,而我正朝着一个深层嵌套的块模式前进,这肯定只会导致其他人阅读或测试它的混淆。

执行任务并且完成块返回下一个任务所需的结果或错误,该任务具有自己的完成任务,下一个任务依赖于此等等。

如何在一个地方管理控件,viewcontroller?

完成块是否只是调用下一个处理下一个任务的函数,使用指向视图控制器(self)的指针来调用它?

3 个答案:

答案 0 :(得分:2)

你想要达到的目标对我来说有点不清楚,但你可以尝试类似的东西:

- (id)performBlocks:(NSArray *)blocks
{
    id state = [self initialState];

    for(id (^block)(id) in blocks)
    {
        state = block(state);

        // do something with state
    }

    return state;
}

由于每个块都取决于前一个块的结果,因此必须按顺序执行它们。您可以传递一个状态对象,该状态对象由每个块更新,然后在对连续块的调用之间传递,您可以根据调用之间的状态进行任何处理。

答案 1 :(得分:1)

这听起来像NSOperation的依赖功能的理想用例。即,

- (void)addDependency:(NSOperation *)operation
- (void)removeDependency:(NSOperation *)operation

您可以使某些操作依赖于其他操作,因此您可以构建操作之间依赖关系的图形。

答案 2 :(得分:1)

关于'给予控制权'回到viewController(VC)的评论没有意义,因为VC通常在runLoop回调中被阻塞,等待某事发生。

如果我理解了你想要的东西,它就有机会在发生所有这些事情的同时获得处理VC的其他消息。定义方法:

{
   NSMutableArray *blocks; // ivar
   BOOL isCanceled;
}
typedef void (^block_t)(id input);

-(void)performBlock:(id)result;

一次创建所有块或悠闲地执行,但将它们添加到块阵列中。每个块都会传递一个传递给它的对象,其中包含所需的工作项。:

block_t b = ^(id input) {
  ... do some work using input;
  NSDictionary *dict = ....; // a possible result of the work
  dispatch_async(dispatch_get_main_queue(), ^{ [self performBlock:dict; } );
};

第一个块被调度到某个队列 - 也可能是后台队列,并将其结果发送回VC:

-(void)performBlock:(id)result
{
  if(isCanceled) { // some other method set this flag
  ...
  } else if([blocks count]) {
    block_t b = [blocks objectAtIndex:0];
    [blocks removeObjectAtIndex:0]; // guessing at method name
    dispatch_async(some queue, b);
  }
}