我有2个课程,NSObject
课程DataParser
和ViewController
。在DataParser
类中,我有一些解析XML的方法,结果保存在一个数组中,该数组是DataParser
类的属性。我想在ViewController
中向用户显示结果。我在这里有这个属性@property (strong, nonatomic) DataParser *parser;
,在viewWillAppear
方法中我创建了DataParser
类的实例,我试图以这种方式得到数组
self.parser = [[DataParser alloc] init];
[self.parser downloadBooksXML];
NSLog(@"%@", self.parser.array);
但我仍然没有。有谁知道问题出在哪里?
- (void)downloadBooksXML
{
NSURL *url = [NSURL URLWithString:@"http://..."];
[self downloadDataFromURL:url withCompletionHandler:^(NSData *data) {
if (data) {
self.xmlParser = [[NSXMLParser alloc] initWithData:data];
self.xmlParser.delegate = self;
self.foundValue = [[NSMutableString alloc] init];
[self.xmlParser parse];
} else {
NSLog(@"Error");
}
}];
}
编辑:当我在DataParser
方法中的parserDidEndDocument
类中使用nslog数组时,它包含数据
答案 0 :(得分:3)
当[self.parser downloadBooksXML]
返回时,self.parser.array
尚未设置,因为尚未下载和解析数据。
文档完成解析后,数据将可用,您可以使用委托方法检查:
- (void)parserDidEndDocument:(NSXMLParser *)parser {
NSLog(@"%@", self.parser.array);
}
因此,你可以使用这样的模式:
- (void) viewDidLoad {
[super viewDidLoad];
self.parser = [[DataParser alloc] init];
[self.parser downloadBooksXML];
}
- (void) dataFinished {
NSLog(@"%@", self.parser.array);
// update the user interface
}
- (void)parserDidEndDocument:(NSXMLParser *)parser {
[self dataFinished];
}
根据其他代码的实现,您可能需要切换到主队列来更新UI:
- (void) dataFinished {
NSLog(@"%@", self.parser.array);
dispatch_async(dispatch_get_main_queue(), ^(void){
// update the user interface
});
}
答案 1 :(得分:1)
鉴于您可能在XML解析器中的某处设置DataParser数组属性,并且downloadBooksXML正在异步执行下载和解析,您将在返回{{1}的调用后立即找到nil值}。
@Aaron建议的委托模式有效。您还可以考虑将自己的完成处理程序添加到downloadBooksXML
方法中,如下所示:
downloadBooksXML
然后你可以"通知"通过调用typedef void (^DownloadBooksCompletionHandler)();
- (void)downloadBooksXMLWithCompletionHandler:(DownloadBooksCompletionHandler)completionHandler
{
NSURL *url = [NSURL URLWithString:@"http://..."];
[self downloadDataFromURL:url withCompletionHandler:^(NSData *data) {
if (data) {
self.xmlParser = [[NSXMLParser alloc] initWithData:data];
self.xmlParser.delegate = self;
self.foundValue = [[NSMutableString alloc] init];
[self.xmlParser parse];
} else {
NSLog(@"Error");
}
completionHandler(); // <-- call the completionHandler!
}];
}
完成下载后调用者,并访问该阵列并更新您的UI。
completionHandler()
您也可以考虑将NSError *作为传递错误信息的方式传递给完成处理程序。
最后,请注意线程问题... [self.parser downloadBooksXMLWithCompletionHandler:^()
{
// now OK to access array property and update your UI
}];
将在downloadDataFromURL完成处理程序调用的线程上运行。根据您的实现,这可能是也可能不是UI线程。
答案 2 :(得分:-1)
NSXMLParser是XML解析器(SAX类型解析器)。它从头开始读取XML,每次找到新元素,结束元素或字符数据时,它都会通知您。在解析您的示例XML时,它将调用它的代理:
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict {
if (elementName == @"YourElement") {
// save the elements of attributeDict in your array! This is the place where you add the object to your property self.parser.array!
}
}
PS:如果投票的人(-1)可以告诉我答案中有什么问题?