私は過去 2 時間、この問題を解決しようとしてきましたが、あまり進展がありませんでした。
基本的に、同時に実行したい 3 つの NSOperations (実際には AFHTTPRequestOperations ですが、正確に理解すれば NSOperations として使用しても問題はありません) があり、それらすべてが完了したら、4 番目の操作を実行したいと考えています。プロセス中にエラーをチェックし、ユーザーに報告します (もちろん、NSOperations は NSOperationQueue 内に追加されます)。
最後の操作は、これら 3 つすべてに依存する NSBlockOperation であり、3 つの操作が完了したときにのみ正しく呼び出されます。このような構造になっています
NSOperation *finishedUploading = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"Completed. Errors: %@", _errors);
_textArea.editable = YES;
if (![_errors isEqualToString: @""])
{
//Trim the last newline
_errors = [_errors substringToIndex: _errors.length-1];
dispatch_async(dispatch_get_main_queue(), ^{
//Show error message
});
} else {
dispatch_async(dispatch_get_main_queue(), ^{
//Show success dialog
});
}
}];
ただし、アクセスしようとしている _errors プロパティは、そのように宣言されています
@property NSString *errors;
finishedUploading ブロックで誤って読み取られます。その値は NSLog によって @"" として報告されます。これは、4 つの NSOperations を実行する前に設定した値です。プロパティは、このように各操作の完了ブロック内で変更されます
_errors = [_errors stringByAppendingString: @"Error: Test error\n"];
割り当て後に_errorsプロパティをNSLoggingすると正しい値が表示され、NSOperationQueueを準備するマスターメソッドの後続の実行で値をチェックしても(@ ""に戻す前に)正しい値が読み取られますが、finishedUploadingだけが間違っています。
さらに、finishedUploading が正しい値を取得することがありますが、それは最初の NSLog の後でのみです (後続の if 条件が true と評価されます)。
完了ブロックの実行が早すぎて、実際には最後の NSOperation を実行する前に 1 秒の遅延を追加すると問題が解決するためだと思いましたが、無駄な遅延が追加されるため、最適な解決策ではありません (0.5 秒でも機能しません)。 . 解決策を探してみましたが、 @synchronized(_errors) を使用して _errors に (retain) を追加しても役に立ちません。
Apple のドキュメントでは、NSString はスレッド セーフであると主張しているため、何が間違っているのかわかりません。文字列に追加すると何らかの理由でこれが発生すると想定しましたが、文字列を直接設定しても問題が発生します。
編集
_errors = @"Error: Test error\n";
文字列を追加すると問題が発生した場合に備えて、割り当てをに変更しました
また、NSLogs が順不同で到着していることにも気付きました (finishedUploading の NSLog は、_errors の値を変更するブロック内の NSLog の前に来ます)。