在过去的两个小时里,我一直在尝试解决这个问题,但没有取得太大进展,我想也许是时候尝试在这个问题上寻求一些外部帮助了。
基本上,我想要同时运行三个 NSOperations(准确地说它们实际上是 AFHTTPRequestOperations,但如果我理解正确,将它们用作 NSOperations 没有问题),当它们全部完成时,我想运行第四个操作在此过程中检查错误并将其报告给用户(NSOperations 当然是添加到 NSOperationQueue 中)。
最后一个操作是一个 NSBlockOperation ,它依赖于这三个操作,只有三个操作完成后才能正确调用。它的结构是这样的
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 报告为@"",这是我在执行四个 NSOperation 之前设置的值。属性在每个操作的完成块内更改,如下所示
_errors = [_errors stringByAppendingString: @"Error: Test error\n"];
NSLogging _errors 属性在分配后将显示正确的值,甚至在准备 NSOperationQueue 的主方法的后续执行中检查该值(在将其设置回@“”之前)读取正确的值,只有 finishedUploading 出错了。
此外,有时finishedUploading 确实获得了正确的值,但仅在第一个NSLog 之后(随后的if 条件被评估为真)。
我认为这是因为完成块执行得太早,实际上在执行最后一个 NSOperation 之前添加一秒延迟确实可以解决问题,但这不是最佳解决方案,因为它增加了无用的延迟(半秒甚至不起作用) . 我曾尝试四处寻找解决方案,但即使使用 @synchronized(_errors) 并将(保留)添加到 _errors 也无济于事。
苹果的文档坚持认为 NSString 是线程安全的,所以我不确定我做错了什么,我认为附加到字符串以某种方式导致了这种情况,但即使直接设置字符串也会导致问题。
编辑
我已将分配更改为_errors = @"Error: Test error\n";
以防万一附加字符串导致问题
我还注意到 NSLogs 乱序到达(finishedUploading 的 NSLog 位于更改 _errors 值的块内的 NSLog 之前)