【发布时间】:2013-11-05 18:03:01
【问题描述】:
过去两个小时我一直在尝试解决这个问题,但没有取得太大进展,我想也许是时候尝试在这个问题上寻求一些外部帮助了。
基本上,我想同时运行三个 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 也无济于事。
Apple 的文档坚持认为 NSString 是线程安全的,所以我不确定我做错了什么,我认为附加到字符串以某种方式导致了这种情况,但即使直接设置字符串也会导致问题。
编辑
我已将分配更改为_errors = @"Error: Test error\n";,以防附加字符串导致问题
我还注意到 NSLogs 出现乱序(finishedUploading 的 NSLog 位于更改 _errors 值的块内的 NSLog 之前)
【问题讨论】:
标签: ios objective-c objective-c-blocks nsoperation nsoperationqueue