我想用解析的xml结果创建对象,但它总是返回null。我认为在nsxmlparser委托没有完成之前就完成了。
这是我的代码。
@interface ParserOperation () <NSXMLParserDelegate, NSURLConnectionDelegate> {
NSString *soapResults;
NSXMLParser *xmlParser;
NSMutableData *responseData;
}
- (void)main {
NSError *error;
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:self.request delegate:self];
if (connection)
responseData = [NSMutableData data];
else
NSLog(@"NSURLConnection initWithRequest: Failed to return a connection.");
if ([self isCancelled]) {
return;
}
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
self.callbackBlock(NO, error);
NSLog(@"error %@", error);
} else {
self.callbackBlock(YES, self.results);
NSLog(@"else %@", soapResults);
}
});
}
当NSURLConnection委托方法完成时,XML解析器就开始了。
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSLog(@"Completed, Received Bytes:%lu",(unsigned long)[responseData length]);
xmlParser = [[NSXMLParser alloc] initWithData: responseData];
xmlParser.delegate = self;
[xmlParser setShouldResolveExternalEntities:YES];
[xmlParser parse];
}
- (void)parser:(NSXMLParser *) parser didStartElement:(NSString *) elementName namespaceURI:(NSString *) namespaceURI qualifiedName:(NSString *) qName attributes:(NSDictionary *)attributeDict {
soapResults = [[NSString alloc] init];
}
- (void)parser:(NSXMLParser *) parser foundCharacters:(NSString *)string {
soapResults = [soapResults stringByAppendingString:string];
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
if ([elementName isEqualToString:self.resultName]) {
if ([soapResults isEqualToString:@""]) {
NSLog(@"error");
}
else {
NSData *jsonData = [soapResults dataUsingEncoding:NSUTF8StringEncoding];
NSError *e;
self.results = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&e];
NSLog(@"Parsed Object: %@", self.results);
NSLog(@"soap: %@", soapResults);
}
}
}
答案 0 :(得分:1)
解析器是同步的,但下载不是。您的完成块以与开始下载相同的方法调用,因此它将始终在下载完成之前运行。
只有在出现错误时才应该在该方法中调用完成块。对于成功案例,应在[xmlParser parse];
之后调用完成块,因为这是处理数据的时间。
答案 1 :(得分:0)
有两个问题:
Wain绝对正确,这是异步网络请求,因此如果不是,则需要将其作为并发操作(+1)。确保(a)isConcurrent
返回YES
; (b)实施您自己的isExecuting
和isFinished
方法(或定义将为您合成这些getter的BOOL
属性); (c)确保在更改值时手动发布isFinished
和isExecuting
的KVN。所有这些都在并发编程指南的Operation Queue章节中讨论。请参阅标题为&#34;配置并发执行操作&#34;
顺便说一句,正如Wain指出的那样,因为这是一个异步网络请求,所以你要确保在connectDidFinishLoading
解析之后启动回调。
您也无法在操作上使用基于委托的NSURLConnection
(假设此操作在操作队列上运行),而无需在运行循环上调度此请求。最简单的解决方案是在主运行循环上安排连接:
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:self.request delegate:self startImmediately:NO];
[connection scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
[connection start];
您还可以为NSURLConnection
创建自己的专用线程(如AFNetworking一样)并安排您的操作,但这会增加一些复杂性。
我见过人们采用的另一种方法(并且它解决了并发操作问题以及运行循环问题)是将其作为非并发操作,但是main
没有只安排操作,但也创建自己的运行循环。我不是那种技术的粉丝,但它也有效。