i search for a way to have multiple detail view in iPad application and i find the sample code in apple developer site http://developer.apple.com/library/ios/#samplecode/MultipleDetailViews/Introduction/Intro.html , but now i want to have navigation in detail view which this sample does not cover, i add uinavigationcontroller to detail view as :
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
ReportsViewController_iPad *master = [[ReportsViewController_iPad alloc] initWithNibName:#"ReportsViewController_iPad" bundle:nil];
DetailViewController_iPad *detail = [[DetailViewController_iPad alloc] initWithNibName:#"DetailViewController_iPad" bundle:nil];
UINavigationController *masterNavController = [[[UINavigationController alloc] initWithRootViewController:master ] autorelease];
UINavigationController *detailNavController = [[[UINavigationController alloc] initWithRootViewController:detail ] autorelease];
splitViewController.viewControllers = [NSArray arrayWithObjects:masterNavController , detailNavController, nil];
[window addSubview:splitViewController.view];
[window makeKeyAndVisible];
return YES;
}
but when i run the sample i got error
[UINavigationController showRootPopoverButtonItem:]: unrecognized selector sent to instance...
showRootPopoverButtonItem is a method define in a protocol in RootViewController
#protocol SubstitutableDetailViewController
- (void)showRootPopoverButtonItem:(UIBarButtonItem *)barButtonItem;
- (void)invalidateRootPopoverButtonItem:(UIBarButtonItem *)barButtonItem;
#end
---- ReportsViewController.h
#protocol SubstitutableDetailViewController
- (void)showRootPopoverButtonItem:(UIBarButtonItem *)barButtonItem;
- (void)invalidateRootPopoverButtonItem:(UIBarButtonItem *)barButtonItem;
#end
#protocol DetailViewControllerManagerDelegate
-(void) didSelectRowAtIndexPathPopOver:(NSString *)ID;
#end
#interface ReportsViewController_iPad : ReportsViewController<UISplitViewControllerDelegate , DetailViewControllerManagerDelegate>
{
UISplitViewController *splitViewController;
UIPopoverController *popoverController;
UIBarButtonItem *rootPopoverButtonItem;
}
#property (nonatomic, assign) IBOutlet UISplitViewController *splitViewController;
#property (nonatomic, retain) UIPopoverController *popoverController;
#property (nonatomic, retain) UIBarButtonItem *rootPopoverButtonItem;
#property(nonatomic, retain) id<DetailViewControllerManagerDelegate> delegate;
-(void)didSelectRowAtIndexPath:(NSString*)ID;
#end
--DetailViewController.h
#import <UIKit/UIKit.h>
#import "ReportsViewController_iPad.h"
#interface DetailViewController_iPad : UIViewController<SubstitutableDetailViewController>
{
UIToolbar *toolbar;
}
#property (nonatomic, retain) IBOutlet UIToolbar *toolbar;
#end
--DetailViewController.m
#import "DetailViewController_iPad.h"
#implementation DetailViewController_iPad
#synthesize toolbar;
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
#pragma mark -
#pragma mark Managing the popover
- (void)showRootPopoverButtonItem:(UIBarButtonItem *)barButtonItem {
// Add the popover button to the toolbar.
NSMutableArray *itemsArray = [toolbar.items mutableCopy];
[itemsArray insertObject:barButtonItem atIndex:0];
[toolbar setItems:itemsArray animated:NO];
[itemsArray release];
}
- (void)invalidateRootPopoverButtonItem:(UIBarButtonItem *)barButtonItem {
// Remove the popover button from the toolbar.
NSMutableArray *itemsArray = [toolbar.items mutableCopy];
[itemsArray removeObject:barButtonItem];
[toolbar setItems:itemsArray animated:NO];
[itemsArray release];
}
- (void)dealloc {
[toolbar release];
[super dealloc];
}
#end
So Thanks in advance.
Where definition of method showRootPopoverButtonItem is present, seems like this is not defined. You need to define it.
If you want to avoid crash then you can use -
if ([aViewController respondsToSelector:#selector(showRootPopoverButtonItem:)]) {
[aViewController performSelector:#selector(showRootPopoverButtonItem:) withObject:self.rootPopoverButtonItem];
}
EDIT -
I have checked this and found what you are doing wrong , for e.g. code in willHideViewController-
UIViewController <SubstitutableDetailViewController> *detailViewController = [splitViewController.viewControllers objectAtIndex:1];
this is expecting a view controller, while you are passing navigation controller which in turn has view controller(similar at some other position), so you need to alter these codes as well if you want to pass navigation controller from app delegate.
Related
I have a view controller which is my HomeViewController, and I have a modal segue between them.
This is the HomeViewController:
import "HomePageViewController.h"
#import "CreatePageViewController.h"
#import "StackTableViewController.h"
#import "PopUpView.h"
#interface HomePageViewController ()
#property (nonatomic, strong) IBOutlet UIButton *toggleButton;
#property (nonatomic, strong) CreatePageViewController *modalTest;
#property (nonatomic, strong) PopUpView *popup;
#end
#implementation HomePageViewController
-(UIStatusBarStyle)preferredStatusBarStyle{
return UIStatusBarStyleLightContent;
}
-(void)viewDidLoad {
[super viewDidLoad];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:Nil];
_modalTest = [storyboard instantiateViewControllerWithIdentifier:#"ModalTest"];
[_toggleButton addTarget:self action:#selector(go) forControlEvents:UIControlEventTouchUpInside];
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(hide) name:#"HideAFPopup" object:nil];
}
-(void)go {
_popup = [PopUpView popupWithView:_modalTest.view];
[_popup show];
}
-(void)hide {
[_popup hide];
}
- (IBAction)pushToNextViewController:(id)sender {
StackTableViewController *vc = [[StackTableViewController alloc]init];
[self presentModalViewController:vc animated:YES];
}
-(void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
#end
I want to add a navigation controller to StackTableViewController...its just a table view and I want it to have a navigation controller, how should I do this?
Also, why xcode tells me my modal method presentModalViewController is deprecated?
tnx
Create a new instance of UINavigationController, with your StackTableViewController as its rootViewController. Then present the navigation controller:
- (IBAction)pushToNextViewController:(id)sender {
StackTableViewController *vc = [[StackTableViewController alloc]init];
UINavigationController *navCtrl = [[UINavigationController alloc] initWithRootViewController:vc];
[self presentViewController:navCtrl animated:YES completion:nil];
}
Note that presentModalViewController:animated: is deprecated because it has been replaced by presentViewController:animated:completion:.
I am having an iPad app in which I want to implement a Side Bar functionality like we have in facebook app.
I am using this Demo for this.
With this I have successfully implemented the Side Bar functionality and its working well but with that my first view doesn't show me well.
Below is the screenshot.
As you can see from the screenshot, there is a black background and my whole view is not showing in full screen when the app launches.
It should be like below.
Also on clicking the button the Side View is showing like below.
It should be small as I have taken the view size with width = 300 and height = 768.
But it is showing bigger than that.
Here is my code which I change in my appdelegate.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[self createEditableCopyOfDatabaseIfNeeded];
// Override point for customization after application launch.
self.viewController = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
UINavigationController *navController = [[UINavigationController alloc]initWithRootViewController:self.viewController];
SlidingViewController *slidingView = [[SlidingViewController alloc]initWithNibName:#"SlidingViewController" bundle:nil];
self.slideMenuController = [[SlideMenuController alloc] initWithCenterViewController:navController];
self.slideMenuController.leftViewController = slidingView;
self.window.rootViewController = navController;
[self.window makeKeyAndVisible];
return YES;
}
- (IBAction)sideBarPressed:(id)sender
{
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
if (appDelegate.slideMenuController.position == TKSlidePositionCenter) {
[appDelegate.slideMenuController presentLeftViewControllerAnimated:YES];
} else {
[appDelegate.slideMenuController presentCenterViewControllerAnimated:YES];
}
}
I want this for my iPad for Landscape mode only.
Please tell me What is wrong here?
I am stuck here for quite a while.
Any help will be appreciated.
Thanks in advance.
So better u need to use UISplitViewController
//in app delegate do like this
//in appDelegate.h file
#import <UIKit/UIKit.h>
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (nonatomic, retain) UISplitViewController *splitViewCOntroller;
#end
//in appDelegate.m file
#import "AppDelegate.h"
#import "SplitMasterViewController.h" //create a UITableviewController
#import "SplitViewDetailController.h" //create a UIViewController
#implementation AppDelegate
#synthesize splitViewCOntroller = _splitViewCOntroller;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
SplitMasterViewController *masterController = [[SplitMasterViewController alloc]initWithNibName:#"SplitMasterViewController" bundle:nil]; //this is the master menu controller
UINavigationController *masterNavController = [[UINavigationController alloc]initWithRootViewController:masterController];
SplitViewDetailController *detailViewController = [[SplitViewDetailController alloc]initWithNibName:#"SplitViewDetailController" bundle:nil]; //this is the master detail controller
UINavigationController *detailNavController = [[UINavigationController alloc]initWithRootViewController:detailViewController];
masterController.detailViewController = detailViewController;
_splitViewCOntroller = [[UISplitViewController alloc]init]; //initilise split controller
_splitViewCOntroller.delegate = detailViewController; //set the delegate to detail controller
_splitViewCOntroller.viewControllers = [NSArray arrayWithObjects:masterNavController,detailNavController, nil]; //set the splitview controller
self.window.rootViewController = _splitViewCOntroller; //finally your splitviewcontroller as the root view controller
[self.window makeKeyAndVisible];
return YES;
}
//in SplitMasterViewController.h this must be a table that contains your side bar menu items
#import "ViewController.h" //comment this if it shows any error
#import "SplitViewDetailController.h"
#interface SplitMasterViewController : UITableViewController<UITableViewDataSource,UITableViewDelegate>
#property (nonatomic, retain) SplitViewDetailController *detailViewController; //to get the detailview from masterMenu controller
#property (nonatomic, retain) NSArray *Names;
#end
// in SplitMasterViewController.m file
#import "SplitMasterViewController.h"
#import "SplitViewDetailController.h"
#interface SplitMasterViewController ()
#end
#implementation SplitMasterViewController
#synthesize Names;
#synthesize detailViewController;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
Names = [[NSArray alloc] initWithObjects:#"apple", #"banana",
#"mango", #"grapes", nil];
[self.tableView selectRowAtIndexPath:
[NSIndexPath indexPathForRow:0 inSection:0]
animated:NO
scrollPosition:UITableViewScrollPositionMiddle];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [Names count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
}
// [self configureCell:cell atIndexPath:indexPath];
cell.textLabel.text = [Names objectAtIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
SplitViewDetailController *detailController = self.detailViewController;
detailController.myLabel.text = [Names objectAtIndex:indexPath.row]; //set the name from the array
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
//in SplitViewDetailController.h
#import "ViewController.h"
#interface SplitViewDetailController : UIViewController<UISplitViewControllerDelegate>
#property (strong, nonatomic) id detailItem;
#property (strong, nonatomic) IBOutlet UILabel *myLabel;
#property (nonatomic, retain) UIBarButtonItem *leftBarButtonItem; //to show a button on left side
#end
//in SplitViewDetailController.m
#import "SplitViewDetailController.h"
#interface SplitViewDetailController ()
{
UIPopoverController *masterPopoverController;
}
#end
#implementation SplitViewDetailController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// _leftBarButtonItem = [[UIBarButtonItem alloc]initWithTitle:#"Menu" style:UIBarButtonItemStyleBordered target:self action:nil];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
//these are the call back to detail view controller to hide or show the button
- (void)splitViewController:(UISplitViewController *)splitController willHideViewController:(UIViewController *)viewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)popoverController
{
_leftBarButtonItem = barButtonItem;
_leftBarButtonItem.style = UIBarButtonItemStyleBordered;
_leftBarButtonItem.title = #"Menu";
[self.navigationItem setLeftBarButtonItem:_leftBarButtonItem animated:YES];
}
// Called when the view is shown again in the split view, invalidating the button
- (void)splitViewController:(UISplitViewController *)splitController willShowViewController:(UIViewController *)viewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem
{
[self.navigationItem setLeftBarButtonItem:nil animated:YES];
}
#end
I successfully implemented this side bar menu functionality with this Demo code and its working perfectly well in my case.
Hope it works to someone else also.
Thanks for your help and suggestions.
i am using this and it's good
https://github.com/ECSlidingViewController/ECSlidingViewController
Having a bit of a problem, here's the breakdown:
My AppDelegate uses as it's rootViewController a view controller. This view controller's purpose is to swap a couple of other view controllers in and out, call it login and main screens. For the sake of simplicity I've removed any swapping code from the code that I will post and am having the rootViewController simply show it's first content view controller, say login.
The issue I'm having is that the content view controller seems to be pushed down a little bit inside the rootViewController. I've given the rootViewController a blue background and the content view controller an orange background. Here's my code:
AppDelegate.h
#import <UIKit/UIKit.h>
#class MainViewController;
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) MainViewController *main;
#end
AppDelegate.m
#import "AppDelegate.h"
#import "MainViewController.h"
#implementation AppDelegate
#synthesize main;
- (void)dealloc
{
[_window release];
[main release];
[super dealloc];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
MainViewController *mainVC = [[MainViewController alloc] init];
self.main = mainVC;
self.window.rootViewController = self.main;
[self.window makeKeyAndVisible];
return YES;
}
MainViewController.h
#import <UIKit/UIKit.h>
#class ContentViewController;
#interface MainViewController : UIViewController
#property (nonatomic, retain) ContentViewController *content;
#end
MainViewController.m
#import "MainViewController.h"
#import "ContentViewController.h"
#implementation MainViewController
#synthesize content;
- (id)init
{
self = [super init];
if (self ) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor blueColor];
ContentViewController *viewController = [[ContentViewController alloc] init];
self.content = viewController;
[self.view insertSubview:self.content.view atIndex:0];
}
- (void)dealloc {
[content release];
[super dealloc];
}
#end
ContentViewController.h
#import <UIKit/UIKit.h>
#interface LoginVC : UIViewController
#end
ContentViewController.m
#import "ContentViewController.h"
#implementation ContentViewController
- (id)init
{
self = [super init];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor orangeColor];
}
- (void)dealloc {
[super dealloc];
}
#end
The above codes gives me a status bar with a blue strip (approximately the height of the status bar) under it (which is the main view controller) followed by the orange content view controller taking up the rest of the screen. For some reason that main view controller seems to be pushing the content view controller down a little.
Strangely, if I create a view controller and use a XIB for drawing the view, it looks just fine and the content view it right up against the top of the main view.
If anybody could shed some light on this issue I'd very much appreciate it.
Cheers
I suppose that you shouldn't be doing
ContentViewController *viewController = [[ContentViewController alloc] init];
self.content = viewController;
[self.view insertSubview:self.content.view atIndex:0];
but rather:
ContentViewController *viewController = [[ContentViewController alloc] init];
self.content = viewController;
[self presentViewController:self.content animated:YES completion:nil];
I'm trying to create a SplitViewController view but I get the following warning:
Property splitViewController requires a method setSplitViewController to be defined -use #Synthesize,#dynamic or provide a method implementation in this class implement.
Here is the code
///AppDelegate.h
#class ViewController;
#class DetailViewController;
#interface AppDelegate : UIResponder <UIApplicationDelegate, UISplitViewControllerDelegate>
{
UISplitViewController *splitViewController;
ViewController *viewcontroller;
DetailViewController *detailViewController;
}
#property (nonatomic,retain) UIWindow *window;
#property (nonatomic,retain) DetailViewController *detailViewController;
#property(nonatomic,retain) UISplitViewController *splitViewController;
#property (nonatomic,retain) ViewController *viewController;
#end
///AppDelegate.m"
#import "ViewController.h"
#import "DetailViewController.h"
#implementation AppDelegate
#synthesize window = _window;
#synthesize viewController = _viewController;
#synthesize splitviewController;
#synthesize detailViewController;
- (void)dealloc
{
[_window release];
[_viewController release];
[super dealloc];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
ViewController *rootViewController = [[ViewController alloc] initWithStyle:UITableViewStylePlain];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
detailViewController = [[DetailViewController alloc] initWithNibName:#"DetailView" bundle:nil];
rootViewController.detailViewController = detailViewController;
splitViewController = [[UISplitViewController alloc] init];
splitViewController.viewControllers = [NSArray arrayWithObjects:navigationController, detailViewController, nil];
splitViewController.delegate = detailViewController;
[self.window makeKeyAndVisible];
return YES;
}
///ViewController.h
#import <UIKit/UIKit.h>
#class DetailViewController;
#interface ViewController : UITableViewController{
DetailViewController *detailViewController;
NSMutableArray *phone;
}
#property (nonatomic,retain)IBOutlet DetailViewController *detailViewController;
#property (nonatomic,retain) NSMutableArray *phone;
#end
///ViewController.m
#import "ViewController.h"
#import "DetailViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize detailViewController,phone;
- (CGSize)contentSizeForViewInPopoverView {
return CGSizeMake(320, 600);
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.phone = [[NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"phone" ofType:#"plist"]] retain];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)aTableView {
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)aTableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return [phone count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"CellIdentifier";
// Dequeue or create a cell of the appropriate type.
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.accessoryType = UITableViewCellAccessoryNone;
}
// Configure the cell.
cell.textLabel.text = [self.phone objectAtIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
/*
When a row is selected, set the detail view controller's detail item to the item associated with the selected row.
*/
detailViewController.detailItem = [self.phone objectAtIndex:indexPath.row];
}
- (void)dealloc {
[detailViewController release];
[super dealloc];
}
#end
In ur code, you haven't synthesized your splitViewController property. Since You have not synthesized it the property, the compiler is issuing a warning asking u to either synthesize the property so that it can generate setters and getters automatically for your convinienvce (You can use the generated setters and getters using . notation as in self.splitViewController so synthesize it as
#synthesize splitViewController = _splitViewController
or
implement your own custom setter and getter as
//setter
- (void)setSplitViewController:(UISplitViewController*)splitViewController_ {
//assuming your property has retain identifier
if (splitViewController != splitViewController_) {
[splitViewController release];
splitViewController = [splitViewController_ retain];
}
}
//getter
- (UISplitViewController*)splitViewController {
return splitViewController;
}
or
declaring the property as dynamic using #dynamic splitViewController . This means that the setter and getter for the property will be provided from somewhere else.
EDIT:
replacedidFinishLaunchingWithOptions method in appDelegate.m with the following:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
_viewController = [[ViewController alloc] initWithNibName:#"ViewController's nib name" bundle:nil];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:_viewController];
detailViewController = [[DetailViewController alloc] initWithNibName:#"DetailView" bundle:nil];
rootViewController.detailViewController = detailViewController;
splitViewController = [[UISplitViewController alloc] init];
splitViewController.viewControllers = [NSArray arrayWithObjects:navigationController, detailViewController, nil];
splitViewController.delegate = detailViewController;
self.window.rootViewController = splitViewController;
return YES;
}
also edit the dealloc:
- (void)dealloc
{
[_window release];
[_viewController release];
[splitViewController release];
[detailViewController release];
[super dealloc];
}
And in viewController viewDidLoad replace self.phones line with this
self.phone = [[NSArray arrayWithObjects:#"Cell ONE",#"Cell TWO",#"Cell THREE",#"Cell FOUR",#"Cell FIVE",#"Cell SIX", nil];
this is just for testing that the array part is loading properly..so that you can see the cells if they are getting created. put a break point in cellForRowAtIndexPath method and see if its getting called
and then finally in didSelect see if the detailItem iVar is not nil.
And Yes, check the NIB names properly before loading them, and also that all outlets in the NIB are properly connected.
Cheers and Have fun.
The problem is you misspelled splitViewController in your #synthesize statement -- you didn't capitalize the v.
You wouldn't run into this problem if you did it the easy way. There's no need for either the instance variables or the #synthesize statements any more -- you get both automatically when create the property.
In your case add #synthesize splitViewController = _splitViewController; and detailViewController = _ detailViewController;
Here is useful code for, how can i add UISplitViewController.
/// AppDelegate.h file
#import <UIKit/UIKit.h>
#import "MasterViewController.h"
#import "DetailViewController.h"
#interface AppDelegate : UIResponder <UIApplicationDelegate, UISplitViewControllerDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (nonatomic, strong) UISplitViewController *splitViewController;
#property (nonatomic, strong) MasterViewController *masterVC;
#property (nonatomic, strong) DetailViewController *detailVC;
#property (nonatomic, strong) UINavigationController *mvcNavCon;
#property (nonatomic, strong) UINavigationController *dvcNavCon;
#end
/// AppDelegate.m File
#import "AppDelegate.h"
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
self.masterVC = [[MasterViewController alloc] init];
self.mvcNavCon = [[UINavigationController alloc] initWithRootViewController:self.masterVC];
self.detailVC = [[DetailViewController alloc] init];
self.dvcNavCon = [[UINavigationController alloc] initWithRootViewController:self.detailVC];
self.splitViewController = [[UISplitViewController alloc] init];
self.splitViewController.delegate = self;
self.splitViewController.viewControllers = [NSArray arrayWithObjects:self.mvcNavCon, self.dvcNavCon,nil];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = self.splitViewController;
[self.window makeKeyAndVisible];
return YES;
}
I have a split view controller for iPad with a drill-down table on the left. I am able to populate the tables with a drill-down without issue but I cannot seem to get the item I clicked within the UITableView on the left side to show up in detailDescriptionLabel on the right side.
I have the following code in my ProductViewController.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSLog(#"Row clicked: %i", indexPath.row);
if (_delegate != nil) {
Product *product = (Product *) [_products objectAtIndex:indexPath.row];
[_delegate productSelectionChanged:product];
}
DetailedVC *detailView = [[DetailedVC alloc] initWithNibName:#"DetailedVC" bundle:[NSBundle mainBundle]];
NSLog(#"User clicked on: %#", [NSString stringWithFormat:#"%d",indexPath.row]);
detailView.detailDescriptionLabel.text = [NSString stringWithFormat:#"%d",indexPath.row];
[self.navigationController pushViewController:detailView animated:YES];
}
What happens here is I push the DetailedVC into the left side where my table view is and what I really want to do is see the row clicked updated in my detailed view on the right. I am able to see in the Log window that I clicked on a certain index so I know I am capturing the click event and getting a value.
Inside my DetailedVC.m I have the following code to update this label.
- (void)viewDidLoad
{
[super viewDidLoad];
[self configureView];
}
- (void) configureView {
if (self.detailItem) {
self.detailDescriptionLabel.text = [self.detailItem description];
NSLog(#"Item: %#", [self.detailItem description]);
}
}
If I edit the viewDidLoad I get a (null) for the [self.detailItem description]
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"Detail description label: %#", [self.detailItem description]);
}
ProductViewController.h
#interface ProductViewController : UIViewController <UITableViewDataSource, UITableViewDelegate> {
NSMutableArray *_products;
UITableView *_productsTableView;
id<ProductSelectionDelegate> _delegate;
}
#property (nonatomic, strong) IBOutlet UITableView *productsTableView;
#property (nonatomic, retain) NSMutableArray *products;
#property (nonatomic, assign) id<ProductSelectionDelegate> delegate;
#end
AppDelegate.h
#class ProductViewController;
#class DetailedVC;
#interface TabAndSplitAppAppDelegate : NSObject <UIApplicationDelegate, UITabBarControllerDelegate> {
UIWindow *window;
UITabBarController *tabBarController;
ProductViewController *_productViewController;
DetailedVC *_detailedViewController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UITabBarController *tabBarController;
#property (nonatomic, retain) IBOutlet ProductViewController *productViewController;
#property (nonatomic, retain) IBOutlet DetailedVC *detailedViewController;
#end
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSMutableArray *products = [NSMutableArray array];
[products addObject:[[Product alloc] initWithName:#"Product 1 Name" desc:#"Product 1 Description"]];
_detailedViewController.product = [products objectAtIndex:0];
// Override point for customization after app launch.
//create split view controller
RootVC *rvc=[[RootVC alloc] init];
rvc.title=#"Root VC";
DetailedVC *dvc=[[DetailedVC alloc] init];
dvc.title=#"Detailed VC";
_productViewController.delegate = _detailedViewController;
MySplitViewController *msc = [[MySplitViewController alloc] initwithLeftVC:rvc rightVC:dvc];
msc.title=#"First";
//create a temporary VC to show in second tab
SecondViewController *vc2 = [[SecondViewController alloc] init];
vc2.title=#"Second";
//make an array containing these two view controllers
NSArray *viewControllers = [NSArray arrayWithObjects:msc,vc2,nil];
[tabBarController setViewControllers:viewControllers];
tabBarController.view.backgroundColor=[UIColor blackColor];
for(UITabBarItem*t in tabBarController.tabBar.items)
{
t.image=[UIImage imageNamed:#"icon.png"];
t.badgeValue=[NSString stringWithFormat:#"%d",([tabBarController.tabBar.items indexOfObject:t]+1)];
}
//the views are retained their new owners, so we can release
[rvc release];
[dvc release];
[msc release];
[vc2 release];
// Add the tab bar controller's current view as a subview of the window
[self.window addSubview:tabBarController.view];
[self.window makeKeyAndVisible];
return YES;
}
MySplitViewController.h
#import <UIKit/UIKit.h>
#interface MySplitViewController : UIViewController
{
UINavigationController *leftController;
UINavigationController *rightController;
}
#property (nonatomic, retain) UINavigationController *leftController;
#property (nonatomic, retain) UINavigationController *rightController;
- (void)layoutViews:(UIInterfaceOrientation)orientation initialVerticalOffset:(float)offset;
- (MySplitViewController*) initwithLeftVC:(UIViewController*)leftvc rightVC:(UIViewController*)rightvc;
#end
MySplitViewController.m
- (MySplitViewController*) initwithLeftVC:(UIViewController*)leftvc rightVC:(UIViewController*)rightvc
{
if(self=[super init])
{
UINavigationController *lnc=[[UINavigationController alloc] initWithRootViewController:leftvc];
lnc.navigationBarHidden=NO;
self.leftController=lnc;
[lnc release];
UINavigationController *rnc=[[UINavigationController alloc] initWithRootViewController:rightvc];
rnc.navigationBarHidden=NO;
self.rightController=rnc;
[rnc release];
}
return self;
}
Product.h
#import <Foundation/Foundation.h>
#interface Product : NSObject {
NSString *_productID;
NSString *_productDescription;
}
#property (nonatomic, copy) NSString *productID;
#property (nonatomic, copy) NSString *productDescription;
- (Product *)initWithName:(NSString *)productID desc:(NSString *)productDescription;
#end
Product.m
#import "Product.h"
#implementation Product
#synthesize productID = _productID;
#synthesize productDescription = _productDescription;
- (Product *)initWithName:(NSString *)productID desc:(NSString *)productDescription {
if ((self = [super init])) {
self.productID = productID;
self.productDescription = productDescription;
}
return self;
}
#end
Ok, please try this in ProductViewController:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSLog(#"Row clicked: %i", indexPath.row);
Product *product = (Product *) [_products objectAtIndex:indexPath.row];
NSLog(#"Product: %#", product);
TabAndSplitAppAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSLog(#"appDelegate: %#", appDelegate);
UITabBarController *tbc = appDelegate.tabBarController;
NSLog(#"tbc: %#", tbc);
MySplitViewController *msvc = tbc.selectedViewController;
NSLog(#"msvc: %#", msvc);
UINavigationController *rnc = msvc.rightController;
NSLog(#"rnc: %#", rnc);
DetailedVC *dvc = rnc.topViewController;
NSLog(#"dvc: %#", dvc);
dvc.detailDescriptionLabel.text = #"We found our DetailedVC";
[dvc productSelectionChanged:product];
}
This code is not an example of how you should structure your program properly. This was just to help me (and you) understand your view controller hierarchy.
The initial idea of notifying a delegate when a product is selected is spot on, it just didn't work in your case because the objects weren't wired up properly. You should try to do that though. In the code you posted, I don't see a location where both the ProductViewControllerand the DetailedVC are both directly visible so that you could just say
productViewControllerInstance.delegate = detailedVCinstance;
The nearest to that is in AppDelegate where you have the RootVC instance rvcthat presumably eventually will create the ProductViewController and the dvc. Maybe you could give the dvcto the rvcso that it can set it as the ProductViewController's delegate when it's created. Good luck!