我已经拔了两天多的头发来解决这个问题,我非常抗拒不在这里问问题,因为这可能是以前别人的问题,但是像这样在 Stackoverflow 上搜索和阅读所有相关问题,或者这个并阅读更多教程并测试不同的示例代码,我仍然无法弄清楚这一点。
我有一个 RSS 解析器应用程序,自从两年前在商店发布以来,它一直运行良好。这是一个简单的NSXMLParser
实现,从那时起我在许多应用程序中都使用了它,如果需要,可以做一些小的改动。现在我在另一个项目上实现相同的代码,它仍然可以正常工作,但是当我关闭 wifi 或使用无效的 url 解析时,它不会在iPhone Simulator
or上抛出错误iPhone 5, iOS 7.0.3
,而相同的代码在iPhone 4S, iOS 6.1.3
这是我的代码:
NIKFeedParser.h
:
#import <Foundation/Foundation.h>
#import "NIKFeedEntry.h"
@class NIKFeedEntry;
@protocol NIKFeedParserDelegate;
@interface NIKFeedParser : NSObject <NSXMLParserDelegate>
{
NIKFeedEntry *currentItem;
NSMutableString *currentItemValue;
NSMutableArray *feedItems;
id<NIKFeedParserDelegate> delegate;
NSOperationQueue *retrieverQueue;
NSUInteger parsingFeedsWithNumbers;
NSOperationQueue *queue;
}
@property (strong, nonatomic) NIKFeedEntry *currentItem;
@property (strong, nonatomic) NSMutableString *currentItemValue;
@property (readonly) NSMutableArray *feedItems;
@property (strong, nonatomic) id<NIKFeedParserDelegate> delegate;
@property (strong, nonatomic) NSOperationQueue *retrieverQueue;
@property (nonatomic) NSUInteger parsingFeedsWithNumbers;
@property (strong, nonatomic) NSOperationQueue *queue;
@property (nonatomic) NSString *selectedCategory;
- (void) startProcess;
@end
@protocol NIKFeedParserDelegate <NSObject>
- (void) processCompleted;
- (void) processHasErrors;
@end
和NIKFeedParser.m
:
#import "NIKFeedParser.h"
@implementation NIKFeedParser
@synthesize currentItem;
@synthesize currentItemValue;
@synthesize feedItems;
@synthesize delegate;
@synthesize retrieverQueue;
@synthesize parsingFeedsWithNumbers;
@synthesize queue;
@synthesize selectedCategory;
- (id) init
{
if (![super init])
{
return nil;
}
feedItems = [[NSMutableArray alloc] init];
queue = [NSOperationQueue new];
return self;
}
- (NSOperationQueue *)retrieverQueue
{
if (nil == retrieverQueue)
{
retrieverQueue = [[NSOperationQueue alloc] init];
retrieverQueue.maxConcurrentOperationCount = 1;
}
return retrieverQueue;
}
- (void) startProcess
{
SEL method = @selector (fetchAndParseFeed);
[[self feedItems] removeAllObjects];
NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:method object:nil];
[self.retrieverQueue addOperation:op];
}
- (BOOL)fetchAndParseFeed
{
parsingFeedsWithNumbers = 0;
@autoreleasepool {
//NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
//To suppress the leak in NSXMLParser.
[[NSURLCache sharedURLCache] setMemoryCapacity:0];
[[NSURLCache sharedURLCache] setDiskCapacity:0];
NSString *file = [[NSBundle mainBundle] pathForResource:@"Feed" ofType:@"plist"];
NSDictionary *item = [[NSDictionary alloc]initWithContentsOfFile:file];
NSArray *array = [item objectForKey:@"Root"];
NSURL *url = [NSURL URLWithString:
[[array objectAtIndex:[selectedCategory intValue]]objectForKey:@"URL"]];
BOOL success = NO;
NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:url];
[parser setDelegate:self];
[parser setShouldProcessNamespaces:YES];
[parser setShouldReportNamespacePrefixes:YES];
[parser setShouldResolveExternalEntities:NO];
success = [parser parse];
return success;
}
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict
{
if(nil != qualifiedName)
{
elementName = qualifiedName;
}
//NSLog(@"elementName: %@", elementName);
if ([elementName isEqualToString:@"item"])
{
self.currentItem = [[NIKFeedEntry alloc] init];
parsingFeedsWithNumbers++;
}
else if([elementName isEqualToString:@"title"] ||
[elementName isEqualToString:@"description"] ||
[elementName isEqualToString:@"link"] ||
[elementName isEqualToString:@"guid"] ||
[elementName isEqualToString:@"author"]||
[elementName isEqualToString:@"pubDate"])
{
self.currentItemValue = [NSMutableString string];
}
else
{
self.currentItemValue = nil;
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if(nil != self.currentItemValue){
[self.currentItemValue appendString:string];
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if(nil != qName)
{
elementName = qName;
}
if([elementName isEqualToString:@"title"])
{
self.currentItem.podcastTitle = self.currentItemValue;
// int titleLength = [self.currentItem.title length];
// int len = (titleLength > 70) ? 70: titleLength;
// self.currentItem.shortTitle = [self.currentItem.title substringWithRange:NSMakeRange(0, len)];
}
else if([elementName isEqualToString:@"link"])
{
self.currentItem.podcastURL = self.currentItemValue;
}
else if([elementName isEqualToString:@"guid"])
{
// self.currentItem.guidUrl = self.currentItemValue;
}
else if ([elementName isEqualToString:@"author"])
{
// self.currentItem.author = self.currentItemValue;
}
else if([elementName isEqualToString:@"pubDate"])
{
// self.currentItem.podcastDate = self.currentItemValue;
// self.currentItem.pubDate = [FarsiNumbers convertNumbersToFarsi:self.currentItemValue];
}
else if([elementName isEqualToString:@"item"])
{
[[self feedItems] addObject:self.currentItem];
}
}
- (void)parser:(NSXMLParser *)parser foundCDATA:(NSData *)CDATABlock{
//CDATAblock implementation
}
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError{
NSLog(@"parseErrorOccurred");
if(parseError.code != NSXMLParserDelegateAbortedParseError) {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
[(id)[self delegate] performSelectorOnMainThread:@selector(processHasErrors)
withObject:nil
waitUntilDone:NO];
}
}
- (void)parserDidEndDocument:(NSXMLParser *)parser {
NSLog(@"parserDidEndDocument");
//TitleViewController *viewController = [[TitleViewController alloc] init];
//viewController.parseFinished = @"1";
// parseFinished = [[NSString alloc] initWithFormat:@"%d", 1];
// NSLog(@"rss parser parser finished, %@", viewController.parseFinished);
parsingFeedsWithNumbers = 0;
[(id)[self delegate] performSelectorOnMainThread:@selector(processCompleted)
withObject:nil
waitUntilDone:NO];
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}
@end
我的NIKMasterViewController.m
:
- (void)viewDidLoad
{
feedParser = [[NIKFeedParser alloc] init];
[[self feedParser] setSelectedCategory:[self selectedCategory]];
[[self feedParser] setDelegate:self];
[[self feedParser] startProcess];
}
- (void)processCompleted
{
[[self tableView] reloadData];
[activityIndicator stopAnimating];
NSInteger rowCount = [[[self feedParser] feedItems] count];
if (rowCount!=0) {
//
self.tableView.delegate = self;
self.tableView.dataSource = self;
}
else if ((rowCount==0) &&([UIApplication sharedApplication].networkActivityIndicatorVisible == NO ) ){
UILabel *noContentWarning = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 480, 480)];
noContentWarning.text = NO_CONTENT_WARNING_MESSAGE;
noContentWarning.center = CGPointMake(self.view.frame.size.width/2, self.view.frame.size.height/3);
}
}
- (void)processHasErrors
{
//Due to internet connection or server error.
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NO_CONNECTION_ALERT_TITLE message: NO_CONNECTION_ALERT_MESSAGE delegate:self cancelButtonTitle:NO_CONNECTION_ALERT_VIEW_DISMISS_BUTTON otherButtonTitles:nil];
[alert show];
[activityIndicator stopAnimating];
}
在主要方法上设置断点并跟踪代码,这是调用方法的顺序:
NIKFeedParser - init
NIKMasterViewController - viewDidLoad
NIKFeedParser - startProcess
NIKFeedParser - retrieveQueue
NIKFeedParser - startProcess - [self.retrieverQueue addOperation:op];
NIKMasterViewController - viewDidLoad
然后我有银行表视图控制器,显然不是可见的网络指示器,因为 wifi 已关闭,而以前,它能够显示UIAlertView
告诉我发生连接错误。Apple 在新的 iOS 或 SDK 中发生了哪些变化?或者我错过了什么?