次のように NSOperationQueue のコールバックを登録しています。
[self.queue addObserver:self forKeyPath:@"operationCount" options:NSKeyValueObservingOptionNew context:NULL];
長いタスクの有効期限ハンドラーがあるため、これを operationCount のコールバックで行います。私は基本的に、キュー内の NSOperation が終了した後に状態を保存し、後で再開しようとしています。だから私はこれを行います:
- (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;
}
}
}
}
期待どおりに動作しません。コードをステップ実行すると、[self.queue removeObserver:..] が実行されることがわかります。ただし、obserValueForKeyPath: メソッドでコールバックを取得することになりますが、その理由はわかりません (self.queue のオブザーバーとして自分自身を削除したと仮定します。self を正しく削除していますか?ありがとう!