I have an NSOperation
subclass that I want to run concurrently.
My understanding is that for concurrent operations to work:
isConcurrent
to return YES
.start
methodisExecuting
and isFinished
when it's done.@synthesize
will automatically send the appropriate KVO notifications when the values for isExecuting
and isFinished
are changed.Despite this, I have verified that my queue never moves on to the next item.
Here's the meat of my code:
@interface MyOperation()
@property (readwrite) BOOL isExecuting;
@property (readwrite) BOOL isFinished;
@end
@implementation MyOperation
- (void)start
{
@autoreleasepool {
self.isExecuting = YES;
self.HTTPOperation = [[AFHTTPRequestOperation alloc] initWithRequest: URLRequest];
_HTTPOperation.completionBlock = [^{
[self completed];
self.isExecuting = NO;
self.isFinished = YES;
} copy];
[_HTTPOperation start];
}
}
- (BOOL)isConcurrent
{
return YES;
}
- (void)completed
{
}
@end
What am I missing?
(This is on an iPhone, but I can't imagine that matters.)
It looks like whatever KVO notifications @synthesize
sends aren't enough for NSOperationQueue
to move on.
Sending the notifications manually fixes the problem:
- (void)start
{
@autoreleasepool {
[self willChangeValueForKey:@"isExecuting"];
self.isExecuting = YES;
[self didChangeValueForKey:@"isExecuting"];
NSURLRequest *URLRequest = [self buildRequest];
if (!URLRequest) {
[self willChangeValueForKey:@"isFinished"];
[self willChangeValueForKey:@"isExecuting"];
_isExecuting = NO;
_isFinished = YES;
[self didChangeValueForKey:@"isExecuting"];
[self didChangeValueForKey:@"isFinished"];
return;
}
self.HTTPOperation = [[AFHTTPRequestOperation alloc] initWithRequest: URLRequest];
_HTTPOperation.completionBlock = [^{
[self completed];
[self willChangeValueForKey:@"isFinished"];
[self willChangeValueForKey:@"isExecuting"];
_isExecuting = NO;
_isFinished = YES;
[self didChangeValueForKey:@"isExecuting"];
[self didChangeValueForKey:@"isFinished"];
} copy];
[_HTTPOperation start];
}
}
See also: