I'm fairly new to Objective-C and iOS app development so I apologize if the answer to my question is simple. I'm trying to send a pointer of a GTGift object from one view controller to another. When I enter the following code, the object is send and stored in an instance variable of the second view controller:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
GTGift *selectedGift = [[[GTGiftStore sharedStore] allGifts] objectAtIndex:[indexPath row]];
GTDetailViewController *dvc = [[self storyboard] instantiateViewControllerWithIdentifier:#"detailVC"];
[dvc setDetailGift:selectedGift];
[[self navigationController] pushViewController:dvc animated:YES];
}
However, when I enter this code in the first view controller:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
gift = [[[GTGiftStore sharedStore] allGifts] objectAtIndex:[indexPath row]];
GTDetailViewController *dvc = [[self storyboard] instantiateViewControllerWithIdentifier:#"detailVC"];
[[self navigationController] pushViewController:dvc animated:YES];
}
And this code in the second view controller:
- (void)viewWillAppear:(BOOL)animated {
GTGiftsViewController *gvc = [[self storyboard] instantiateViewControllerWithIdentifier:#"giftsVC"];
detailGift = [gvc gift];
NSLog(#"%#", detailGift);
}
detailGift returns null.
I can't for the life of me understand why, and it would be much more practical for my application if I could use an approach similar to the code segment that does not work.
If anyone can shine some light on this topic for me or point me in a different direction to complete the same task I would really appreciate it!
Your problem is that the word "instantiate" means what it says. :-)
In viewWillAppear you're creating a brand new GTGiftsViewController object which knows nothing about the gift that's been selected in the first GTGiftsViewController object.
(The "storyboard way" of doing this kind of thing is to create a prepareForSegue:sender: method in your first view controller and do the work there.)
Related
I am doing a small app and I am using a UISplitVIewController and I am trying to push the UITable cell text to the detail view and display it in a UITextField. I have managed to push the string nicely when i test it with a NSLog but when i apply to the UITextField it does not display not sure why here my method: (I am doing this using a storyboard)
-(void)pushModuleName:(NSString*)moduleName
{
self.Lv4ModuleTitleTextField.text = moduleName;
NSLog(#"name pushed%#",moduleName);
}
Not sure why this doesn't work.
[UPDATE]
UITableViewController.m (where the method is called)
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *selectedModule = [NSString stringWithFormat:#"%#",[_numberOfRows objectAtIndex:indexPath.row]];
Lv4GradeViewController *lv4 = [[Lv4GradeViewController alloc] initWithNibName:nil bundle:nil];
[lv4 pushModuleName:selectedModule];
}
You are creating a new instance of Lv4GradeViewController with the following code but no XIB file which will contain the text field:
Lv4GradeViewController *lv4 = [[Lv4GradeViewController alloc] initWithNibName:nil bundle:nil];
I would suggest you instantiate Lv4GradeViewController with the storyboard instantiateViewControllerWithIdentifier method:
Lv4GradeViewController *lv4 = [self.storyboard instantiateViewControllerWithIdentifier:#"IdentifierName"];
And remember to set the storyboard ID of the Lv4GradeViewController the same as IdentifierName in the storyboard.
The problem is that you're not getting a reference to the Lv4GradeViewController that you have on screen, you're creating a new one with alloc init. A split view controller, has a viewControllers array, with the controller at index 0 being the master controller, and the one at index 1 being the detail controller. So, the didSelectRowAtIndexPath method should look like this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *selectedModule = [NSString stringWithFormat:#"%#",[_numberOfRows objectAtIndex:indexPath.row]];
Lv4GradeViewController *lv4 = self.splitViewController.viewControllers[1];
[lv4 pushModuleName:selectedModule];
}
So I have an app that contains a tableView. When you press on a row, it should go to a new view controller and transfer the results. But it only sort-of works. If you press on a row, it will stay selected (Highlighted blue), but then if you select a different row, it will release the press on the first row and then move to the corresponding view. Sorry if this is a little confusing. Here is a short video of the error --> http://vid.ly/1e8u0h
It would seem as though the problem is that when I tap on a row, it never sends the "tap up" action, therefore doesn't continue with this method :
-(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
DetailViewController *detailViewController = [[DetailViewController alloc] init];
NSArray *items = [[BNRItemStore sharedStore] allItems];
BNRItem *selectedItem = [items objectAtIndex:[indexPath row]];
[detailViewController setItem:selectedItem];
[[self navigationController] pushViewController:detailViewController animated:YES];
}
How do I fix this? Thanks.
You're using didDeselectRowAtIndexPath instead of didSelectRowAtIndexPath :) Easy fix. Happy Coding.
You schould use tableview:didSelectRowAtIndexPath instead of tableView:didDeselectRowAtIndexPath.
I have two UITableViewControllers. In the first UITableView, once a user selects a cell, a new UITableViewController is pushed. I have set both UITableViews to "Grouped" in IB. However, when the second UITableViewController is pushed, it appears as a "Plain" UITableView. Is there a way to fix this?
Just as a sanity check, I changed the code so that the second UITableViewController is pushed not from the first UITableViewController, and it does appear to be "Grouped". Is there a reason this is happening?
Code From UITableViewController that is pushing second UITableViewController:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if ([cell.text isEqualToString:#"Long Term Disability"]) {
LongDisabilityTableView *ldvc = [LongDisabilityTableView alloc];
[self.navigationController pushViewController:ldvc animated:YES];
}
if ([cell.textLabel.text isEqualToString:#"Short Term Disability"]) {
ShortDisabilityTableView *sdvc = [ShortDisabilityTableView alloc];
[self.navigationController pushViewController:sdvc animated:YES];
}
}
If you are pushing to a UITableViewController, you can force the table to be grouped by doing one of the following:
Init
MyTableController *grouped = [[MyTableController alloc] initWithStyle:UITableViewStyleGrouped];
Super
This needs to be added to a UITableViewController.
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:UITableViewStyleGrouped]; /* This is where the magic happens */
if (self) {
self.title = #"My Grouped Table";
}
return self;
}
Double Check
Make sure that you are not placing your UITableView on a UIViewController.
Make sure that you are calling the correct controller in your code (from didSelectRowAtIndexPath:)
Update, added after code
Well there's one reason right there, you aren't using init. See my first example above.
You should also change your code to this:
/* This assumes that your Long Term Disability cell is at index 0
and that your Short Term Disability cell is at index 1.
*/
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
switch ( indexPath.row )
{
case 0: /* #"Long Term Disability" */
LongDisabilityTableView *ldvc = [[LongDisabilityTableView alloc] initWithStyle:UITableViewStyleGrouped];
[self.navigationController pushViewController:ldvc animated:YES];
break;
case 1: /* #"Short Term Disability" */
ShortDisabilityTableView *sdvc = [[ShortDisabilityTableView alloc] initWithStyle:UITableViewStyleGrouped];
[self.navigationController pushViewController:sdvc animated:YES];
break;
}
}
I'm following Apple sample code "MultipleDetailViews" but what I want to do is that:
at start, shows the RootViewController (table view) display the default detailViewController (1st detailView)
when user selected a table cell, push into the stack, display the SubCategoriesVC (table view) in the master of the splitView but don't update the detailView.
in SubCategoriesVC, selecting a table cell.. update the detailViewController (2nd detailView)
So, in RootViewController.m, I push another navigation
...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
SubCatVC *browseSubCatView = [[SubCatVC alloc] initWithNibName:#"SubCatVC" bundle:nil];
[self.navigationController pushViewController:browseSubCatView animated:YES];
[browseSubCatView release];
}
Then, in SubCatVC.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UIViewController <SubstitutableDetailViewController> *detailViewController = nil;
SecondDetailViewController *newDetailViewController = [[SecondDetailViewController alloc] initWithNibName:#"SecondDetailViewController" bundle:nil];
detailViewController = newDetailViewController;
// Update the split view controller's view controllers array.
NSArray *viewControllers = [[NSArray alloc] initWithObjects:self.navigationController, detailViewController, nil];
self.splitViewController.viewControllers = viewControllers;
[viewControllers release];
// Dismiss the popover if it's present.
if (self.popoverController != nil) {
[self.popoverController dismissPopoverAnimated:YES];
}
// Configure the new view controller's popover button (after the view has been displayed and its toolbar/navigation bar has been created).
if (self.rootPopoverButtonItem != nil) {
[detailViewController showRootPopoverButtonItem:self.rootPopoverButtonItem];
}
[detailViewController release];
[[NSNotificationCenter defaultCenter] postNotificationName:#"updateProduct" object:nil];
}
but it didn't update my detailView.. so I don't know what's wrong?
Src here: http://pastebin.com/iy6SqLqt
Hope someone can advise me. Thanks
I Have not looked at your source, but but a common problem with Split views are delegates.
When you Push a new rootController ont the nav stack, you need to make sure it has the pointer to the detailViewController that you want it to talk to. You can check htis my logging the delegate before you try to update it:
In your SubCatVC (or any root for that matter):
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
//do stuff, init alloc vc's....
NSLog(#"DELEGATE: %#",self.delegate);
//push/delegate etc..
}
If you find its nil, copy the original roots delegate, or when your putting your new detail in, notify/set the root you want to comunicate with it.
If you need any more detail, just ask.
Can anyone tell me if this is possible?
I have a setup a UITableViewController which consists of a number of cells, if you select one of these cells you are taken to a new viewController using pushViewController (see below)
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger row = [indexPath row];
NSLog(#"CELL__: You tapped the row ... %#", [list objectAtIndex:row]);
TestController *testController = [[TestController alloc] init];
[[self navigationController] pushViewController:testController animated:YES];
[testController release];
}
If in the implementation for "TestController" I would like to refer back to [self navigationController] (or maybe to add yet another view) is there any way to do that. My problem is that I need to access [self navigationController] to push further views and I don't know how to do that from the bottom controller?
Does that make sense?
Gary
From within TestController you reference the same UINavigationController via [self navigationController] as well.
EDIT to elaborate after comment:
The navigationController property is a property of UIViewController. If the controller is contained within a UINavigationController then it's own navigationController property will be a reference to that container UINavigationController. The same applies for tabBarController and splitViewController.