Official Forum for Programming in Objective-C (the iPhone Programming Language) - Stephen Kochan
August 18, 2017, 09:33:20 AM *
Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length
 
   Home   Help Search Login Register Chat  
Pages: [1]   Go Down
  Print  
Author Topic: Parsing Data  (Read 16141 times)
jonthornham
Full Member
***
Posts: 169



WWW Email
« on: June 28, 2012, 04:08:16 PM »

I am trying to parse Data from multiple RSS feeds.  If I use a single feed I am able to display the information in a table without any issues.  I am using the title elements and loading them in a table for display. 

When I try and load multiple RSS feeds I am able to append the feeds in a NSMutableData object but when I parse the data I only see the first feeds in the table.

In the view did load method I use fast enumeration to cycle through the different feeds.
Code: (Objective-C)
- (void)viewDidLoad
{
    [super viewDidLoad];
    self.title = @"News";
    self.navigationItem.leftBarButtonItem = self.editButtonItem;
   
    // Create an array that holds the URLs of the RSS feeds
    NSMutableArray *RSSTempArray = [[NSMutableArray alloc] initWithObjects:kFLOCyclingURL, kTriathleteURL, kSlowtwitchURL, kCyclingNewsURL, nil];
    //NSMutableArray *RSSTempArray = [[NSMutableArray alloc] initWithObjects:kFLOCyclingURL, nil];
    //NSMutableArray *RSSTempArray = [[NSMutableArray alloc] initWithObjects:kTriathleteURL, nil];
    //NSMutableArray *RSSTempArray = [[NSMutableArray alloc] initWithObjects:kSlowtwitchURL, nil];
    //NSMutableArray *RSSTempArray = [[NSMutableArray alloc] initWithObjects:kCyclingNewsURL, nil];

    self.RSSFeedArray = RSSTempArray;
   
    NSMutableData *tempData = [[NSMutableData alloc] init];
    self.RSSFeedData = tempData;
    [self.RSSFeedData setLength: 0];
   
    for (NSString *element in self.RSSFeedArray)
    {
        NSLog(@"The current element is %@", element);
       
        // Loading the data from the RSS feed.  This creates the connection for the NSURLConnectionDelegate Methods.
        NSURLRequest *req = [[NSURLRequest alloc] initWithURL: [NSURL URLWithString: element]];
        NSURLConnection *con = [[NSURLConnection alloc] initWithRequest: req delegate: self];
       
        // This gives you access the the activity indicator in the top bar. 
        UIApplication.sharedApplication.networkActivityIndicatorVisible = YES;
       
        // Tests to make sure the connection exists and sets up the NSMutableData object if it does exist.
        if (con)
        {
                NSLog(@"Connected");
                NSMutableData *data = [[NSMutableData alloc] init];
                self.receivedData = data;
        }
        else
        {
            UIAlertView * alert = [[UIAlertView alloc] initWithTitle: @"Error" message:@"Error connecting to server" delegate:self cancelButtonTitle:@"Nuts" otherButtonTitles:nil];
            [alert show];
        }
    }
   
    NSLog (@"Out of the RSS Loop");
}

In the NSURLConnection methods I append the feed data as it comes in and then once it is complete I append it to the RSSFeedData object.  You can see the accumulation in the console print out below.  I have a test loop in the connectionDidFinishLoading method to ensure the parser is not called before all feeds have been downloaded.  Once they have I create a new thread and parse the data.
Code: (Objective-C)
-(void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    // This gives you access the the activity indicator in the top bar.  It is a UIApplication item.  Pretty cool.
    UIApplication.sharedApplication.networkActivityIndicatorVisible = YES;
   
    // Test to make sure the data array is created.
    if (!receivedData)
    {
        NSMutableData *data = [[NSMutableData alloc] init];
        self.receivedData = data;
    }

    // This sets up the connection and sets the received data object to 0
    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
 
    NSLog(@"remote url returned  %d %@",[httpResponse statusCode],[NSHTTPURLResponse localizedStringForStatusCode:[httpResponse statusCode]]);
     
    [receivedData setLength: 0];
   
    //currentlyReadingFeeds = YES;   
    //NSLog(@"currentlyReadingFeeds turned on");
}
 
 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
