I wanted to have a tab bar controller, then a table view controller with a corresponding detail view. I am new to this, so I tried combining Apple's SimpleDrillDown:
http://developer.apple.com/library/ios/#samplecode/SimpleDrillDown/Introduction/Intro.html
...with Ray Wenderlich's tutorial on Storyboards:
http://www.raywenderlich.com/5138/beginning-storyboards-in-ios-5-part-1
Ray's shows you how to set up the tabs and get the first table view, but then doesn't show you how to get a detail view, so then I tried to learn how to get the detail view from Apple's SimpleDrillDown (which doesn't have the tab bar controller).
My program runs with no errors, but when you click on a row in the table view (FactSheetsViewController), it stays blue (selected) and never segues to my FactSheetsDetailViewController. If I put a breakpoint in my table view class at this method:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"DisplaySelectedFactSheet"]) {
NSIndexPath *selectedRowIndex = [self.tableView indexPathForSelectedRow];
FactSheetsDetailViewController *detailViewController = [segue destinationViewController];
detailViewController.factSheet = [dataController objectInListAtIndex:selectedRowIndex.row];
}
}
The breakpoint is never reached when I run the program and click on a cell.
I'm not sure what other code to post, because I'm not sure what I did wrong. I'm wondering if I initialized things incorrectly in my AppDelegate?
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UITabBarController *tabBarController = (UITabBarController *)self.window.rootViewController;
UINavigationController *navigationController = [[tabBarController viewControllers] objectAtIndex:0];
FactSheetsViewController *factSheetsViewController = [[navigationController viewControllers] objectAtIndex:0];
DataController *controller = [[DataController alloc] init];
factSheetsViewController.dataController = controller;
self.dataController = controller;
return YES;
}
Or, if I'm not setting things up correctly in the storyboard somehow. I set the identifier to my segue from FactSheetsViewController to my FactSheetsDetailView to "DisplaySelectedFactSheet" in the attributes inspector.
I'm happy to post more details if it would help - please just let me know! Thank you.
In Xcode, you need to create a segue between the table cell (prototype) and the FactSheetsDetailViewController. Then, also in Xcode, edit the segue name to be DisplaySelectedFactSheet.
Related
Have two segue in my storyboard. One segue shows navigation bar and navigation item when pushed but second segue doesn't shows navigation bar when pushed
This my code for pushing second segue
- (IBAction)ReadAction:(id)sender {
[self performSegueWithIdentifier:#"MySegue" sender:sender];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"MySegue"]) {
// Get destination view
PDFViewController *pdfviewController = [segue destinationViewController];
}
}
In the storyboard navigationbar and navigation bar title is showing for both segue in storyboard and navigationcontroller is set as rootviewcontroller that is why it is showing in first segue but i wonder why it is not showing only for second segue when execute
Edit:
Solved little bit but still have problem
The view controller which i was trying to push
In that view controller had code like this
NSString *path = [[NSBundle mainBundle] pathForResource:#"Paper" ofType:#"pdf"];
PageViewController *page = [[PageViewController alloc] initWithPDFAtPath:path];
//[self presentViewController:page animated:NO completion:NULL];
When i commented out this statement from above code then it shows navigation bar and backbuttonitem that is what i was looking for
[self presentViewController:page animated:NO completion:NULL];
but now after commenting it doesn't displays pageviewcontroller in the pushed view controller.
Now how can i display pageviewcontroller.
Edit:
Just added
[self.view addSubview:page.view];
but now another problem pageviewcontroller is displaying with navigation bar and all that but now not turning pages over using curl effect with previous commented statement it was turning pages over
Help will be really appreciated.
Thanks.
I think the below should work for your needs. One pushes and one presents simply.
PDFViewController *pdfviewController = [segue destinationViewController];
[self.navigationController presentViewController:pdfviewController animated:YES];
or
[self.navigationController pushViewController:pdfviewController animated:YES];
Try both.
i am facing a situation that i am loading data correctly to a uitableviewcontroller. also i am loading data correctly to the detail view controller.
what i am using:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"ShowPaymentDetails"])
{
DetailPaymentViewController *detailViewController = [segue destinationViewController];
NSIndexPath *myIndexPath = [self.paymentsTableView indexPathForSelectedRow];
detailViewController.payment = [arrayOfPayment objectAtIndex:[myIndexPath row]];
}
}
the problem i have is that when i am going back (through normal drag and drop swipe) the uitableviewcontroller is reloaded. since this takes data from a web service ... i don't want to reload the data.
Can you help me on any ideas on this.
Thnx in advance.
I'm guessing your segueing to the TableViewController from the DetailViewController. I think your creating a new TableViewController and not going back to the original one. You can check this in the debugger by setting a breakpoint in viewWillApear and looking at the value of self.
(lldb) po self
$0 = 0x1ddd2480
You should do this in your DetailViewController to go back to the TableViewController.
[self.navigationController popViewControllerAnimated:YES];
I'm trying to load a specific UITableViewController as the Detail view of a UISplitViewController when the user selects a cell within the Master view; but having some problems. When i select the cell, it just shows a blank window with out a table view controller.
However if i change the App Delegate to just load the UITableView controller without using the UISplitViewController it works fine, so i know it's a problem with the way i've coded the UISplitViewController.
The view hierachy:
UISplitViewController
-->
UINavigationController
--> UITableViewController (DetailViewController)
UINavigationController
--> UIViewController (ColorViewController)
The user selects a cell in ColorViewController and that should change the DetailViewController.
In AppDelegate.m:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.viewController = [[ViewController alloc] init];
self.window.rootViewController = [self.viewController splitViewController];
[self.window makeKeyAndVisible];
return YES;
}
In ViewController.m:
- (UIViewController *) splitViewController {
// Create the navigation-run root view
ColorViewController *rootVC = [ColorViewController controller];
UINavigationController *rootNav = [[UINavigationController alloc] initWithRootViewController:rootVC];
// Create the navigation-run detail view
DetailViewController *detailVC = [DetailViewController controller];
UINavigationController *detailNav = [[UINavigationController alloc] initWithRootViewController:detailVC];
// Add both to the split view controller
svc = [[UISplitViewController alloc] init];
svc.viewControllers = [NSArray arrayWithObjects: rootNav, detailNav, nil];
svc.delegate = detailVC;
return svc;
}
In ColorViewController.m:
#interface ColorViewController : UITableViewController
...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UIViewController *controller = (UIViewController *)self.splitViewController.delegate;
TableViewController *tvc = [[TableViewController alloc] init];
[controller.view addSubview:tvc.view];
}
What's the best way to change the Detail view within a UISplitViewController? Should i just add the replacement view to UIViewController like above or is there a better way? Maybe that's the cause of my problem?
Since you have a navigation controller handling the detail side of your split view, your strategy should be to use it to push your new table view controller. When I've done this, I've kept references to both navigation controllers as properties in the app delegate so that I can use one or the other for push operations.
I'm not sure what the real purpose of your ViewController class is but if you move its splitViewController method into the app delegate it would be easier to change the navigation controllers from local variables to properties in a place where they can be easily accessed.
I'm going to answer my own question..
For some reason, in the Master view (ColorViewController), the detail object TableViewController *tvc needs to be declared as an instance variable, not as a variable within a method.
After doing that, it works and displays the table properly.
I don't really understand why though, if anyone would like to try to explain.
Cheers,
New to iOS development, I've been following the tutorials on developer.apple.com, and am now adding functionality to those examples to further my knowledge.
The "second ios app" tutorial gives you a navigation controller based app. Extending this app, I want to have a tab bar controller as the first view controller.
So I now have the following setup:
All good. But there is code in the BirdsAppDelegate (a UIApplicationDelegate) which was relying on the navigation controller being the root view controller, so it can create and assign the "datacontroller" object.
This is the original code (before I added the tab bar controller):
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UINavigationController *navigationController = (UINavigationController *)self.window.rootViewController;
BirdsMasterViewController *firstViewController = (BirdsMasterViewController *)[[navigationController viewControllers] objectAtIndex:0];
BirdSightingDataController *aDataController = [[BirdSightingDataController alloc] init];
firstViewController.dataController = aDataController;
return YES;
}
Now this code fails because it assumes the root view controller is the navigation controller.
I have updated the code so that it works - but in my opinion it is ugly, and would have to be changed every time I make a change to the view controller hierarchy:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions
{
// Override point for customization after application launch.
UITabBarController *tabBarController = (UITabBarController *)self.window.rootViewController;
UINavigationController *navigationController = (UINavigationController *) [[tabBarController viewControllers] objectAtIndex:0];
BirdsMasterViewController *firstViewController = (BirdsMasterViewController*) [[navigationController viewControllers] objectAtIndex:0];
BirdSightingDataController *aDataController = [[BirdSightingDataController alloc] init];
firstViewController.dataController = aDataController;
return YES;
}
So my question is: What is the better way to do what I am doing in the code above, so that any changes to the hierarchy will not break the code?
How do I programmatically access the view controller I am after in the application delegate, so that I can create and assign it's BirdSightingDataController object?
Thanks!
You can loop the [navigationController viewControllers] array looking for an instance of BirdsMasterViewController... Using [obj isKindOfClass:[BirdsMasterViewController class]].
You don't even need that code at a all. If you just want to change the controller, go to the storyboard and select the viewController you want to change to a TabBarController. In the Editor menu, there is an option for "Embed In", the choices are TabBar and Navigation controllers.
I always start with a single view application template. There is no code in the "application didFinishLaunchingWithOptions:" method,(except to return YES). You can set any viewController as your initial view in the storyboard, by setting the is initial View Controller check box, or just dragging the arrow to the viewController you want as your initial view.
I am learning iOS and I have written a simple iPhone app using iOS 5. The app shows a UITableView populated with Speakers' names, when I select one of the names its supposed to go to a UIViewController and show details about that person (name, address, etc), so its really two ViewControllers a UITableViewController and UIViewController (both subclassed).
So, in MICSpeakersTableViewController : UITableViewController I have this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
MICSpeakerDetailViewController *detailViewController = [[MICSpeakerDetailViewController alloc] initWithNibName:#"Detail" bundle:nil];
[detailViewController setSpeaker:[[self getSpeakers] objectAtIndex:indexPath.row]];
[self.navigationController pushViewController:detailViewController animated:YES];
}
which gets called when I select it and populates the speaker (in that its not nil and description matches).
Then I have this in the same implementation:
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSIndexPath *indexPath = [ self.tableView indexPathForCell:sender];
if ([segue.identifier isEqualToString:#"Detail"])
[segue.destinationViewController setSpeaker:[[self getSpeakers] objectAtIndex:indexPath.row]];
}
Which also gets called and the segue.identifier is Detail and the destinationViewController's speaker is set correctly (is not nil, description matches). I am not quite sure why I have to set that again since I am setting it in didSelectRowAtIndexPath but I set it again and it seems harmless.
Finally, in the MICSpeakerDetailViewController, the initWithNibName method is called and the self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; returns an instance.
However, the segue never happens and viewDidLoad is never called.
Its probably something small but I can't figure it out... any advice?
Edit: Here is a screenshot of the storyboard showing the segue and the controllers:
You have to embed the view controllers in a navigation controller for push segues to work. I don't know why it lets you define them without this in place.
To do this, click on your table view controller, then choose Editor --> Embed In --> Navigation Controller. If you should also be within a tab bar controller, then the navigation controller is embedded in that in a similar fashion. You should see the following:
Your segue will now work.