I'm registering for callbacks on for my NSOperationQueue like this:
[self.queue addObserver:self forKeyPath:@"operationCount" options:NSKeyValueObservingOptionNew context:NULL];
Because I have an expirationhandler for the long task, I do this in the callback of the operationCount. I basically am trying to save the state after an NSOperation in my queue finishes, and then resume it later. So I do this:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:@"operationCount"]) {
NSNumber *num = [change objectForKey:NSKeyValueChangeNewKey];
self.progress = (1.0 - (double)[num integerValue] / self.totalPackets);
if ([UIApplication sharedApplication].backgroundTimeRemaining <= MIN_BACKGROUND_TIME) {
// Background time is almost up, save the state and resume later
NSLog(@"running out of time");
[self.queue cancelAllOperations];
[self.queue removeObserver:self forKeyPath:@"operationCount" context:NULL];
if (self.patientProcessingTaskID != UIBackgroundTaskInvalid) {
[[UIApplication sharedApplication] endBackgroundTask:self.patientProcessingTaskID];
self.patientProcessingTaskID = UIBackgroundTaskInvalid;
}
}
if (self.queue.operationCount == 0) {
NSLog(@"no more operations");
[self.queue removeObserver:self forKeyPath:@"operationCount" context:NULL];
if (self.patientProcessingTaskID != UIBackgroundTaskInvalid) {
[[UIApplication sharedApplication] endBackgroundTask:self.patientProcessingTaskID];
self.patientProcessingTaskID = UIBackgroundTaskInvalid;
}
}
}
}
It does not work as I expected. I step through the code and I see that [self.queue removeObserver:..] gets run. However, I still end up getting a callback in my obserValueForKeyPath: method which I'm not sure why (assuming that I removed myself as the observer for the self.queue. Am I removing self correctly? Thanks!