-(void) connection:(NSURLConnection *)connection didReceiveData: (NSData *) data
{
    // This appends the data to the receivedData object as chunks are received
    NSLog(@"Data Received");
    [receivedData appendData: data];
 
    if (self.receivedData == nil)
    {
        NSLog(@"No Data Received");
    }
}
 
 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
-(void) connection:(NSURLConnection *)connection didFailWithError: (NSError *) error
{
    // This give you access the the activity indicator in the top bar.  It is a UIApplication item.  Pretty cool.
    UIApplication.sharedApplication.networkActivityIndicatorVisible = NO;
   
    NSLog(@"Failed With Error");
    self.receivedData = nil;
 
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" message:[NSString stringWithFormat:@"Connection failed! Error - %@ (URL: %@)", [error localizedDescription],[[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]] delegate:self cancelButtonTitle:@"Bummer" otherButtonTitles:nil];
 
    [alert show];
}
 
 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
-(void) connectionDidFinishLoading:(NSURLConnection *)connection
{
    static NSInteger i = 0;
    i++;
    NSLog(@"i = %i", i);
    NSLog(@"RSSFeedArray = %i", [self.RSSFeedArray count]);
   
    // Checks to see if the receivedData array is nil
    if (self.receivedData == nil)
    {
        NSLog(@"NSData File nil");
    }
   
    // This is a test to see if any data has been received
    NSLog(@"I've downloaded: %d bytes", [receivedData length]);
   
    currentlyReadingFeeds = NO;
    NSLog(@"currentlyReadingFeeds turned off");
   
    [self.RSSFeedData appendData: self.receivedData];
    NSLog(@"The RSSFeedData Object currently contains %d bytes", [RSSFeedData length]);
   
    //I am moving the XMLParser methods outside of the URL Connection methods since I am connecting to multiple sites.  Each time I connect to a new site I clear my array.
    if (i == [self.RSSFeedArray count])
    {
       
        NSLog(@"I am parsing");
        NSLog(@"Inside the Parsing call the RSSFeedData Object contains %d bytes", [RSSFeedData length]);

        // This sets up the array used in the NSXMLParser methods for gathering the parsed elements.  Cuurently it adds all the <title> elements
        NSMutableArray *tempArray = [[NSMutableArray alloc] init];
        self.testingArray = tempArray;
   
        // This sets up the string used in the NSXMLParser methods for gathering string characters as they are collected by the parser.
        NSMutableString *tempString = [[NSMutableString alloc] init];
        self.currentParsedCharacterData = tempString;
   
        // Start up the Parser in a seperate queue on Grand Central Dispatch.  I have to use self on the parseRSSData method I created.
        myQueue = dispatch_queue_create("com.flocycling.gcdparser", NULL);
        dispatch_async(myQueue, ^ { [self parseRSSData: RSSFeedData];
                                    [self.myTableView reloadData]; } );
    }
}

Once I have the data I call the parser methods.
Code: (Objective-C)
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict 
{       
    if ([elementName isEqualToString: kTitleElement])
    {
        currentlyAccumulatingParsedCharacters = YES;
        [currentParsedCharacterData setString: @""];
    }
}

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{     
    if([elementName isEqualToString: kTitleElement])
    {
        currentlyAccumulatingParsedCharacters = NO;
        NSLog(@"Title: %@", currentParsedCharacterData);
        // This adds the finished string to the array for the table.  You need to create an object here or it ends up copying everything to the same
        // address and all the elements are the same
        NSString *tempString = [NSString stringWithFormat: currentParsedCharacterData];
        [testingArray addObject: tempString];
    }
}

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

