0

我正在尝试建立一个相当复杂的 RestKit 操作链。首先,我必须向父对象列表发出请求(我们称之为 parentRequestOperation),并且对于列表中的每个父对象,我必须创建另一个请求操作来获取相关对象(我们称之为 childRequestOperation)。显然,我只能在 parentRequestOperation 的 success() 块中创建 childRequestOperations,因为我之前不知道应该创建多少个以及使用哪些细节。

我想在所有操作完成后得到一些反馈。为此,我用我的处理块创建了一个 NSOperation 实例(我们称它为finishedOperation),向它添加了对 parentRequest 的依赖,并添加到我的 RKObjectManager 的 operationQueue 中。

我的问题是如何在 childRequestOperations 和 finishedOperation 之间进行“会合”。在我创建 childRequestOperation 之后,我尝试将对 childRequestOperation 的依赖添加到 finishedOperation(仍在 parentRequestOperation 的成功块中)。但问题是 RestKit 在与 RKObjectManager 的 operationQueue 不同的调度队列中异步调用成功块,所以一旦 parentRequestOperation 完成,在我可以添加对 childRequestOperation 的新依赖之前,finishedOperation 就会被触发。

在类似情况下设置 finishedOperation 的最佳做法是什么?

4

2 回答 2

1

您可以查看设置successCallbackQueue要使用的操作,并在执行现有的相关操作时将您自己的任务推送到同一个队列中。如果您使用的队列是串行的,那么您可以保证执行顺序。

于 2013-10-02T10:09:10.253 回答
0

最后我想出了一个稍微开箱即用的解决方案。它是一个用资源计数器信号量扩展的 NSObject 子类。此操作仅在信号量达到零时执行。

SemaphoreDependencyOperation.h

@interface SemaphoreDependencyOperation : NSOperation

@property (atomic, readonly) int32_t dependencySemaphore;

-(void)incrementDependencySemaphore;
-(void)decrementDependencySemaphore;

@end

信号量依赖操作.m

#import "SemaphoreDependencyOperation.h"
#include <libkern/OSAtomic.h>

@implementation SemaphoreDependencyOperation

-(void)incrementDependencySemaphore
{
    [self willChangeValueForKey:@"dependencySemaphore"];
    OSAtomicIncrement32(&_dependencySemaphore);
    [self didChangeValueForKey:@"dependencySemaphore"];
}

-(void)decrementDependencySemaphore
{
    [self willChangeValueForKey:@"dependencySemaphore"];
    OSAtomicDecrement32(&_dependencySemaphore);
    [self didChangeValueForKey:@"dependencySemaphore"];
}

+(NSSet *)keyPathsForValuesAffectingIsReady
{
    return [NSSet setWithObject:@"dependencySemaphore"];
}

-(BOOL)isReady
{
    return [super isReady] && _dependencySemaphore <= 0;
}

@end

和用法:

SemaphoreDependencyOperation* trackerOperation = [[UpdateTrackerOperation alloc] init];
[trackerOperation setCompletionBlock:^{
    NSLog(@"Everything done"); 
}];

NSURLRequest* parentRequest = // ...
RKObjectRequestOperation* parentRequestOperation =
  [self.objectManager objectRequestOperationWithRequest:parentRequest
                                                success:
  ^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) 
  {
    // create childRequestOperations based on mappingResult
    for (MyObject* myObject in [mappingResult array]) 
    {
       NSURLRequest* childRequest = // ... create it from myObject
       RKObjectRequestOperation* childRequestOperation = 
         [self.objectManager objectRequestOperationWithRequest:parentRequest
                                                       success:
         ^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) 
         {
           // ...
           [trackerOperation decrementDependencySemaphore];
         }
                                                       failure:nil];

         [self.objectManager enqueueObjectRequestOperation:childRequestOperation];
         [trackerOperation incrementDependencySemaphore];
    }
    [trackerOperation decrementDependencySemaphore];
  }
                                                failure:nil];

[self.objectManager enqueueObjectRequestOperation:parentRequestOperation];
[trackerOperation incrementDependencySemaphore];
[self.objectManager.operationQueue addOperation:trackerOperation];
于 2013-10-03T13:32:03.343 回答