Permalink
Browse files

NSURL fun

  • Loading branch information...
Ryan Blunden
Ryan Blunden committed Jan 18, 2013
1 parent 486a0cb commit 1bc98b95102e536a4cc2ee2ea7e7b0c43f86e841
@@ -0,0 +1,22 @@
+//
+// Created by rblunden on 1/17/13.
+//
+// To change the template use AppCode | Preferences | File Templates.
+//
+
+
+#import <Foundation/Foundation.h>
+
+@class RSSChannel;
+
+
+@interface ListViewController : UITableViewController <NSURLConnectionDelegate, NSURLConnectionDataDelegate, NSXMLParserDelegate> {
+ NSURLConnection *connection;
+ NSMutableData *xmlData;
+
+ RSSChannel *channel;
+}
+
+- (void)fetchEntries;
+
+@end
@@ -0,0 +1,113 @@
+//
+// Created by rblunden on 1/17/13.
+//
+// To change the template use AppCode | Preferences | File Templates.
+//
+
+
+#import "ListViewController.h"
+#import "RSSChannel.h"
+#import "RSSItem.h"
+
+
+@implementation ListViewController {
+
+}
+
+- (id)initWithStyle:(UITableViewStyle)style {
+ self = [super initWithStyle:style];
+ if (self) {
+ [self fetchEntries];
+ }
+
+ return self;
+}
+
+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
+ return [[channel items] count];
+}
+
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
+ UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"UITableView"];
+
+ if (cell == nil) {
+ cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
+ reuseIdentifier:@"UITableView"];
+ }
+ RSSItem *item = [channel items][[indexPath row]];
+ [[cell textLabel] setText:[item title]];
+
+ return cell;
+}
+
+- (void)fetchEntries {
+ // Create a new data container for the stuff service data
+ xmlData = [[NSMutableData alloc] init];
+
+ // Apple's hot feed
+ NSURL *url = [NSURL URLWithString:@"http://www.apple.com/pr/feeds/pr.rss"];
+
+ NSURLRequest *req = [NSURLRequest requestWithURL:url];
+ connection = [[NSURLConnection alloc] initWithRequest:req delegate:self
+ startImmediately:YES];
+}
+
+- (void)connection:(NSURLConnection *)conn didReceiveData:(NSData *)data {
+ // Add the incoming chunk of data to the container we are keeping
+ // The date always comes in the correct order
+ [xmlData appendData:data];
+}
+
+- (void)connectionDidFinishLoading:(NSURLConnection *)conn {
+ // Create the parser object
+ NSXMLParser *parser = [[NSXMLParser alloc] initWithData:xmlData];
+
+ // Give it a delegate - ignore the warning here for now
+ [parser setDelegate:self];
+
+ // Start parsing - the document will be parsed and the delegate of NSXMLPArser will get all of its delegate
+ // messages sent to it before this line finishes execution - it is blocking
+ [parser parse];
+
+ // Get rid of the XML data as we no longer need it
+ xmlData = nil;
+
+ // Get rid of connection, we longer need it
+ connection = nil;
+
+ // Reload the table... for now, the table will be empty
+ [[self tableView] reloadData];
+}
+
+- (void)connection:(NSURLConnection *)conn didFailWithError:(NSError *)error {
+ // Release the connection object, we're done with it
+ connection = nil;
+
+ // Release the xmlData object, we're done
+ xmlData = nil;
+
+ // Grab the description of the error passed to us
+ NSString *errorString = [NSString stringWithFormat:@"Fetch failed %@", [error localizedDescription]];
+
+ // Create and show an alert view with this error displayed
+ UIAlertView *av = [[UIAlertView alloc] initWithTitle:@"Error" message:errorString
+ delegate:nil cancelButtonTitle:@"OK"
+ otherButtonTitles:nil];
+ [av show];
+}
+
+- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI
+ qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict {
+
+ // If the parser saw a channel, create a new instance, store in our ivar
+ channel = [[RSSChannel alloc] init];
+
+ // Give the channel object ap ointer back to ourselves for later
+ [channel setParentParserDelegate:self];
+
+ // Set the parser's dleedate to the channel object
+ // THere will be a warning here, ignore for now
+ [parser setDelegate:channel];
+}
+
+@end
@@ -0,0 +1,16 @@
+//
+// NerdfeedAppDelegate.h
+// Nerdfeed
+//
+// Created by Ryan Blunden on 01/17/13.
+// Copyright (c) 2013 __MyCompanyName__. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface NerdfeedAppDelegate : UIResponder <UIApplicationDelegate> {
+}
+
+@property(strong, nonatomic) UIWindow *window;
+
+@end
@@ -0,0 +1,61 @@
+//
+// NerdfeedAppDelegate.m
+// Nerdfeed
+//
+// Created by Ryan Blunden on 01/17/13.
+// Copyright (c) 2013 __MyCompanyName__. All rights reserved.
+//
+
+#import "NerdfeedAppDelegate.h"
+#import "ListViewController.h"
+
+@implementation NerdfeedAppDelegate
+
+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+ self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
+ // Override point for customization after application launch.
+
+ ListViewController *lvc = [[ListViewController alloc] initWithStyle:UITableViewStylePlain];
+
+ UINavigationController *masterNav = [[UINavigationController alloc] initWithRootViewController:lvc];
+
+ [[self window] setRootViewController:masterNav];
+
+ self.window.backgroundColor = [UIColor whiteColor];
+ [self.window makeKeyAndVisible];
+ return YES;
+}
+
+- (void)applicationWillResignActive:(UIApplication *)application {
+ // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
+ // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
+
+}
+
+- (void)applicationDidEnterBackground:(UIApplication *)application {
+ // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
+ // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
+
+}
+
+- (void)applicationWillEnterForeground:(UIApplication *)application {
+ // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
+
+}
+
+- (void)applicationDidBecomeActive:(UIApplication *)application {
+ // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
+
+}
+
+- (void)applicationWillTerminate:(UIApplication *)application {
+ // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
+
+}
+
+- (void)fetchEntries {
+
+}
+
+
+@end
@@ -0,0 +1,19 @@
+//
+// Created by rblunden on 1/17/13.
+//
+// To change the template use AppCode | Preferences | File Templates.
+//
+
+
+#import <Foundation/Foundation.h>
+
+
+@interface RSSChannel : NSObject <NSXMLParserDelegate>
+
+@property(nonatomic, weak) id parentParserDelegate;
+
+@property(nonatomic, strong) NSString *title;
+@property(nonatomic, strong) NSString *infoString;
+@property(nonatomic, readonly, strong) NSMutableArray *items;
+
+@end
@@ -0,0 +1,66 @@
+//
+// Created by rblunden on 1/17/13.
+//
+// To change the template use AppCode | Preferences | File Templates.
+//
+
+
+#import "RSSChannel.h"
+#import "RSSItem.h"
+
+
+@implementation RSSChannel {
+ NSMutableString *currentString;
+}
+
+- (id)init {
+ self = [super init];
+ if (self) {
+ _items = [[NSMutableArray alloc] init];
+ }
+
+ return self;
+}
+
+- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
+
+ if ([elementName isEqual:@"title"]) {
+ currentString = [[NSMutableString alloc] init];
+ [self setTitle:currentString];
+ }
+ else if ([elementName isEqual:@"description"]) {
+ currentString = [[NSMutableString alloc] init];
+ [self setInfoString:currentString];
+ }
+ else if([elementName isEqual:@"item"]) {
+ // When we find an item, create an instance of an RSSItem
+ RSSItem *entry = [[RSSItem alloc] init];
+
+ // Set up its parent as ourselves so we can regain control o the parser
+ [entry setParentParserDelegate:self];
+
+ // turn the parser to the RSSItem
+ [parser setDelegate:entry];
+
+ // Add the item to our array and release our hold on it
+ [[self items] addObject:entry];
+ }
+}
+
+- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
+ [currentString appendString:string];
+}
+
+- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
+ // If we were in an element that we wre collecting the string for, this appropriate releases our hold on it and
+ // the permanent ivar keeps ownership of it. If we weren't parsing such an element, the currentString is nil already.
+ currentString = nil;
+
+ // if the element that was eneded was the channel, give up control to who gave us control in the first place
+ if ([elementName isEqual:@"channel"]) {
+ [parser setDelegate:_parentParserDelegate];
+ }
+}
+
+
+@end
@@ -0,0 +1,20 @@
+//
+// Created by rblunden on 1/17/13.
+//
+// To change the template use AppCode | Preferences | File Templates.
+//
+
+
+#import <Foundation/Foundation.h>
+
+
+@interface RSSItem : NSObject <NSXMLParserDelegate> {
+ NSMutableString *currentString;
+}
+
+@property(nonatomic, weak) id parentParserDelegate;
+
+@property(nonatomic, strong) NSString *title;
+@property(nonatomic, strong) NSString *link;
+
+@end
@@ -0,0 +1,38 @@
+//
+// Created by rblunden on 1/17/13.
+//
+// To change the template use AppCode | Preferences | File Templates.
+//
+
+
+#import "RSSItem.h"
+
+
+@implementation RSSItem {
+
+}
+
+- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
+
+ if ([elementName isEqual:@"title"]) {
+ currentString = [[NSMutableString alloc] init];
+ [self setTitle:currentString];
+ }
+ else if ([elementName isEqual:@"link"]) {
+ currentString = [[NSMutableString alloc] init];
+ [self setLink:currentString];
+ }
+}
+
+- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)str {
+ [currentString appendString:str];
+}
+
+- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
+ currentString = nil;
+
+ if ([elementName isEqual:@"item"]) {
+ [parser setDelegate:_parentParserDelegate];
+ }
+}
+@end
@@ -0,0 +1,13 @@
+//
+// NerdfeedTests.h
+// NerdfeedTests
+//
+// Created by Ryan Blunden on 01/17/13.
+// Copyright (c) 2013 __MyCompanyName__. All rights reserved.
+//
+
+#import <SenTestingKit/SenTestingKit.h>
+
+@interface NerdfeedTests : SenTestCase
+
+@end
Oops, something went wrong.

0 comments on commit 1bc98b9

Please sign in to comment.