从财产

时间:2016-09-08 14:32:43

标签: ios objective-c

我有2个课程,NSObject课程DataParserViewController。在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数组时,它包含数据

3 个答案:

答案 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

然后你可以&#34;通知&#34;通过调用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)可以告诉我答案中有什么问题?