3

我正在使用 TBXML 创建一个 xml 解析器类。我希望该类加载一个 xml 文档,遍历它,并返回一个字符串数组来填充一个表。这应该发生在后台线程中,因此它确实会阻塞 UI。我想添加一个完成块,以便在 xml 解析完成时设置表的数据源数组。

如何实现完成块?这是我到目前为止所拥有的:

解析器

- (NSMutableArray *)loadObjects
{
    // Create a success block to be called when the asyn request completes
    TBXMLSuccessBlock successBlock = ^(TBXML *tbxmlDocument) {
        NSLog(@"PROCESSING ASYNC CALLBACK");

        // If TBXML found a root node, process element and iterate all children
        if (tbxmlDocument.rootXMLElement)
            [self traverseElement:tbxmlDocument.rootXMLElement];
    };

    // Create a failure block that gets called if something goes wrong
    TBXMLFailureBlock failureBlock = ^(TBXML *tbxmlDocument, NSError * error) {
        NSLog(@"Error! %@ %@", [error localizedDescription], [error userInfo]);
    };

    // Initialize TBXML with the URL of an XML doc. TBXML asynchronously loads and parses the file.
    tbxml = [[TBXML alloc] initWithURL:[NSURL URLWithString:@"XML_DOC_URL"]
                               success:successBlock
                               failure:failureBlock];
    return self.array;
}


- (void)traverseElement:(TBXMLElement *)element
{    
    do {
        // if the element has child elements, process them
        if (element->firstChild) [self traverseElement:element->firstChild];

        if ([[TBXML elementName:element] isEqualToString:@"item"]) {
            TBXMLElement *title = [TBXML childElementNamed:@"title" parentElement:element];
            NSString *titleString = [TBXML textForElement:title];
            [self.array addObject:titleString];
        };

        // Obtain next sibling element
    } while ((element = element->nextSibling));
}

表视图控制器.m

- (void)viewDidLoad
{
    [super viewDidLoad];

    Parser *parser = [[Parser alloc] init];
    self.products = [parser loadObjects]; 
}
4

1 回答 1

2

像这样,你会得到一个空数组,对吧?那是因为loadObjects在它完成任务之前没有阻塞并返回。

现在,您希望您viewDidLoad立即返回,以便您的表格可以显示。因此,在您的 中TableViewController,您需要一个在显示空表后被调用并管理更新的回调。标准技术是使用委托。在Parser.h定义中

@protocol ParserProtocol <NSObject>
-(void)parserDidFinishLoading;
@end

在解析器接口中添加

@property id<ParserProtocol> delegate;

successBlock用线完成你

[self.delegate parserDidFinishLoading];

然后使 TableViewController 符合ParserProtocol并将 Parser 添加为属性:

@property Parser* parser;

在 TableViewController.m 中替换

Parser *parser = [[Parser alloc] init];
self.products = [parser loadObjects]; 

self.parser = [[Parser alloc] init];
self.products = [self.parser loadObjects]; 

并添加

-(void)parserDidFinishLoading{
    [self.tableView reloadData];
}

self.products指向现在修改的array属性Parser。所以不需要额外的设置。

祝你好运,彼得。

于 2012-10-06T19:35:11.953 回答