我一直试图解析XML文件,以便从使用后台获取的网站获取文章。从XML文件解析链接并将其推送到UIWebView
指南的链接是here。
我已经成功完成了本教程并解析了我的XML文件,但不是通过Safari浏览器从外部推送链接,当用户单击文章时,我希望他们在UIWebView中看到它。
我该如何在我的代码中实现?
我的代码:
NewsViewController.h(此文件加载运行后台抓取获得的文章一个UITableView):
#import <UIKit/UIKit.h>
@interface NewsViewController : UIViewController<UITableViewDelegate, UITableViewDataSource>
@property (weak, nonatomic) IBOutlet UITableView *tblNews;
- (IBAction)removeDataFile:(id)sender;
-(void)fetchNewDataWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler;
@end
NewsViewController.m:
#import "NewsViewController.h"
#define NewsFeed @"http://www.teamfortress.com/rss.xml"
#import "XMLParser.h"
@interface NewsViewController()
@property (nonatomic, strong) UIRefreshControl *refreshControl;
@property (nonatomic, strong) NSArray *arrNewsData;
@property (nonatomic, strong) NSString *dataFilePath;
-(void)refreshData;
-(void)performNewFetchedDataActionsWithDataArray:(NSArray *)dataArray;
@end
@implementation NewsViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// 1. Make self the delegate and datasource of the table view.
[self.tblNews setDelegate:self];
[self.tblNews setDataSource:self];
// 2. Specify the data storage file path.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docDirectory = [paths objectAtIndex:0];
self.dataFilePath = [docDirectory stringByAppendingPathComponent:@"newsdata"];
// 3. Initialize the refresh control.
self.refreshControl = [[UIRefreshControl alloc] init];
[self.refreshControl addTarget:self
action:@selector(refreshData)
forControlEvents:UIControlEventValueChanged];
[self.tblNews addSubview:self.refreshControl];
// 4. Load any saved data.
if ([[NSFileManager defaultManager] fileExistsAtPath:self.dataFilePath]) {
self.arrNewsData = [[NSMutableArray alloc] initWithContentsOfFile:self.dataFilePath];
[self.tblNews reloadData];
}
}
- (IBAction)removeDataFile:(id)sender {
if ([[NSFileManager defaultManager] fileExistsAtPath:self.dataFilePath]) {
[[NSFileManager defaultManager] removeItemAtPath:self.dataFilePath error:nil];
self.arrNewsData = nil;
[self.tblNews reloadData];
}
}
-(void)refreshData{
XMLParser *xmlParser = [[XMLParser alloc] initWithXMLURLString:NewsFeed];
[xmlParser startParsingWithCompletionHandler:^(BOOL success, NSArray *dataArray, NSError *error) {
if (success) {
[self performNewFetchedDataActionsWithDataArray:dataArray];
[self.refreshControl endRefreshing];
}
else{
NSLog(@"%@", [error localizedDescription]);
}
}];
}
-(void)performNewFetchedDataActionsWithDataArray:(NSArray *)dataArray{
// 1. Initialize the arrNewsData array with the parsed data array.
if (self.arrNewsData != nil) {
self.arrNewsData = nil;
}
self.arrNewsData = [[NSArray alloc] initWithArray:dataArray];
// 2. Reload the table view.
[self.tblNews reloadData];
// 3. Save the data permanently to file.
if (![self.arrNewsData writeToFile:self.dataFilePath atomically:YES]) {
NSLog(@"Couldn't save data.");
}
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return self.arrNewsData.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"idCellNewsTitle"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"idCellNewsTitle"];
}
NSDictionary *dict = [self.arrNewsData objectAtIndex:indexPath.row];
cell.textLabel.text = [dict objectForKey:@"title"];
cell.detailTextLabel.text = [dict objectForKey:@"pubDate"];
return cell;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 80.0;
}
//THIS IS THE SECTION OF CODE THAT OPENS THE LINKS
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
NSDictionary *dict = [self.arrNewsData objectAtIndex:indexPath.row];
NSString *newsLink = [dict objectForKey:@"link"];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:newsLink]];
}
//END OF THE SECTION
-(void)fetchNewDataWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{
XMLParser *xmlParser = [[XMLParser alloc] initWithXMLURLString:NewsFeed];
[xmlParser startParsingWithCompletionHandler:^(BOOL success, NSArray *dataArray, NSError *error) {
if (success) {
NSDictionary *latestDataDict = [dataArray objectAtIndex:0];
NSString *latestTitle = [latestDataDict objectForKey:@"title"];
NSDictionary *existingDataDict = [self.arrNewsData objectAtIndex:0];
NSString *existingTitle = [existingDataDict objectForKey:@"title"];
if ([latestTitle isEqualToString:existingTitle]) {
completionHandler(UIBackgroundFetchResultNoData);
NSLog(@"No new data found.");
}
else{
[self performNewFetchedDataActionsWithDataArray:dataArray];
completionHandler(UIBackgroundFetchResultNewData);
NSLog(@"New data was fetched.");
}
}
else{
completionHandler(UIBackgroundFetchResultFailed);
NSLog(@"Failed to fetch new data.");
}
}];
}
@end
XMLParser.h(该文件解析XML以获取标题,日期也被公布,链接等)
#import <Foundation/Foundation.h>
@interface XMLParser : NSObject <NSXMLParserDelegate>
-(id)initWithXMLURLString:(NSString *)xmlUrlString;
-(void)startParsingWithCompletionHandler:(void(^)(BOOL success, NSArray *dataArray, NSError *error))completionHandler;
@end
XMLParser.m:
#import "XMLParser.h"
@interface XMLParser()
@property (nonatomic, strong) NSXMLParser *xmlParser;
@property (nonatomic, strong) NSOperationQueue *operationQueue;
@property (nonatomic, strong) NSMutableArray *arrParsedData;
@property (nonatomic, strong) NSString *currentElement;
@property (nonatomic, strong) NSString *newsTitle;
@property (nonatomic, strong) NSString *newsPubDate;
@property (nonatomic, strong) NSString *newsLink;
@property (nonatomic, strong) void (^completionHandler)(BOOL, NSArray *, NSError *);
@property (nonatomic) BOOL isNewsItem;
@property (nonatomic) BOOL allowedData;
-(void)parse;
-(void)endParsingWithError:(NSError *)error;
@end
@implementation XMLParser
-(id)initWithXMLURLString:(NSString *)xmlUrlString{
self = [super init];
if (self) {
self.xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:[NSURL URLWithString:xmlUrlString]];
self.xmlParser.delegate = self;
self.operationQueue = [NSOperationQueue new];
self.currentElement = @"";
self.isNewsItem = NO;
self.allowedData = NO;
}
return self;
}
#pragma mark - Public method implementation
-(void)startParsingWithCompletionHandler:(void (^)(BOOL, NSArray *, NSError *))completionHandler{
self.completionHandler = completionHandler;
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self
selector:@selector(parse)
object:nil];
[self.operationQueue addOperation:operation];
}
#pragma mark - Private method implementation
-(void)parse{
if (self.xmlParser != nil) {
[self.xmlParser parse];
}
}
-(void)endParsingWithError:(NSError *)error{
BOOL success = (error == nil) ? YES : NO;
self.completionHandler(success, self.arrParsedData, error);
}
#pragma mark - NSXMLParserDelegate method implementation
-(void)parserDidStartDocument:(NSXMLParser *)parser{
if (self.arrParsedData != nil) {
[self.arrParsedData removeAllObjects];
self.arrParsedData = nil;
}
self.arrParsedData = [[NSMutableArray alloc] init];
}
-(void)parserDidEndDocument:(NSXMLParser *)parser{
[self performSelectorOnMainThread:@selector(endParsingWithError:) withObject:nil waitUntilDone:NO];
}
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
if ([elementName isEqualToString:@"item"]) {
self.isNewsItem = YES;
}
if (self.isNewsItem) {
if ([elementName isEqualToString:@"title"] ||
[elementName isEqualToString:@"pubDate"] ||
[elementName isEqualToString:@"link"]) {
self.allowedData = YES;
}
}
self.currentElement = elementName;
}
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
if ([elementName isEqualToString:@"item"]) {
self.isNewsItem = NO;
NSDictionary *dict = @{@"title": self.newsTitle,
@"pubDate": self.newsPubDate,
@"link": self.newsLink
};
[self.arrParsedData addObject:dict];
}
if (self.isNewsItem) {
if ([elementName isEqualToString:@"title"] ||
[elementName isEqualToString:@"pubDate"] ||
[elementName isEqualToString:@"link"]) {
self.allowedData = NO;
}
}
}
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
if (self.allowedData) {
if ([self.currentElement isEqualToString:@"title"]) {
self.newsTitle = string;
}
else if ([self.currentElement isEqualToString:@"pubDate"]){
self.newsPubDate = string;
}
else if ([self.currentElement isEqualToString:@"link"]){
self.newsLink = string;
}
}
}
-(void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError{
[self performSelectorOnMainThread:@selector(endParsingWithError:) withObject:parseError waitUntilDone:NO];
}
-(void)parser:(NSXMLParser *)parser validationErrorOccurred:(NSError *)validationError{
[self performSelectorOnMainThread:@selector(endParsingWithError:) withObject:validationError waitUntilDone:NO];
}
@end
如果你想自己运行的项目,你可以找到它在Github here
注意当使用该链接时,Xcode项目在“您的TF2指南”下。
感谢任何人的帮助!
@gabembev谢谢你的回答!我希望它能起作用! –
我有一个SIGABRT错误。看看我的帖子在这里:[链接](http://stackoverflow.com/questions/22925618/loading-links-from-an-xml-file-onto-a-uiwebview-sigabrt-error) –