Имам NSOperation с AFHTTPClient заявка. В края на операцията трябва да изпълня още 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
Връзка към OBOperation
източник в края на въпроса. Това е прост клас, който добавя полезни методи за контрол на NSOperation
потока
Пример за вътрешна операция:
@interface MyInnerOperation : OBOperation
- (id)initWithNumber:(NSNumber *)number;
@end
@implementation MyInnerOperation
- (id)initWithNumber:(NSNumber *)number
{
if (self = [super init]) {
_number = number;
self.state = OBOperationReadyState;
}
return self;
}
- (void)start
{
self.state = OBOperationExecutingState;
NSLog(@"begin inner operation: %@", _number);
AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:@"http://google.com"]];
[client getPath:@"/"
parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"inner operation success: %@", _number);
self.state = OBOperationFinishedState;
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
self.state = OBOperationFinishedState;
NSLog(@"inner operation error: %@", _number);
}];
}
@end
Така че, ако започна операцията си:
MyOperation *op = [MyOperation new];
[_queue addOperation:op];
Виждам в конзолата begin inner operation: 1
и това е всичко! Приложението ми напълно замръзва (дори потребителския интерфейс)
След известно проучване решавам, че замръзването е причинено от [queue addOperations:ops waitUntilFinished:YES];
. Ако не изчакам завършване, моите вътрешни операции работят според очакванията, но MyOperation завърши преди дъщерните операции да бъдат завършени.
Така че сега имам заобиколно решение със зависима блокова операция:
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];
Но все още напълно не разбирам какъв е истинският проблем на това замръзване. Всяко обяснение ще бъде много полезно.
Източник на клас OBOperaton: https://dl.dropboxusercontent.com/u/1999619/issue/OBOperation.h https://dl.dropboxusercontent.com/u/1999619/issue/OBOperation.m
Целият проект: https://dl.dropboxusercontent.com/u/1999619/issue/OperationsTest.zip