For循环后添加具有依赖关系的NSOperation

时间:2014-07-01 16:17:23

标签: ios facebook multithreading graph nsoperation

所以我尝试在所有块操作之后执行lastOperation,但由于某种原因它首先被执行。为什么是这样?是否以错误的方式添加依赖项?

[self facebookAccount:^(NSError *error, ACAccount *facebookAccount) {
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    [queue setMaxConcurrentOperationCount:1];
    NSBlockOperation *lastOperation = [NSBlockOperation blockOperationWithBlock:completionAll];
    for (NSString *postID in postIDs) {
        NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
            NSString *postIDString = [NSString stringWithFormat:@"https://graph.facebook.com/v2.0/%@", postID];
            NSURL *postIDURL = [NSURL URLWithString:postIDString];
            SLRequest *postIDRequest = [SLRequest requestForServiceType:SLServiceTypeFacebook requestMethod:SLRequestMethodGET URL:postIDURL parameters:nil];
            postIDRequest.account = facebookAccount;

            [postIDRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
                NSError *parseError;
                NSDictionary *response = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingAllowFragments error:&parseError];

                completion(response);
            }];

        }];
        [queue addOperation:operation];
        [lastOperation addDependency:operation];
    }

    [queue addOperation:lastOperation];

}];

如果我在[self facebookAccount:^(NSError * error,ACAccount * facebookAccount)]中添加以下代码:

[RACObserve(queue, operationCount) subscribeNext:^(id x) {
        NSLog(@"Operation count for queue: %@", x);
    }];

然后输出到控制台是:

http://i.imgur.com/efrouOC.png(抱歉,我无法发布图片,但我很快就会获得声誉)

“全部完成”的位置通常在5到10之间变化。所以我很确定这取决于哪个NSOperations在队列到达lastOperation之前完成了处理GET请求。

2 个答案:

答案 0 :(得分:2)

我猜测performRequestWithHandler:会立即返回,因为它需要一个回调块作为其参数。一旦NSBlockOperation的块返回,操作就被认为已完成,因此所有操作都会立即完成,并且只有稍后才会调用它们的完成块。

您可能需要继承NSOperation并实现并发方法(最少:startisConcurrentisExecutingisFinished)而不是非并发方法(最小值:main)。来自performRequestWithHandler:的回调应触发与状态相关的属性的键值通知,以指示NSOperation已完成。

答案 1 :(得分:0)

NSOperations在将它们添加到NSOperationQueue后立即调用它们的-start方法。因此,当你调用[queue addOperation:operation]时,for循环中的每个操作都会被启动;

由于lastOperation将操作设置为依赖项,因此每次操作完成时都会调用它,这可能在将lastOperation添加到队列之前发生。