Objective c NSOperation中的NSOperationQueue导致应用程序冻结,waitUntilFinished:是

Objective c NSOperation中的NSOperationQueue导致应用程序冻结,waitUntilFinished:是,objective-c,nsoperation,nsoperationqueue,Objective C,Nsoperation,Nsoperationqueue,我已通过AFHTTPClient请求执行NSO操作。在操作结束时,我需要对请求执行另一个N操作,并等待请求完成,以将主操作标记为已完成 @interface MyOperation : OBOperation @end @implementation MyOperation - (id)init { if (self = [super init]) { self.state = OBOperationReadyState; } return sel

我已通过AFHTTPClient请求执行NSO操作。在操作结束时,我需要对请求执行另一个N操作,并等待请求完成,以将主操作标记为已完成

@interface MyOperation : OBOperation

@end

@implementation MyOperation

- (id)init
{
    if (self = [super init]) {
        self.state = OBOperationReadyState;
    }

    return self;
}

- (void)start
{
    self.state = OBOperationExecutingState;

    AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:@"http://google.com"]];
    [client getPath:@"/"
         parameters:nil
            success:^(AFHTTPRequestOperation *operation, id responseObject) {
                NSOperationQueue *queue = [NSOperationQueue new];
                queue.maxConcurrentOperationCount = 1;

                NSMutableArray *ops = [NSMutableArray array];
                for (int i = 1; i < 10; i++) {
                    MyInnerOperation *innerOp = [[MyInnerOperation alloc] initWithNumber:@(i)];
                    [ops addObject:innerOp];
                }

                [queue addOperations:ops waitUntilFinished:YES];

                self.state = OBOperationFinishedState;
            } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                self.state = OBOperationFinishedState;
                NSLog(@"error");
            }];
}

@end
因此,如果我开始手术:

MyOperation *op = [MyOperation new];
[_queue addOperation:op];
NSBlockOperation *endOperation = [NSBlockOperation blockOperationWithBlock:^{
    self.state = OBOperationFinishedState;
}];

NSMutableArray *ops = [NSMutableArray arrayWithObject:endOperation];
for (int i = 1; i < 10; i++) {
    MyInnerOperation *innerOp = [[MyInnerOperation alloc] initWithNumber:@(i)];
    [ops addObject:innerOp];

    [endOperation addDependency:innerOp];
}

[queue addOperations:ops waitUntilFinished:NO];
我在控制台中看到
开始内部操作:1
仅此而已!我的应用程序完全冻结(即使是UI)

经过一番探索,我决定冻结是由
[queue addOperations:ops waituntillfinished:YES]引起的。如果我不等待完成,我的内部操作将按预期工作,但MyOperation在子操作完成之前完成

现在我有了解决依赖块操作的方法:

MyOperation *op = [MyOperation new];
[_queue addOperation:op];
NSBlockOperation *endOperation = [NSBlockOperation blockOperationWithBlock:^{
    self.state = OBOperationFinishedState;
}];

NSMutableArray *ops = [NSMutableArray arrayWithObject:endOperation];
for (int i = 1; i < 10; i++) {
    MyInnerOperation *innerOp = [[MyInnerOperation alloc] initWithNumber:@(i)];
    [ops addObject:innerOp];

    [endOperation addDependency:innerOp];
}

[queue addOperations:ops waitUntilFinished:NO];
NSBlockOperation*操作=[NSBlockOperation blockOperationWithBlock:^{
self.state=OBOperationFinishedState;
}];
NSMutableArray*ops=[NSMutableArray arrayWithObject:endOperation];
对于(int i=1;i<10;i++){
MyInnerOperation*innerOp=[[MyInnerOperation alloc]initWithNumber:@(i)];
[ops addObject:innerOp];
[innerOperationAddDependency:innerOp];
}
[队列添加操作:ops waitUntilFinished:否];
但我仍然完全不明白这次冻结的真正问题是什么。任何解释都会非常有用

oOperation类源:


整个项目:

死锁的原因是AFNetworking将完成块分派到主队列。因此,第一个
success
处理程序中的
waitUntilFinished
将阻塞主队列,直到下级请求完成。但是,这些从属请求无法完成,因为它们需要将完成块分配到主队列,而第一个操作仍在阻塞主队列


显然,您无论如何都不想阻止主队列,但如果阻止等待操作的主队列,则会出现死锁,而这些操作本身就需要主队列。

@striker是的,这种解决方法很好。不过,既然你问了,我对整体设计一点也不感兴趣,一个操作在等待其他操作(你正在使用
maxConcurrentOperationCount
中的一个操作,而这个操作除了等待其他操作之外什么都不做)。我想你这么做是因为你还有其他的行动,这取决于所有其他行动的完成。如果是这样的话,我会考虑一个自定义<代码> CuleTythAdvults/Cuth.Bug参数,或者类似的东西,而不是让第一个操作等待其他操作。我的操作并不仅仅是等待完成所有其他操作。操作使用类似[{id:1,updatedAt:2014-05-24 19:55},{id:2,updatedAt:2014-05-23 19:55}]的结构从服务器上传一些列表,并遍历这些项目,如果updatedAt<上次更新时间(我存储在设备上),我需要执行一个额外的请求,并将其封装在我的主操作中。因此,内部操作甚至可能不会创建。