Permalink
Browse files

Universalizing NerdFeed and implementing the split view controller

  • Loading branch information...
1 parent a6b95d1 commit 65a95ea021fe4d00c80136008e35581be21c432f Ryan Blunden committed Jan 18, 2013
View
16 Nerdfeed/Nerdfeed/ChannelViewController.h
@@ -0,0 +1,16 @@
+//
+// Created by rblunden on 1/17/13.
+//
+// To change the template use AppCode | Preferences | File Templates.
+//
+
+
+#import <Foundation/Foundation.h>
+#import "ListViewController.h"
+
+@class RSSChannel;
+
+@interface ChannelViewController : UITableViewController <ListViewControllerDelegate, UISplitViewControllerDelegate> {
+ RSSChannel *channel;
+}
+@end
View
78 Nerdfeed/Nerdfeed/ChannelViewController.m
@@ -0,0 +1,78 @@
+//
+// Created by rblunden on 1/17/13.
+//
+// To change the template use AppCode | Preferences | File Templates.
+//
+
+
+#import "ChannelViewController.h"
+#import "RSSChannel.h"
+
+
+@implementation ChannelViewController {
+
+}
+
+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
+ return 2;
+}
+
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
+ UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"UITableView"];
+
+ if (!cell) {
+ cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue2
+ reuseIdentifier:@"UITableViewCell"];
+ }
+
+ if ([indexPath row] == 0) {
+ // Put the title of the channel in row 0
+ [[cell textLabel] setText:@"Title"];;
+ [[cell detailTextLabel] setText:[channel title]];
+ }
+ else {
+ // Put the description of the channel in row 1
+ [[cell textLabel] setText:@"Info"];
+ [[cell detailTextLabel] setText:[channel infoString]];
+ }
+
+ return cell;
+}
+
+- (NSUInteger)supportedInterfaceOrientations {
+ return UIInterfaceOrientationMaskAllButUpsideDown;
+}
+
+- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
+ return UIInterfaceOrientationMaskAllButUpsideDown;
+}
+
+- (void)listViewController:(ListViewController *)lvc handleObject:(id)object {
+ // If we are in portrait mode, provide a button to show the split pane view menu as it disappears when
+ // clicking on the nav bar
+ if (UIDeviceOrientationIsPortrait([self interfaceOrientation])) {
+
+ }
+
+ // Make sure the ListViewController gave us the right object
+ if (![object isKindOfClass:[RSSChannel class]]) {
+ return;
+ }
+
+ channel = object;
+
+ [[self tableView] reloadData];
+}
+
+- (void)splitViewController:(UISplitViewController *)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)pc {
+ [barButtonItem setTitle:@"List"];
+
+ [[self navigationItem] setLeftBarButtonItem:barButtonItem];
+}
+
+- (void)splitViewController:(UISplitViewController *)svc willShowViewController:(UIViewController *)aViewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem {
+ if (barButtonItem == [[self navigationItem] leftBarButtonItem]) {
+ [[self navigationItem] setLeftBarButtonItem:nil];
+ }
+}
+@end
View
6 Nerdfeed/Nerdfeed/ListViewController.h
@@ -22,4 +22,10 @@
- (void)fetchEntries;
+@end
+
+@protocol ListViewControllerDelegate
+// Classes that conform to this protocol must implement this method
+- (void)listViewController:(ListViewController *)lvc handleObject:(id)object;
+
@end
View
68 Nerdfeed/Nerdfeed/ListViewController.m
@@ -9,6 +9,7 @@
#import "RSSChannel.h"
#import "RSSItem.h"
#import "WebViewController.h"
+#import "ChannelViewController.h"
@implementation ListViewController {
@@ -18,12 +19,51 @@ @implementation ListViewController {
- (id)initWithStyle:(UITableViewStyle)style {
self = [super initWithStyle:style];
if (self) {
+ UIBarButtonItem *bbi = [[UIBarButtonItem alloc] initWithTitle:@"Info"
+ style:UIBarButtonItemStyleBordered target:self
+ action:@selector(showInfo:)];
+ [[self navigationItem] setRightBarButtonItem:bbi];
[self fetchEntries];
}
return self;
}
+- (void)showInfo:(id)showInfo {
+ // Create the channel view controller
+ ChannelViewController *channelViewController = [[ChannelViewController alloc] initWithStyle:UITableViewStyleGrouped];
+
+ if ([self splitViewController]) {
+ UINavigationController *nvc = [[UINavigationController alloc] initWithRootViewController:channelViewController];
+
+ // Grab a pointer to the split view controller and reset its view controllers array
+ [[self splitViewController] setViewControllers:@[[self navigationController], nvc]];
+
+ // Make detail view controller the delegate of the split view controller and reset its view controllers array
+ [[self splitViewController] setDelegate:channelViewController];
+
+ // If a row has been selected, delesect it so that a row is not slected when viewing the info
+ NSIndexPath *selectedRow = [[self tableView] indexPathForSelectedRow];
+ if (selectedRow) {
+ [[self tableView] deselectRowAtIndexPath:selectedRow animated:YES];
+ }
+ }
+ else {
+ [[self navigationController] pushViewController:channelViewController animated:YES];
+ }
+
+ // Give the VC the channel object through the protocol message
+ [channelViewController listViewController:self handleObject:channel];
+}
+
+- (NSUInteger)supportedInterfaceOrientations {
+ return UIInterfaceOrientationMaskAllButUpsideDown;
+}
+
+- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
+ return UIInterfaceOrientationMaskAllButUpsideDown;
+}
+
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [[channel items] count];
}
@@ -42,24 +82,24 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
- // Push the web view controller onto the navigation stack - this implicitly creates the web view controller's view
- // the first time through
- [[self navigationController] pushViewController:_webViewController animated:YES];
-
- // Grab the selected item
- RSSItem *entry = [channel items][[indexPath row]];
+ if (![self splitViewController]) {
+ [[self navigationController] pushViewController:_webViewController animated:YES];
+ }
+ else {
+ // We have to create a new navigation controller, as the old one was retained by the split view controller as is
+ // now gone
+ UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:_webViewController];
- // Construct a URL with the link string of the item
- NSURL *url = [NSURL URLWithString:[entry link]];
+ [[self splitViewController] setViewControllers:@[[self navigationController], nav]];
- // Construct a request object with that URL
- NSURLRequest *req = [NSURLRequest requestWithURL:url];
+ // Make the detail view controller the dlegate of the split view controller
+ [[self splitViewController] setDelegate:_webViewController];
+ }
- // Load the request into the web view
- [[_webViewController webView] loadRequest:req];
+ // Grab the selected item
+ RSSItem *entry = [channel items][[indexPath row]];
- // Set the title of the web view controller's navigation item
- [[_webViewController navigationItem] setTitle:[entry title]];
+ [_webViewController listViewController:self handleObject:entry];
}
- (void)fetchEntries {
View
19 Nerdfeed/Nerdfeed/NerdfeedAppDelegate.m
@@ -23,7 +23,24 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
WebViewController *wvc = [[WebViewController alloc] init];
[lvc setWebViewController:wvc];
- [[self window] setRootViewController:masterNav];
+ // Check to make sure we're running on the iPad
+ if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
+ // webViewController must be in navigation controller, you'll see why later
+ UINavigationController *detailNav = [[UINavigationController alloc] initWithRootViewController:wvc];
+
+ UISplitViewController *svc = [[UISplitViewController alloc] init];
+
+ // Set the delegate of the split view controller to the detail VC. We'll need this later
+ [svc setDelegate:wvc];
+ [svc setViewControllers:@[masterNav, detailNav]];
+
+ // Set the root view controller
+ [[self window] setRootViewController:svc];
+ }
+ else {
+ // On non-iPad devices, go with old version, just add the single nav controller to the window
+ [[self window] setRootViewController:masterNav];
+ }
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
View
3 Nerdfeed/Nerdfeed/WebViewController.h
@@ -6,9 +6,10 @@
#import <Foundation/Foundation.h>
+#import "ListViewController.h"
-@interface WebViewController : UIViewController <UIPageViewControllerDelegate>
+@interface WebViewController : UIViewController <UIPageViewControllerDelegate, ListViewControllerDelegate, UISplitViewControllerDelegate>
@property(nonatomic, readonly, strong) UIWebView *webView;
View
43 Nerdfeed/Nerdfeed/WebViewController.m
@@ -6,6 +6,7 @@
#import "WebViewController.h"
+#import "RSSItem.h"
@implementation WebViewController {
@@ -26,4 +27,46 @@ - (void)loadView {
- (UIWebView *)webView {
return (UIWebView *) [self view];
}
+
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)io {
+ if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
+ return YES;
+ }
+
+ return io == UIInterfaceOrientationPortrait;
+}
+
+- (void)listViewController:(ListViewController *)lvc handleObject:(id)object {
+ // Cast the passed object to an RSSItem
+ RSSItem *entry = object;
+
+ // Make sure that we are really getting a RSSItem
+ if (![entry isKindOfClass:[RSSItem class]]) {
+ return;
+ }
+
+ // Grab the info from the item and push it into the appropriate views
+ NSURL *url = [NSURL URLWithString:[entry link]];
+ NSURLRequest *req = [NSURLRequest requestWithURL:url];
+ [[self webView] loadRequest:req];
+
+ [[self navigationItem] setTitle:[entry title]];
+}
+
+- (void)splitViewController:(UISplitViewController *)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)pc {
+ // If this bar button item doesn't hav a title, it won't appear at all
+ [barButtonItem setTitle:@"List"];
+
+ // Take this bar button item and put it on the left side of our nav item
+ [[self navigationItem] setLeftBarButtonItem:barButtonItem];
+}
+
+- (void)splitViewController:(UISplitViewController *)svc willShowViewController:(UIViewController *)aViewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem {
+ // Remove the bar button item from our navigation item. We'll double check that its the correct button,
+ // even though we know it is
+ if (barButtonItem == [[self navigationItem] leftBarButtonItem]) {
+ [[self navigationItem] setLeftBarButtonItem:nil];
+ }
+}
+
@end

0 comments on commit 65a95ea

Please sign in to comment.