Cocoa Touch:动态XML定义的视图可能吗?

时间:2010-10-11 14:01:21

标签: iphone objective-c xml uiview xml-serialization

第一篇文章。现在已经是iPhone开发人员实习生大约五周了。我已经阅读了很多介绍性的Apress材料,但如果我犯了一些词汇侵犯,请放轻松。到目前为止,我已经能够通过搜索和潜伏找到答案。但是我现在有一项任务,我可以找到很少的相关信息。

我的iPhone应用程序目前使用刚性视图层次结构来选择项目。 MainViewController链接到(错误,Subviews?)一个TableView,用于从工厂列表中选择任何一个。选择工厂然后加载TableView以获取有关该工厂的各种统计信息。填充这些表的数据由http。

从远程JSON服务器加载

我希望在远程服务器上有一个视图层次结构的XML定义,应用程序可以动态地构建视图结构。通过这种方式,视图结构不会硬编码到客户端(iPhone ViewControllers / nibs)中,并为重新组织内容服务器端提供了更大的灵活性。

这可能吗,有没有人完成这个?最相关的答案是Dynamic UI in iphone,但是在阅读时我觉得Apple的序列化/存档指南很快就会脱离我想要做的事情。有人可以解释其相关性或指向另一种资源吗?

2 个答案:

答案 0 :(得分:1)

是的,这完全有可能,而且我(以及其他人)做过类似的事情。基本上,你必须写几个类:

一个是一个Controller类,用于解析XML,以便在下载到您可以在Model类中使用的格式时获取所需的内容。有很多OSS库,但不要在iPhone上使用Cocoa的XML类,因为它们在解析时速度太慢。请务必仔细检查OSS库附带的许可证,以免与GPL等发生冲突。

您需要的第二个类是将您的模型转换为视图层次结构,并在用户浏览内容时将其立即放置在屏幕上。这是作为单独的步骤实现的,但挑战在于管理内容放置工作流程。

您的问题中提到的内容确实偏离了手头的核心任务,但它仍然与您的兴趣相关。至少它可以让您了解如何处理项目的某些方面。

答案 1 :(得分:0)

这是一个后续行动。我已经完成了我想做的事。

我有一个ListViewController类和一个Repository模型/对象。为了解析XML,我使用了XPathQuery,Matt Gallagher为Cocoa改编了libxml2(http://cocoawithlove.com/2008/10/using-libxml2-for-parsing-and-xpath.html)。

ListViewController跟踪当前的XML路径。选择表视图中的单元格时,相应的路径将连接到现有路径。 ListViewController创建并推送其自身的另一个实例,PerformXMLPathQuery()返回一个数组来填充表视图单元格。存储库包含NSMutableData对象和具有当前路径的NSString。 XPath Query都需要这两个:

NSArray *PerformXMLXPathQuery(NSData *document, NSString *query);

PerformXMLPathQuery为您做了很多工作。这就是我用它来从XML中得到我想要的东西:

-(NSArray*)getListFromRepositoryWithPath:(NSString *)path {

    // Get the nodes referred to by the path
    NSArray *nodes = PerformXMLXPathQuery(repository.data, path);

    // Build an array with the node names
    NSMutableArray* sublist = [[NSMutableArray alloc] init];

    for (NSDictionary* node in nodes) {     
        for (id key in node) {

            if ([key isEqualToString:@"nodeChildArray"]) {
                NSArray* subNodes = [node objectForKey:@"nodeChildArray"];

                for (NSDictionary* subNode in subNodes) {
                    for (id subKey in node) {

                        if ([subKey isEqualToString:@"nodeName"]) {
                            [sublist addObject:[subNode objectForKey:subKey]];
                        }
                    }
                }
            }
        }
        // Ignore duplicate entries in the data
        if ([sublist count] > 0) { 
            return [NSArray arrayWithArray:sublist]; 
        }
    }
    return [NSArray arrayWithArray:sublist];
}

当选择一行时,我使用didSelectRowAtIndexPath来准备下一个路径并查看控制器:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    NSString *nextXpathQueryString = [self.xpathQueryString copy];

    // Build the path string for the next view's XML path query
    if ([[nextXpathQueryString lastPathComponent] isEqualToString:@"*"]) {
        nextXpathQueryString = [nextXpathQueryString stringByDeletingLastPathComponent];
        nextXpathQueryString = [nextXpathQueryString stringByAppendingPathComponent:@ROOTNAME];
    }
    nextXpathQueryString = [nextXpathQueryString stringByAppendingPathComponent:[repository.currentListToDisplay objectAtIndex:indexPath.row]];

    // Navigation logic. Create and push another view controller.
    ListViewController *detail = [[ListViewController alloc] init];

    // Populate the new ViewController
    [detail setRepository:repository];
    [detail setTitle:nextXpathQueryString];
    [detail setXpathQueryString:nextXpathQueryString];

    [nextXpathQueryString release];

    UIBarButtonItem *doneButton = [[self navigationItem] rightBarButtonItem];
    [[detail navigationItem] setRightBarButtonItem:doneButton animated:YES];

    // Pass the selected object to the new view controller.
    [self.navigationController pushViewController:detail animated:YES];
    [detail release];
}

很酷的事情是ListViewController的每个实例都保留自己的路径字符串和内容数组。不要愚弄嵌套的树对象或指针。

基本上我有一个灵活的iPhone XML树浏览器。谢谢Stack Overflow。