// The parser delivers parsed character data (PCDATA) in chunks, not necessarily all at once.
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
    if (currentlyAccumulatingParsedCharacters)
    {
        [self.currentParsedCharacterData appendString: string];
    }
}

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError
{

}

You can see in the console print out that the data is being accumulated for each feed.  I have tested each feed individually and the bytes all add up to what is being shown in the print out.  Does anyone have any idea why I am not seeing all the data in the table?


2012-06-28 15:37:02.356 FLO Cycling[21958:15e03] The current element is http://flocycling.blogspot.com/feeds/posts/default?alt=rss
2012-06-28 15:37:02.361 FLO Cycling[21958:15e03] Connected
2012-06-28 15:37:02.364 FLO Cycling[21958:15e03] The current element is http://triathlon.competitor.com/feed
2012-06-28 15:37:02.365 FLO Cycling[21958:15e03] Connected
2012-06-28 15:37:02.367 FLO Cycling[21958:15e03] The current element is http://www.slowtwitch.com/rss
2012-06-28 15:37:02.368 FLO Cycling[21958:15e03] Connected
2012-06-28 15:37:02.368 FLO Cycling[21958:15e03] The current element is http://feeds.feedburner.com/cyclingnews/news?format=xml
2012-06-28 15:37:02.369 FLO Cycling[21958:15e03] Connected
2012-06-28 15:37:02.369 FLO Cycling[21958:15e03] Out of the RSS Loop
2012-06-28 15:37:02.404 FLO Cycling[21958:15e03] remote url returned  200 no error
2012-06-28 15:37:02.407 FLO Cycling[21958:15e03] Data Received
2012-06-28 15:37:02.409 FLO Cycling[21958:15e03] i = 1
2012-06-28 15:37:02.410 FLO Cycling[21958:15e03] RSSFeedArray = 4
2012-06-28 15:37:02.411 FLO Cycling[21958:15e03] I've downloaded: 6934 bytes
2012-06-28 15:37:02.412 FLO Cycling[21958:15e03] currentlyReadingFeeds turned off
2012-06-28 15:37:02.412 FLO Cycling[21958:15e03] The RSSFeedData Object currently contains 6934 bytes
2012-06-28 15:37:02.505 FLO Cycling[21958:15e03] remote url returned  200 no error
2012-06-28 15:37:02.507 FLO Cycling[21958:15e03] Data Received
2012-06-28 15:37:02.508 FLO Cycling[21958:15e03] i = 2
2012-06-28 15:37:02.509 FLO Cycling[21958:15e03] RSSFeedArray = 4
2012-06-28 15:37:02.511 FLO Cycling[21958:15e03] I've downloaded: 30916 bytes
2012-06-28 15:37:02.512 FLO Cycling[21958:15e03] currentlyReadingFeeds turned off
2012-06-28 15:37:02.513 FLO Cycling[21958:15e03] The RSSFeedData Object currently contains 37850 bytes
2012-06-28 15:37:02.514 FLO Cycling[21958:15e03] remote url returned  200 no error
2012-06-28 15:37:02.515 FLO Cycling[21958:15e03] Data Received
2012-06-28 15:37:02.516 FLO Cycling[21958:15e03] i = 3
2012-06-28 15:37:02.517 FLO Cycling[21958:15e03] RSSFeedArray = 4
2012-06-28 15:37:02.518 FLO Cycling[21958:15e03] I've downloaded: 66542 bytes
2012-06-28 15:37:02.520 FLO Cycling[21958:15e03] currentlyReadingFeeds turned off
2012-06-28 15:37:02.521 FLO Cycling[21958:15e03] The RSSFeedData Object currently contains 104392 bytes
2012-06-28 15:37:02.645 FLO Cycling[21958:15e03] remote url returned  200 no error
2012-06-28 15:37:02.646 FLO Cycling[21958:15e03] Data Received
2012-06-28 15:37:02.650 FLO Cycling[21958:15e03] Data Received
2012-06-28 15:37:02.745 FLO Cycling[21958:15e03] Data Received
2012-06-28 15:37:02.748 FLO Cycling[21958:15e03] Data Received
2012-06-28 15:37:02.749 FLO Cycling[21958:15e03] Data Received
2012-06-28 15:37:02.845 FLO Cycling[21958:15e03] Data Received
2012-06-28 15:37:02.846 FLO Cycling[21958:15e03] Data Received
2012-06-28 15:37:02.848 FLO Cycling[21958:15e03] Data Received
2012-06-28 15:37:02.944 FLO Cycling[21958:15e03] Data Received
2012-06-28 15:37:02.946 FLO Cycling[21958:15e03] Data Received
2012-06-28 15:37:02.946 FLO Cycling[21958:15e03] Data Received
2012-06-28 15:37:02.947 FLO Cycling[21958:15e03] Data Received
2012-06-28 15:37:02.949 FLO Cycling[21958:15e03] Data Received
2012-06-28 15:37:03.042 FLO Cycling[21958:15e03] Data Received
2012-06-28 15:37:03.044 FLO Cycling[21958:15e03] Data Received
2012-06-28 15:37:03.046 FLO Cycling[21958:15e03] Data Received
2012-06-28 15:37:03.049 FLO Cycling[21958:15e03] Data Received
2012-06-28 15:37:03.050 FLO Cycling[21958:15e03] i = 4
2012-06-28 15:37:03.053 FLO Cycling[21958:15e03] RSSFeedArray = 4
2012-06-28 15:37:03.054 FLO Cycling[21958:15e03] I've downloaded: 76718 bytes
2012-06-28 15:37:03.055 FLO Cycling[21958:15e03] currentlyReadingFeeds turned off
2012-06-28 15:37:03.057 FLO Cycling[21958:15e03] The RSSFeedData Object currently contains 181110 bytes
2012-06-28 15:37:03.059 FLO Cycling[21958:15e03] I am parsing
2012-06-28 15:37:03.060 FLO Cycling[21958:15e03] Inside the Parsing call the RSSFeedData Object contains 181110 bytes
2012-06-28 15:37:03.062 FLO Cycling[21958:17803] In the parseRSSData method the RSSFeedData Object contains 181110 bytes
2012-06-28 15:37:03.063 FLO Cycling[21958:17803] The Parse methods is being called
2012-06-28 15:37:03.066 FLO Cycling[21958:17803] Title: Slowtwitch.com
2012-06-28 15:37:03.066 FLO Cycling[21958:17803] Title: Slowtwitch.com
2012-06-28 15:37:03.067 FLO Cycling[21958:17803] Title: The 2012 Celtman video
2012-06-28 15:37:03.068 FLO Cycling[21958:17803] Title: Derek Oskutis' dangerous life
2012-06-28 15:37:03.069 FLO Cycling[21958:17803] Title: Norseman bound Bjorn Andersson
2012-06-28 15:37:03.069 FLO Cycling[21958:17803] Title: S-Works Venge LTD EPS
2012-06-28 15:37:03.070 FLO Cycling[21958:17803] Title: Kienle, Wutti take Heilbronn
2012-06-28 15:37:03.071 FLO Cycling[21958:17803] Title: Van Lierde, Deckers rule Nice
2012-06-28 15:37:03.071 FLO Cycling[21958:17803] Title: Alistair Brownlee dominates again
2012-06-28 15:37:03.075 FLO Cycling[21958:17803] Title: Gambles, Naeth win Syracuse 70.3
2012-06-28 15:37:03.076 FLO Cycling[21958:17803] Title: Drew Scott wins Buffalo Springs Lake 70.3
2012-06-28 15:37:03.077 FLO Cycling[21958:17803] Title: Guillaume, Tisseyre win Mt. Tremblant

Take care,

Jon
Logged

Jon Thornham
Pages: [1]   Go Up
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.11 | SMF © 2006-2009, Simple Machines LLC Valid XHTML 1.0! Valid CSS!
Entire forum contents ゥ 2009 classroomM.com. All rights reserved.