NSOperationのサブクラスを使用して、AmazonのiOS SDK(v1.3.2)を使用して大きなファイルをAWSS3にアップロードします。これはすべて正常に機能しますが、一部のベータテスターはデッドロックを経験します(iOS5.1.1)。その結果、一度に1つの操作しか実行できないため、操作がスケジュールされているNSOperationQueueがブロックされます。問題は、ベータテスターが毎回この問題を経験するのに対し、私は問題を再現できないことです。
AWS iOS SDKの動作方法により、操作は非常に複雑です。ただし、テストに基づいて私が知る限り、この問題はAWSiOSSDKとは関係ありません。操作の主な方法を以下に貼り付けます。操作の主な方法のアイデアは、このStackOverflowの質問に基づいています。
- (void)main {
// Operation Should Terminate
_operationShouldTerminate = NO;
// Notify Delegate
dispatch_async(dispatch_get_main_queue(), ^{
[self.delegate operation:self isPreparingUploadWithUuid:self.uuid];
});
// Increment Network Activity Count
[self incrementNetworkActivityCount];
// Verify S3 Credentials
[self verifyS3Credentials];
while (!_operationShouldTerminate) {
if ([self isCancelled]) {
_operationShouldTerminate = YES;
} else {
// Create Run Loop
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
}
// Decrement Network Activity Count
[self decrementNetworkActivityCount];
NSLog(@"Operation Will Terminate");
}
マルチパートアップロードを終了するメソッドは、ブール値_operationShouldTerminate
を設定しYES
て操作を終了します。その方法は次のようになります。
- (void)finalizeMultipartUpload {
// Notify Delegate
dispatch_async(dispatch_get_main_queue(), ^{
[self.delegate operation:self didFinishUploadingUploadWithUuid:self.uuid];
});
// Operation Should Terminate
_operationShouldTerminate = YES;
NSLog(@"Finalize Multipart Upload");
}
最終ログステートメントはコンソールに出力されますが、操作のmainメソッドの最終ログステートメントがコンソールに出力されないため、mainメソッドのwhileループは終了していないようです。その結果、操作がスケジュールされている操作キューがブロックされ、スケジュールされた操作は実行されません。
操作のisFinished
メソッドは、以下のように単純に戻り_operationShouldTerminate
ます。
- (BOOL)isFinished {
return _operationShouldTerminate;
}
whileループが終了しないのは奇妙なことであり、私自身のテストデバイス(iPhone 3GS、iPad 1、およびiPad 3)のいずれでも発生しないのはさらに奇妙なことです。ヘルプやポインタは大歓迎です。