Ios 在For循环后添加具有依赖项的NSO操作
所以我试图在所有的块操作之后执行Ios 在For循环后添加具有依赖项的NSO操作,ios,facebook,multithreading,graph,nsoperation,Ios,Facebook,Multithreading,Graph,Nsoperation,所以我试图在所有的块操作之后执行lastOperation,但出于某种原因,它是先执行的。为什么会这样?添加依赖项是错误的做法吗 [self facebookAccount:^(NSError *error, ACAccount *facebookAccount) { NSOperationQueue *queue = [[NSOperationQueue alloc] init]; [queue setMaxConcurrentOperationCount:1]; NS
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)]中添加以下代码:
然后,控制台的输出为:
(很抱歉,我无法发布照片,但我很快就会提高声誉)
“全部完成”的位置通常在5到10之间变化。因此,我非常确定这取决于哪个NSOperations在队列到达最后一个操作之前完成了GET请求的处理。NSOperations在添加到NSOperationQueue后立即调用其-start方法。因此,当您调用[queue addOperation:operation]时,for循环中的每个操作都会启动
由于lastOperation将操作设置为依赖项,因此每次操作完成时都会调用它,这很可能是在您将lastOperation添加到队列之前发生的。我猜是
performRequestWithHandler:
会立即返回,因为它将回调块作为参数。NSBlockOperation的块一返回,该操作即被视为已完成,因此您的所有操作都会立即完成,直到稍后才会调用它们的完成块
您可能需要将NSOperation子类化并实现并发方法(最小值:
start
,isConcurrent
,isExecuting
,isFinished
),而不是非并发方法(最小值:main
)。来自performRequestWithHandler:
的回调应触发与状态相关属性的键值通知,以指示NSO操作已完成。对于明显的问题,很抱歉,但是您是否有多篇文章?在将操作添加到队列之前,您是否尝试设置依赖关系?我不能说为什么它不工作,但我会尝试重构,看看它是否工作。然后试着从中吸取教训。尝试的一件事是将所有post块添加到单个块操作中,因为它们将被执行,并且只有当所有块都完成时,操作才会被视为完成。你能更清楚地说明你希望看到什么吗?在代码中放入一些NSLog调用,如NSLog(@“1”);然后告诉我们您看到它们的顺序以及您希望看到它们的顺序。是的,很抱歉,这段代码正在添加一组NSOperations,它们发出GET请求并处理对NSOperationQueue的响应。我想知道NSOperationQueue何时不仅完成了GET请求,还完成了对它们的处理。这个问题不包括处理,但它是块“完成(响应)”,它所做的是将解析的“响应”存储在核心数据实体中。“completionAll()”块是在完成所有操作时应该调用的块。我确实尝试在操作之前添加依赖项,但没有成功。因此,我使用ReactiveCocoa进行键值观察,并观察NSOperationQueue的operationCount和NSLogging发送的所有内容。在我的completionAll()中,这是最后一个操作的块,我只需要NSLog(“全部完成”)。我编辑我的帖子是为了向您展示它的样子。因此,如果我让我的操作在执行回调中的任何操作时执行,然后相应地完成,NSOperationQueue将自动等待直到isFinished信号移动到下一个操作?将我的setMaxConcurrentOperationCount保持为1应该可以做到这一点吗?如果是这样,我认为这是一个非常有用的评论,谢谢!当然,我也可以支持这一点;我已经在我的代码库中工作过了。此外,子类化NSOperation
并以这种方式构造代码可以为我提供干净的“工作单元”,我可以根据需要进行转换(或链接在一起)。另外,虽然我相信您可以为块操作提供NSString
名称表示,但在调试时,子类化NSOperation
可以为代码提供更清晰的外观,尤其是在堆栈跟踪中。谢谢,这正是我所需要的。我会在它工作后更新它,但这似乎是一个相当简单的解决方案。
[RACObserve(queue, operationCount) subscribeNext:^(id x) {
NSLog(@"Operation count for queue: %@", x);
}];