将 XML 文件中的链接加载到 UIWebView(SIGABRT 错误) [英] Loading links from an XML file onto a UIWebView (SIGABRT error)

查看:21
本文介绍了将 XML 文件中的链接加载到 UIWebView(SIGABRT 错误)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在尝试解析 XML 文件,以便使用后台提取从网站获取文章.

I have been trying to parse an XML file in order to get articles from a website using background fetch.

有人给了我这个问题的答案这里.

Someone gave me an answer to this question here.

然而,他的回答导致了 SIGABRT 错误.

However, his answer resulted in an SIGABRT error.

有人可以看看我的代码,看看我的问题是什么吗?提前致谢.

Could someone please look at my code and see what my problem is? Thanks in advance.

我的代码:

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

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

 }

 - (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{

     if([segue.identifier isEqualToString:@"detail"]){


         DetailViewController *detail = segue.destinationViewController;
         NSIndexPath *indexPath = [self.tblNews indexPathForSelectedRow];
         detail.item = [self.arrNewsData objectAtIndex:indexPath.row];

     }
 }


 -(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> {
NSMutableDictionary *item;
NSMutableString * currentLink;
}

@property (retain, nonatomic) NSMutableString *currentLink;

-(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"]) {
     item = [[NSMutableDictionary alloc] init];
     self.currentLink = [[NSMutableString alloc] init];
     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;

         [item setObject:self.currentLink forKey:@"link"];


         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;
             [self.currentLink appendString: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

DetailViewController.h(这是包含一个包含我的 UIWebView 的 uiviewcontroller 的文件):

 #import <UIKit/UIKit.h>

 @interface DetailViewController : UIViewController<UIWebViewDelegate> {
     NSDictionary *item;
 }

 @property (retain, nonatomic) NSDictionary *item;
 @property (retain, nonatomic) IBOutlet UIWebView *itemSummary;

 @end

DetailViewController.m:

 #import "DetailViewController.h"

 @interface DetailViewController ()

 @end

 @implementation DetailViewController
 @synthesize item;
 @synthesize itemSummary = _itemSummary;

 - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
 {
     self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
     if (self) {
         // Custom initialization
     }
     return self;
 }

 - (void)viewDidLoad
 {
     [super viewDidLoad];

     _itemSummary.delegate = self;
     _itemSummary.scalesPageToFit = YES;

     NSURL* url = [NSURL URLWithString:[item objectForKey:@"link"]];
     [_itemSummary loadRequest:[NSURLRequest requestWithURL:url]];
     // Do any additional setup after loading the view.
 }

 - (void)didReceiveMemoryWarning
 {
     [super didReceiveMemoryWarning];
     // Dispose of any resources that can be recreated.
 }

 /*
 #pragma mark - Navigation

 // In a storyboard-based application, you will often want to do a little preparation  before navigation
 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
 {
     // Get the new view controller using [segue destinationViewController].
     // Pass the selected object to the new view controller.
 }
 */

 @end

如果你想自己运行这个项目,你可以在 Github 这里找到它

If you would like to run the project yourself, you can find it on Github here

注意 使用链接时,Xcode 项目位于Your Guide to TF2"下.

NOTE When using the link, the Xcode project is under "Your Guide to TF2".

感谢任何提供帮助的人!

Thanks to anyone that helps!

崩溃日志

2014-04-08 16:33:05.611 Your Guide to TF2[499:70b] -[UINavigationController fetchNewDataWithCompletionHandler:]: unrecognized selector sent to instance 0x1090aa930
2014-04-08 16:33:05.755 Your Guide to TF2[499:70b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UINavigationController fetchNewDataWithCompletionHandler:]: unrecognized selector sent to instance 0x1090aa930'
*** First throw call stack:
(
    0   CoreFoundation                      0x000000010189a795 __exceptionPreprocess + 165
    1   libobjc.A.dylib                     0x00000001015fd991 objc_exception_throw + 43
    2   CoreFoundation                      0x000000010192bbad -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
    3   CoreFoundation                      0x000000010188c09d ___forwarding___ + 973
    4   CoreFoundation                      0x000000010188bc48 _CF_forwarding_prep_0 + 120
    5   Your Guide to TF2                   0x0000000100004819 -[AppDelegate application:performFetchWithCompletionHandler:] + 345
    6   UIKit                               0x000000010026e0b5 -[UIApplication _handleOpportunisticFetchWithSequenceNumber:] + 170
    7   UIKit                               0x000000010025b200 -[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 1761
    8   UIKit                               0x000000010025ebe8 -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 660
    9   UIKit                               0x000000010026faab -[UIApplication handleEvent:withNewEvent:] + 3092
    10  UIKit                               0x000000010026ff1e -[UIApplication sendEvent:] + 79
    11  UIKit                               0x00000001002602be _UIApplicationHandleEvent + 618
    12  GraphicsServices                    0x00000001039a2bb6 _PurpleEventCallback + 762
    13  GraphicsServices                    0x00000001039a267d PurpleEventCallback + 35
    14  CoreFoundation                      0x000000010181c819 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 41
    15  CoreFoundation                      0x000000010181c5ee __CFRunLoopDoSource1 + 478
    16  CoreFoundation                      0x0000000101845ab3 __CFRunLoopRun + 1939
    17  CoreFoundation                      0x0000000101844f33 CFRunLoopRunSpecific + 467
    18  UIKit                               0x000000010025e4bd -[UIApplication _run] + 609
    19  UIKit                               0x0000000100260043 UIApplicationMain + 1010
    20  Your Guide to TF2                   0x0000000100004ce3 main + 115
    21  libdyld.dylib                       0x0000000101f295fd start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)

AppDelegate.m

 #import "AppDelegate.h"
 #import "NewsViewController.h"
 #define UIColorFromRGB(rgbValue) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 green:((float)((rgbValue & 0xFF00) >> 8))/255.0 blue:((float)(rgbValue &  0xFF))/255.0 alpha:1.0]

 @implementation AppDelegate

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
 {
     [application setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];
     // Override point for customization after application launch.
     // Uncomment to change the background color of navigation bar
     [[UINavigationBar appearance] setBarTintColor:UIColorFromRGB(0xb35326)];

     // Uncomment to change the color of back button
     //[[UINavigationBar appearance] setTintColor:[UIColor whiteColor]];

     // Uncomment to assign a custom backgroung image
     //[[UINavigationBar appearance] setBackgroundImage:[UIImage imageNamed:@"tf2_logo.png"] forBarMetrics:UIBarMetricsDefault];

     // Uncomment to change the back indicator image
     /*
      [[UINavigationBar appearance] setBackIndicatorImage:[UIImage imageNamed:@"back_btn.png"]];
      [[UINavigationBar appearance] setBackIndicatorTransitionMaskImage:[UIImage imageNamed:@"back_btn.png"]];
      */

     // Uncomment to change the font style of the title
     /*
      NSShadow *shadow = [[NSShadow alloc] init];
 shadow.shadowColor = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.8];
      shadow.shadowOffset = CGSizeMake(0, 1);
      [[UINavigationBar appearance] setTitleTextAttributes: [NSDictionary dictionaryWithObjectsAndKeys:
      [UIColor colorWithRed:245.0/255.0 green:245.0/255.0 blue:245.0/255.0 alpha:1.0], NSForegroundColorAttributeName,
 shadow, NSShadowAttributeName,
      [UIFont fontWithName:@"HelveticaNeue-CondensedBlack" size:21.0], NSFontAttributeName, nil]];
      */


     return YES;
 }

 -(void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{
     NSDate *fetchStart = [NSDate date];

NewsViewController *viewController = (NewsViewController *)self.window.rootViewController;

[viewController fetchNewDataWithCompletionHandler:^(UIBackgroundFetchResult result) {
    completionHandler(result);

    NSDate *fetchEnd = [NSDate date];
    NSTimeInterval timeElapsed = [fetchEnd timeIntervalSinceDate:fetchStart];
    NSLog(@"Background Fetch Duration: %f seconds", timeElapsed);

     }];
 }

推荐答案

问题出在你的 -[AppDelegate application:performFetchWithCompletionHandler:]这一行是错误的:

The problem is in your -[AppDelegate application:performFetchWithCompletionHandler:] This line is wrong:

NewsViewController *viewController = (NewsViewController *)self.window.rootViewController;

根视图控制器是一个 UINavigationController,但您假设它是一个 NewsViewController.那应该是:

The root view controller is a UINavigationController, but you're assuming it is a NewsViewController. That should be:

UINavigationController *navController = (UINavigationController *)self.window.rootViewController;
NewsViewController *viewController = (NewsViewController *)[[navController viewControllers] objectAtIndex:0];

这篇关于将 XML 文件中的链接加载到 UIWebView(SIGABRT 错误)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