Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

MVC Store

  • Loading branch information...
commit 23ddf24fd03458b77b307b843e055caf6f7b523e 1 parent 65a95ea
Ryan Blunden authored
View
24 Nerdfeed/Nerdfeed/BNRConnection.h
@@ -0,0 +1,24 @@
+//
+// Created by rblunden on 1/18/13.
+//
+// To change the template use AppCode | Preferences | File Templates.
+//
+
+
+#import <Foundation/Foundation.h>
+
+
+@interface BNRConnection : NSObject <NSURLConnectionDelegate, NSURLConnectionDataDelegate> {
+ NSURLConnection *internalConnection;
+ NSMutableData *container;
+}
+
+- (id)initWithRequest:(NSURLRequest *)request;
+
+@property(nonatomic, copy) NSURLRequest *request;
+@property(nonatomic, copy) void (^completionBlock)(id obj, NSError *err);
+@property(nonatomic, strong) id <NSXMLParserDelegate> xmlRootObject;
+
+- (void)start;
+
+@end
View
73 Nerdfeed/Nerdfeed/BNRConnection.m
@@ -0,0 +1,73 @@
+//
+// Created by rblunden on 1/18/13.
+//
+// To change the template use AppCode | Preferences | File Templates.
+//
+
+
+#import "BNRConnection.h"
+
+
+@implementation BNRConnection {
+
+}
+
+static NSMutableArray *sharedConnectionList = nil;
+
+- (id)initWithRequest:(NSURLRequest *)req {
+ self = [super init];
+ if (self) {
+ [self setRequest:req];
+ }
+ return self;
+}
+
+- (void)start {
+ // Initialize container for data collected from NSURLConnection
+ container = [[NSMutableData alloc] init];
+
+ // Spawn connection
+ internalConnection = [[NSURLConnection alloc] initWithRequest:[self request] delegate:self
+ startImmediately:YES];
+
+ // If this is the first connection started, create the array
+ if (!sharedConnectionList) {
+ sharedConnectionList = [[NSMutableArray alloc] init];
+
+ // Add the connection to the array so it doesn't get destroyed
+ [sharedConnectionList addObject:self];
+ }
+}
+
+- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
+ [container appendData:data];
+}
+
+- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
+ // IF there is "root object"
+ if ([self xmlRootObject]) {
+ // Create a parser with the incoming data and let the root object parse its contents
+ NSXMLParser *parser = [[NSXMLParser alloc] initWithData:container];
+ [parser setDelegate:[self xmlRootObject]];
+ [parser parse];
+ }
+
+ // Then pass the root object to the completion block - remember, this is the block that the controller supplied
+ if ([self completionBlock]) {
+ [self completionBlock]([self xmlRootObject], nil);
+ }
+
+ // now, destory the connection
+ [sharedConnectionList removeObject:self];
+}
+
+- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
+ // Pass the error from the connection to the completion block
+ if ([self completionBlock]) {
+ [self completionBlock](NSIsNotNilTransformerName, error);
+ }
+
+ // Destroy the connection
+ [sharedConnectionList removeObject:self];
+}
+@end
View
19 Nerdfeed/Nerdfeed/BNRFeedStore.h
@@ -0,0 +1,19 @@
+//
+// Created by rblunden on 1/18/13.
+//
+// To change the template use AppCode | Preferences | File Templates.
+//
+
+
+#import <Foundation/Foundation.h>
+
+@class RSSChannel;
+
+@interface BNRFeedStore : NSObject
+
++ (BNRFeedStore *)sharedStore;
+
+- (void)fetchRSSFeedWithCompletion:(void (^)(RSSChannel *obj, NSError *err))block;
+
+- (void)fetchTopSongs:(int)count withCompletion:(void (^)(RSSChannel *obj, NSError *err))block;
+@end
View
68 Nerdfeed/Nerdfeed/BNRFeedStore.m
@@ -0,0 +1,68 @@
+//
+// Created by rblunden on 1/18/13.
+//
+// To change the template use AppCode | Preferences | File Templates.
+//
+
+
+#import "BNRFeedStore.h"
+#import "RSSChannel.h"
+#import "BNRConnection.h"
+
+@implementation BNRFeedStore {
+
+}
++ (BNRFeedStore *)sharedStore {
+ static BNRFeedStore *feedStore = nil;
+ if (!feedStore) {
+ feedStore = [[BNRFeedStore alloc] init];
+ }
+
+ return feedStore;
+}
+
+- (void)fetchRSSFeedWithCompletion:(void (^)(RSSChannel *, NSError *))block {
+ NSURL *url = [NSURL URLWithString:
+ @"http://forums.bignerdranch.com/"
+ @"smartfeed.php?limit=1_DAY&sort_by=standard"
+ @"&feed_type=RSS2.0&feed_style=COMPACT"
+ ];
+
+ NSURLRequest *req = [NSURLRequest requestWithURL:url];
+
+ // Create an empty channel
+ RSSChannel *channel = [[RSSChannel alloc] init];
+
+ // Create a connection "actor" object that will transfer data from the server
+ BNRConnection *connection = [[BNRConnection alloc] initWithRequest:req];
+
+ // When the connection completes, this block from the controller will be called
+ [connection setCompletionBlock:block];
+
+ // Let the empty channel parse the returning data from teh web service
+ [connection setXmlRootObject:channel];
+
+ // Begin the connection
+ [connection start];
+}
+
+- (void)fetchTopSongs:(int)count withCompletion:(void (^)(RSSChannel *, NSError *))block {
+ // Prepare a request URL, including the argument from the controler
+ NSString *requestString = [NSString stringWithFormat:
+ @"http://itunes.apple.com/us/rss/topsongs/limit=%d/xml", count];
+
+ NSURL *url = [NSURL URLWithString:requestString];
+
+ // Set up the connection as normal
+ NSURLRequest *req = [NSURLRequest requestWithURL:url];
+ RSSChannel *channel = [[RSSChannel alloc] init];
+
+ BNRConnection *connection = [[BNRConnection alloc] initWithRequest:req];
+ [connection setCompletionBlock:block];
+ [connection setXmlRootObject:channel];
+
+ [connection start];
+}
+
+
+@end
View
6 Nerdfeed/Nerdfeed/ListViewController.h
@@ -10,12 +10,18 @@
@class RSSChannel;
@class WebViewController;
+// WTF is this?
+typedef enum {
+ ListViewControllerRSSTypeBNR,
+ ListViewControllerRSSTypeApple
+} ListViewControllerRSSType;
@interface ListViewController : UITableViewController <NSURLConnectionDelegate, NSURLConnectionDataDelegate, NSXMLParserDelegate> {
NSURLConnection *connection;
NSMutableData *xmlData;
RSSChannel *channel;
+ ListViewControllerRSSType rssType;
}
@property(nonatomic, strong) WebViewController *webViewController;
View
108 Nerdfeed/Nerdfeed/ListViewController.m
@@ -10,6 +10,7 @@
#import "RSSItem.h"
#import "WebViewController.h"
#import "ChannelViewController.h"
+#import "BNRFeedStore.h"
@implementation ListViewController {
@@ -23,12 +24,25 @@ - (id)initWithStyle:(UITableViewStyle)style {
style:UIBarButtonItemStyleBordered target:self
action:@selector(showInfo:)];
[[self navigationItem] setRightBarButtonItem:bbi];
+
+ UISegmentedControl *rssTypeControl = [[UISegmentedControl alloc] initWithItems:@[@"BNR", @"Apple"]];
+ [rssTypeControl setSelectedSegmentIndex:0];
+ [rssTypeControl setSegmentedControlStyle:UISegmentedControlStyleBar];
+ [rssTypeControl addTarget:self action:@selector(changeType:)
+ forControlEvents:UIControlEventValueChanged];
+ [[self navigationItem] setTitleView:rssTypeControl];
+
[self fetchEntries];
}
return self;
}
+- (void)changeType:(id)sender {
+ rssType = [sender selectedSegmentIndex];
+ [self fetchEntries];
+}
+
- (void)showInfo:(id)showInfo {
// Create the channel view controller
ChannelViewController *channelViewController = [[ChannelViewController alloc] initWithStyle:UITableViewStyleGrouped];
@@ -103,73 +117,33 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath
}
- (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];
+ void (^completionBlock)(RSSChannel *obj, NSError *err) =
+ ^(RSSChannel *obj, NSError *err) {
+ // When the request completes, this block will be called
+
+ if (!err) {
+ // If everything went ok, grab the channel object and reload the table
+ channel = obj;
+
+ [[self tableView] reloadData];
+ }
+ else {
+ // If things went bad...
+ UIAlertView *av = [[UIAlertView alloc] initWithTitle:@"error" message:[err localizedDescription]
+ delegate:nil cancelButtonTitle:@"OK"
+ otherButtonTitles:nil];
+ [av show];
+ };
+ };
+
+ // Initiate the request
+ if (rssType == ListViewControllerRSSTypeBNR) {
+ [[BNRFeedStore sharedStore] fetchRSSFeedWithCompletion:completionBlock];
+ }
+ else if (rssType == ListViewControllerRSSTypeApple) {
+ [[BNRFeedStore sharedStore] fetchTopSongs:10
+ withCompletion:completionBlock];
+ }
}
@end
View
2  Nerdfeed/Nerdfeed/RSSChannel.m
@@ -32,7 +32,7 @@ - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName nam
currentString = [[NSMutableString alloc] init];
[self setInfoString:currentString];
}
- else if([elementName isEqual:@"item"]) {
+ else if([elementName isEqual:@"item"] || [elementName isEqual:@"entry"]) {
// When we find an item, create an instance of an RSSItem
RSSItem *entry = [[RSSItem alloc] init];
View
2  Nerdfeed/Nerdfeed/RSSItem.m
@@ -31,7 +31,7 @@ - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)str {
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
currentString = nil;
- if ([elementName isEqual:@"item"]) {
+ if ([elementName isEqual:@"item"] || [elementName isEqual:@"entry"]) {
[parser setDelegate:_parentParserDelegate];
}
}
Please sign in to comment.
Something went wrong with that request. Please try again.