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

发布于 2024-09-27 07:06:58 字数 598 浏览 0 评论 0原文

第一篇文章。作为 iPhone 开发实习生已经大约五个星期了。我读过很多 Apress 的介绍性材料,但如果我有一些词汇违规,请放轻松。到目前为止,我已经能够通过搜索和潜伏找到答案。然而,我现在有一项任务,我几乎找不到相关信息。

我的 iPhone 应用程序当前使用严格的视图层次结构来选择项目。 MainViewController 链接到(呃,子视图?)一个 TableView,用于从工厂列表中选择任何一个。选择一个工厂,然后加载一个 TableView 以获取有关该工厂的各种统计信息。填充这些表的数据通过 http 从远程 JSON 服务器加载。

我想要远程服务器上的视图层次结构的 XML 定义,应用程序可以从中动态构造视图结构。通过这种方式,视图结构不会被硬编码到客户端(iPhone ViewControllers/nib)中,并且为重新组织内容服务器端提供了更大的灵活性。

这可能吗?有人做到了吗?最相关的答案是 Dynamic UI in iphone,但是读完后我觉得苹果的序列化/存档指南很快就偏离了我想做的事情。有人可以解释其相关性或指出其他资源吗?

first post. Been an iPhone developer intern for about five weeks now. I've read a lot of introductory Apress material, but please take it easy if I make some vocabulary violations. So far I've been able to find answers by searching and lurking. However I now have a task for which I can find little relevant information.

My iPhone application currently uses a rigid view hierarchy for selection of items. The MainViewController links to (err, Subviews?) a TableView for selecting any from a list of factories. Selecting a factory then loads a TableView for various statistics about that factory. The data to populate these tables loads from a remote JSON server by http.

I would like to have an XML definition of the view hierarchy on the remote server from which the application dynamically constructs the view structure. In this way the view structure is not hard-coded into the client (the iPhone ViewControllers/nibs) and offers more flexibility for reorganizing the content server-side.

Is this possible, and has anybody accomplished this? Most relevant answer was Dynamic UI in iphone, however upon reading I feel Apple's guide to Serializing/Archiving departs quickly from what I am trying to do. Can somebody explain its relevance or point to another resource?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

你的他你的她 2024-10-04 07:06:58

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

一个是控制器类,用于解析 XML,以将下载后所需的内容转换为可在模型类中使用的格式。有许多 OSS 库,但不要在 iPhone 上使用 Cocoa 的 XML 类,因为它们解析时太慢了。请务必仔细检查 OSS 库附带的许可证,以免违反 GPL 等。

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

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

Yes, it is entirely possible, and I (as well as others) have done something similar. Essentially, you will have to write a couple classes:

One is a Controller class to parse the XML to get the content you need upon download into a format you can use in a Model class. There are a number of OSS libraries out there, but don't use Cocoa's XML classes on the iPhone because they are just too slow when parsing. Be sure to double-check the license that comes with the OSS library so that you don't run afoul of GPL and the like.

The second class you'll need is one that will translate your model into a view hierarchy and place it on screen on the fly as the user moves through the content. This is to implement as individual steps, but the challenge is managing the content placement workflow.

The content noted in your question does depart a bit from the core task at hand but it can still be relevant to your interests. At the very least it may give you an idea on how to approach certain aspects of your project.

并安 2024-10-04 07:06:58

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

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

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

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 树浏览器。感谢堆栈溢出。

Here's a follow-up. I have accomplished what I wanted to do.

I have a ListViewController class and a Repository model/object. To parse XML, I used XPathQuery, Matt Gallagher's adaptation of libxml2 for Cocoa (http://cocoawithlove.com/2008/10/using-libxml2-for-parsing-and-xpath.html).

The ListViewController tracks the current XML path. When a cell in the table view is selected, the corresponding path is concatenated to the existing path. The ListViewController creates and pushes another instance of itself and PerformXMLPathQuery() returns an array to populate the table view cells. The Repository holds an NSMutableData object and an NSString with current path. Both are required for XPath Query:

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

PerformXMLPathQuery does a lot of back work for you. This is how I used it to get what I wanted from the 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];
}

When a row is selected, I used didSelectRowAtIndexPath to prepare the next path and view controller:

- (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];
}

The cool thing is each instance of ListViewController keeps its own path string and content array. No fooling around with nested tree objects or pointers.

Essentially I have a flexible XML tree browser for the iPhone. Thanks Stack Overflow.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文