//
// FeedURLConnection.m
// RSSTest2
//
// Created by Christos Sotiriou on 10/10/09.
// Copyright 2009 Tei of Pireus. All rights reserved.
//
#import "FeedURLConnection.h"
#import "NewsPapersSingleton.h"
#import <CFNetwork/CFNetwork.h>
@implementation FeedURLConnection
@synthesize stories, xmlFeedConnection, xmlData, url;
- (id) init
{
self = [super init];
if (self != nil) {
}
return self;
}
- (id) initWithURL:(NSString *)urlString
{
self = [super init];
if (self != nil) {
self.url = urlString;
}
return self;
}
- (void)connectAndParse
{
NSURLRequest *feedURLRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:self.url]];
//NSURLResponse *response;
//NSData *data = [NSURLConnection sendSynchronousRequest:feedURLRequest returningResponse:&response error:NULL];
//[self.xmlData setData:data];
self.xmlFeedConnection = [[[NSURLConnection alloc]initWithRequest:feedURLRequest delegate:self]autorelease];
}
#pragma mark -
#pragma mark NSURLConnection delegate methods
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
//NSLog(@"Did Receive Response with name: %@", [response textEncodingName]);
self.xmlData = [NSMutableData data];
myResponce = [response retain];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
//NSLog(@"did receive data! %@ with length: %i", [[[NSString alloc]initWithData:data encoding:NSASCIIStringEncoding]autorelease], [data length]);
//[xmlData appendData:[self dataFromData:data withEncoding:[myResponce textEncodingName]]];
[xmlData appendData:data];
//if ([[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]canBeConvertedToEncoding:NSUTF8StringEncoding]) {
// NSLog(@"yes, it can!");
//}
}
//I wonder what this does... I found it on Apple
- (NSData *)dataFromData:(NSData *)data withEncoding:(NSString *)encoding
{
NSStringEncoding nsEncoding = NSUTF8StringEncoding;
if (encoding) {
CFStringEncoding cfEncoding = CFStringConvertIANACharSetNameToEncoding((CFStringRef)encoding);
if (cfEncoding != kCFStringEncodingInvalidId) {
nsEncoding = CFStringConvertEncodingToNSStringEncoding(cfEncoding);
}
}
NSString *formattedString = [[[NSString alloc]initWithData:data encoding:nsEncoding]autorelease];
NSLog(formattedString);
return [[formattedString dataUsingEncoding:nsEncoding]retain];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
if ([error code] == kCFURLErrorNotConnectedToInternet) {
// if we can identify the error, we can present a more precise message to the user.
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:NSLocalizedString(@"No Connection Error", @"Error message displayed when not connected to the Internet.") forKey:NSLocalizedDescriptionKey];
NSError *noConnectionError = [NSError errorWithDomain:NSCocoaErrorDomain code:kCFURLErrorNotConnectedToInternet userInfo:userInfo];
[self handleError:noConnectionError];
} else {
// otherwise handle the error generically
[self handleError:error];
}
self.xmlFeedConnection = nil;
[[NSNotificationCenter defaultCenter]postNotificationName:FEED_TABLEVIEW_NEEDS_REFRESH_NOTIFICATION object:self];
}
- (void)handleError:(NSError *)error {
NSString *errorMessage = [error localizedDescription];
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Error Title", @"Title for alert displayed when download or parse error occurs.") message:errorMessage delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alertView show];
[alertView release];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
self.xmlFeedConnection = nil;
//[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
// Spawn a thread to fetch the earthquake data so that the UI is not blocked while the application parses the XML data.
//
// IMPORTANT! - Don't access UIKit objects on secondary threads.
//
//[NSThread detachNewThreadSelector:@selector(parseXMLFileAtURL:) toTarget:self withObject:sel];
// earthquakeData will be retained by the thread until parseEarthquakeData: has finished executing, so we no longer need
// a reference to it in the main thread.
//self.xmlData = nil;
//NSLog(@"content: %@", [[[NSString alloc]initWithData:self.xmlData encoding:NSUTF8StringEncoding]autorelease]);
[NSThread detachNewThreadSelector:@selector(parseXMLFileAtURL:) toTarget:self withObject:self.url];
}
#pragma mark -
#pragma mark NSXMLParser Delegations
- (void)parserDidStartDocument:(NSXMLParser *)parser{
NSLog(@"found file and started parsing");
}
- (void)parseXMLFileAtURL:(NSString *)URL
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
stories = [[NSMutableArray alloc] init];
//you must then convert the path to a proper NSURL or it won't work
//NSURL *xmlURL = [NSURL URLWithString:URL];
// here, for some reason you have to use NSClassFromString when trying to alloc NSXMLParser, otherwise you will get an object not found error
// this may be necessary only for the toolchain
//NSString *xmlString = @"SADfsd";
//[xmlString dataUsingEncoding:NSWindowsCP1250StringEncoding];
//rssParser = [[NSXMLParser alloc] initWithContentsOfURL:xmlURL];
//NSString *str = [[[NSString alloc]initWithData:self.xmlData encoding:NSWindowsCP1253StringEncoding]autorelease];
//NSLog(str);
//rssParser = [[NSXMLParser alloc]initWithData:self.xmlData];
//NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:self.url]];
//NSString *result = [NSString stringWithContentsOfURL:[NSURL URLWithString:self.url] encoding:NSUTF8StringEncoding error:NULL];
rssParser = [[NSXMLParser alloc]initWithData:self.xmlData];
//rssParser = [[NSXMLParser alloc]initWithData:[result dataUsingEncoding:NSUTF8StringEncoding]];
// Set self as the delegate of the parser so that it will receive the parser delegate methods callbacks.
[rssParser setDelegate:self];
// Depending on the XML document you're parsing, you may want to enable these features of NSXMLParser.
[rssParser setShouldProcessNamespaces:YES];
[rssParser setShouldReportNamespacePrefixes:YES];
[rssParser setShouldResolveExternalEntities:YES];
[rssParser parse];
[pool release];
}
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {
NSString * errorString = [NSString stringWithFormat:@"Unable to download story feed from web site (Error code %i )", [parseError code]];
NSLog(@"error parsing XML: %@", errorString);
UIAlertView * errorAlert = [[UIAlertView alloc] initWithTitle:@"Error loading content" message:errorString delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
[errorAlert show];
[errorAlert release];
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
//NSLog(@"found this element: %@", elementName);
currentElement = [elementName copy];
if ([elementName isEqualToString:@"item"]) {
// clear out our story item caches...
item = [[NSMutableDictionary alloc] init];
currentTitle = [[NSMutableString alloc] init];
currentDate = [[NSMutableString alloc] init];
currentSummary = [[NSMutableString alloc] init];
currentLink = [[NSMutableString alloc] init];
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
//NSLog(@"ended element: %@", elementName);
if ([elementName isEqualToString:@"item"]) {
// save values to an item, then store that item into the array...
[item setObject:currentTitle forKey:@"title"];
[item setObject:currentLink forKey:@"link"];
[item setObject:currentSummary forKey:@"summary"];
[item setObject:currentDate forKey:@"date"];
[stories addObject:[item copy]];
[item release];
//NSLog(@"adding story: %@", currentTitle);
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
//NSLog(@"found characters: %@", string);
// save the characters for the current item...
if ([currentElement isEqualToString:@"title"]) {
[currentTitle appendString:string];
} else if ([currentElement isEqualToString:@"link"]) {
[currentLink appendString:string];
} else if ([currentElement isEqualToString:@"description"]) {
[currentSummary appendString:string];
//NSLog(string);
} else if ([currentElement isEqualToString:@"pubDate"]) {
[currentDate appendString:string];
}
}
- (void)parserDidEndDocument:(NSXMLParser *)parser {
//[activityIndicator stopAnimating];
//[activityIndicator removeFromSuperview];
//NSLog(@"all done!");
//NSLog(@"stories array has %d items", [stories count]);
//[[NSNotificationCenter defaultCenter]postNotificationName:FEED_TABLEVIEW_NEEDS_REFRESH_NOTIFICATION object:self];
//[newsTable reloadData];
[self performSelectorOnMainThread:@selector(returnToMainThreadWithNotificationPosted) withObject:nil waitUntilDone:NO];
}
- (void)returnToMainThreadWithNotificationPosted
{
NSLog(@"all done!");
NSLog(@"stories array has %d items", [stories count]);
[[NSNotificationCenter defaultCenter]postNotificationName:FEED_TABLEVIEW_NEEDS_REFRESH_NOTIFICATION object:self];
}
#pragma mark -
- (void) dealloc
{
[url release];
[stories release];
[xmlFeedConnection release];
[xmlData release];
[super dealloc];
}
@end