这或多或少是jeffamaphone 所说的,但我提出了一个gist,粗略地说,它应该按照你的要求去做。
我创建了NSOperationQueues 中的NSMutableArray,用作“队列队列”。每次添加 BarrierOperation 对象时,都会在末尾添加一个新的 suspended 操作队列。这将成为addingQueue,您可以在其中添加后续操作。
- (void)addOperation:(NSOperation *)op {
@synchronized (self) {
if ([op isKindOfClass:[BarrierOperation class]]) {
[self addBarrierOperation:(id)op];
} else {
[[self addingQueue] addOperation:op];
}
}
}
// call only from @synchronized block in -addOperation:
- (void)addBarrierOperation:(BarrierOperation *)barrierOp {
[[self addingQueue] setSuspended:YES];
for (NSOperation *op in [[self addingQueue] operations]) {
[barrierOp addDependency:op];
}
[[self addingQueue] addOperation:barrierOp];
// if you are free to set barrierOp.completionBlock, you could skip popCallback and do that
__block typeof(self) weakSelf = self;
NSOperation *popCallback = [NSBlockOperation blockOperationWithBlock:^{
[weakSelf popQueue];
}];
[popCallback addDependency:barrierOp];
[[self addingQueue] addOperation:popCallback];
[[self addingQueue] setSuspended:NO];
NSOperationQueue *opQueue = [[NSOperationQueue alloc] init];
[opQueue setSuspended:YES];
[_queueOfQueues addObject:opQueue]; // fresh empty queue to add to
}
当一个NSOperationQueue 完成时,它会弹出并开始运行下一个。
- (void)popQueue
{
@synchronized (self) {
NSAssert([_queueOfQueues count], @"should always be one to pop");
[_queueOfQueues removeObjectAtIndex:0];
if ([_queueOfQueues count]) {
// first queue is always running, all others suspended
[(NSOperationQueue *)_queueOfQueues[0] setSuspended:NO];
}
}
}
我可能错过了一些重要的事情。魔鬼在细节中。
这对我来说有点像家庭作业。如果是这样,请告诉我我得到了什么等级。 :)
附录:来自abhilash1912 的评论,一个不同但相似的approach。该代码已经测试,所以它已经成功了。但它有点陈旧(截至今天 2 年左右;一些已弃用的方法使用)。此外,我质疑从NSOperationQueue 继承是否是最好的路径,尽管它具有保持熟悉的优点。无论如何,如果您已经阅读了这么多,那么它可能值得一看。
如果您创建或发现了世界上最伟大的 BarrierQueue 类,请在 cmets 或其他方式中告诉我们,以便将其链接起来。