该项目代码来自于王志刚 《软件创富密码:iPhone应用程序开发攻略之深入浅出Objective-C 2.0》一书,这是一个图例很丰富的书,适合入门阅读。
首先给出最终接图,接着给代码:
代码
// // AppController.h // RSS Reader // // Created by longx-app on 13-9-14. // Copyright (c) 2013年 longx-app. All rights reserved. // #import <Foundation/Foundation.h> @interface AppController : NSTableView <NSTableViewDataSource> { NSXMLDocument* document; IBOutlet id linkTextField; IBOutlet id titleTextField; IBOutlet id urlTextField; IBOutlet NSTableView *tableView; } - (IBAction)readURL:(id)sender; @end
// // AppController.m // RSS Reader // // Created by longx-app on 13-9-14. // Copyright (c) 2013年 longx-app. All rights reserved. // #import "AppController.h" @implementation AppController // NSTableView数据资源 - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView { if (!document) { return 0; } // 取得 “/rss/channel/item” 节点 NSArray* nodes; nodes = [document nodesForXPath:@"/rss/channel/item" error:NULL]; if ([nodes count] == 0) { // 取得 “/rdf:RDF/item” 节点 nodes = [document nodesForXPath:@"/rdf:RDF/item" error:NULL]; } if ([nodes count] == 0) { // 取得 “/feed/entry” 节点 nodes = [document nodesForXPath:@"/feed/entry" error:NULL]; } // 返回节点的个数 return [nodes count]; } - (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row { // 判断实例变量document是否有效,无效则退出处理 if (!document) { return nil; } // 使用identifier方法取得参数tableColumn的识别符,此识别符会用于后面列的判别 id identifier; identifier = [tableColumn identifier]; // 对 XML 文档使用 nodesForXPath: 方法取得 item 节点数组 // 取得 “/rss/channel/item” 节点 NSArray* nodes; nodes = [document nodesForXPath:@"/rss/channel/item" error:NULL]; if ([nodes count] == 0) { // 取得 “/rdf:RDF/item” 节点 nodes = [document nodesForXPath:@"/rdf:RDF/item" error:NULL]; } if ([nodes count] == 0) { // 取得 “/feed/entry” 节点 nodes = [document nodesForXPath:@"/feed/entry" error:NULL]; } // 根据行参数row取得指定行的item节点 NSXMLNode* node; node = [nodes objectAtIndex:row]; // 以下使用识别符来判断具体的列,首先是title列,从item节点中取得title节点,找到 // title的值后,返回此值 if ([identifier isEqual:@"title"]) { // 取得 “title” 的字符串 nodes = [node nodesForXPath:@"title" error:NULL]; if ([nodes count] == 1) { node = [nodes objectAtIndex:0]; return [node stringValue]; } } // 其次是link列,从item节点,找到后返回link值。 if ([identifier isEqual:@"link"]) { // 取得 ”link“ 的字符串 nodes = [node nodesForXPath:@"link" error:NULL]; if ([nodes count] == 1) { node = [nodes objectAtIndex:0]; return [node stringValue]; } } return nil; } - (IBAction)readURL:(id)sender { NSURL* url; url = [NSURL URLWithString:[urlTextField stringValue]]; // 创建XML文档,这里的URL如果是远程文件的话,必须以http://或ftp://开头,如果是 // 本地的,必须以file:///开头 document = [[NSXMLDocument alloc] initWithContentsOfURL:url options:0 error:NULL]; if (!document) { return; } // 取得 “/rss/channel/title” 节点 NSArray* nodes; nodes = [document nodesForXPath:@"/rss/channel/title" error:NULL]; if ([nodes count] == 0) { // 取得 “/rdf:RDF/channel/title” 节点 nodes = [document nodesForXPath:@"/rdf:RDF/channel/title" error:NULL]; } if ([nodes count] == 0) { // 取得 “/feed/title” 节点 nodes = [document nodesForXPath:@"/feed/title" error:NULL]; } if ([nodes count] == 1) { NSXMLNode* titleNode; titleNode = [nodes objectAtIndex:0]; // 设置RSS文档的标题 NSString* title; title = [titleNode stringValue]; [titleTextField setStringValue:title]; } // 取得 “/rss/channel/link” 节点 nodes = [document nodesForXPath:@"/rss/channel/link" error:NULL]; if ([nodes count] == 0) { // 取得 “/rdf:RDF/channel/link” 节点 nodes = [document nodesForXPath:@"/rdf:RDF/channel/link" error:NULL]; } if ([nodes count] == 0) { // 取得 “/feed/link” 节点 nodes = [document nodesForXPath:@"/feed/link" error:NULL]; } if ([nodes count] == 1) { NSXMLNode* linkNode; linkNode = [nodes objectAtIndex:0]; // 设置RSS文档对应网页的URL NSString* link; link = [linkNode stringValue]; [linkTextField setStringValue:link]; } // 表格数据读入 [tableView reloadData]; } @end
其中,readURL:动作主要完成对远程RSS文档的读取,因为RSS文档的版本众多,为取得RSS文档的标题以及URL,方法中进行了多重判断处理,请参照RSS版本说明来阅读上述代码。