1

我认为我在正确的轨道上,但只是想在这里仔细检查一下。我最近开始使用 AFNetworking 从数据库中获取一个大型 XML 文件,然后我需要对其进行解析(我已经弄清楚了那部分)。我希望在后台线程上进行解析,然后在主线程上更新我的 UI。所以我在 AFXMLRequestOperation 的成功块中添加了另一个 dispatch_async 块:

self.xmlOperation =
[AFXMLRequestOperation XMLParserRequestOperationWithRequest: request
                                                    success: ^(NSURLRequest *request, NSHTTPURLResponse *response, NSXMLParser *XMLParser) {

                                                        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                                                             XMLParser.delegate = self;
                                                            [XMLParser setShouldProcessNamespaces:YES];
                                                            [XMLParser parse];

                                                            dispatch_async(dispatch_get_main_queue(), ^{
                                                                [self.searchResultViewController didFinishImport];
                                                                [[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait];

                                                            });
                                                        });
                                                    }
                                                    failure: ^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, NSXMLParser *XMLParser) {
                                                        // show error
                                                    }];

[self.xmlOperation start];

是正确/正确/首选的方法吗?

4

1 回答 1

1

这看起来很不错。不过有两个观察结果:

  1. 您在主线程上的任何代码是否可以访问您的NSXMLParserDelegate方法正在主动更新的任何对象?如果没有,你很好。

    但是,如果您有任何代码(例如,驱动 UI)正在访问NSXMLParserDelegate方法正在更新的相同对象/集合,那么您必须小心同步这些共享资源。(有关同步资源的更多信息,请参阅线程编程指南的同步部分和/或并发编程指南的消除基于锁的代码部分。 )

    就个人而言,我喜欢将NSXMLParserDelegate代码移动到一个单独的类中,并为单个请求实例化它,这样我就知道我的请求和随后的解析过程永远不会成为同步问题的根源。您仍然需要同步更新模型/存储过程,但您可以通过在主队列上执行最终更新来有效地做到这一点。

  2. 您的 UI 是否允许您在第一个 XML 请求正在进行时发出另一个 XML 请求?如果没有,你很好。

    如果用户可以在第一个请求正在进行时发起第二个请求,那么它会为您打开(不可否认的)场景,即您可以使用同一委托对象实例同时处理两个请求。显然,您可以通过阻止后续请求直到第一个请求完成(例如禁用请求刷新的 UI 元素),或使用串行队列,或将解析器移动到您将为每个请求实例化的单独类中来解决此问题。就个人而言,我倾向于使此解析请求可取消,并使新请求的发出取消任何先前正在进行的请求。

当我查看您的代码示例时,这是两个与并发相关的问题。实际上,也许这些都不是您的特定实现的问题。话虽如此,代码如此依赖于您的其余实现这一事实本身就是一个问题。

于 2013-08-30T15:36:31.330 回答