segue from UITableViewController doesn't work as push, only as modal - ios5

I have this view stack:
UIViewController --> (Modal segue) -->
UITabBarController --> (relationship) -->
UINavigationController --> (relationship) -->
UITableViewController --> (segue) --> UIViewController
Here is my segue code in the UITableViewController:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"selected row...");
[self performSegueWithIdentifier:#"showVmail" sender:self];
NSLog(#"done segue");
}
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"showVmail"]) {
NSLog(#"Got segue request...");
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
[segue.destinationViewController setMyVmail: [self.vmails objectAtIndex:indexPath.row]];
}
}
When I click on an item in the table view controller, I see these log messages:
selected row...
Got segue request...
Setting myVmail... // from the new view controller
done segue
And it doesn't move onto my new view controller.
If I change to a Modal, segue it works, but of course there is no Back button.
As far as I can see, Ive done everything correctly. Ive read many a response on stack overflow, with the same issue, and their resolution is to put in the UINavigationController. Ive already done this.
Any thoughts would be muchly appreciated!

I tried the suggestion seen else where that you should go back to simple cases. I changed the UINavigationController in the storyboard to point to a basic UIViewController and then for that to have a button that segued to another UIViewController. When I ran it, I still got my UITableViewController!
That is when I remembered that I was programatically filling in the objects in the UITabBarController, and that I wasn't invoking the UINavigationController, but skipping that and invoking the UITableViewController! So in fact, I really was having the same issue as everyone else, missing the UINavigationController !
Change my program in to link the UINavigationController instead of the UITableViewController and all is now working as expected.

Related

navigating from detail view controller to table view controller

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];

Sending a Notification from a UIButton to a ViewController

I have a UITableViewCell created in an external Nib from my storyboard. I have set up a segue from the UITableViewController to another ViewController which works nicely when tested.
I was wondering how would I get the UIButton in the Nib to call
[performSegueWithIdentifier:#"identifier" sender:self]; when it's pressed.
Any ideas? I'm still very amateurish so if you could explain quite clearly I'd really appreciate it.
Regards,
Mike
You can also accomplish the same thing on the storyboard; right click the button and drag the arrow to the viewcontroller you want to navigate to, it will give the segue options (push, modal, custom) and just select one.
In your ViewController.h do this:
- (IBAction)buttonPressed:(id)sender;
In your .m file do this:
- (IBAction)buttonPressed:(id)sender {
[self performSegueWithIdentifier:#"identifier" sender:self];
}
Now go to your .xib File and connect the Buttons selector to your controller.
To handle it in your calling VC
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"identifier"]) {
>yoursecondVC> *secondViewController = [segue destinationViewController];
secondViewController.<param> = <param>;
}
}

UITableView didSelectRowAtIndexPath with prepareForSegue but didLoadView is not called

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.

launching a UIViewcontroller from a UITableViewController crashes app

I have a UItableViewController. Inside this class there is the following method where I am trying to launch another UIViewController. I tried to connect the two using a segue and gave it a identifier, then used this version:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"About to launch MyDetail View controller");
[self performSegueWithIdentifier:#"myDetailSegue" sender:self];
}
That didnt work, the app froze and I got a message in the main.m file as follows: " "Thread 1 received signal Sigabrt"
So then deleted the segue and tried to instantiate the UIViewcontroller as follows,
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"About to launch my Detail View controller");
UIStoryboard *sboard = [UIStoryboard storyboardWithName:#"iPhone" bundle:nil];
UIViewController *myDetailVC = [sboard instantiateViewControllerWithIdentifier:#"myDetailVC"];
[self.navigationController pushViewController:myDetailVC animated:YES];
}
which worked. But now Im confused. Why would the UIStoryboard way work and the segue not???
Could someone please help, Im so confused.
I don't get understand what exactly problem you are facing but i want tell you that because of you are using uitableview first please connect its cell to new view controller and select 'Push' segue method. Once you have done this then add following code in your application instead to user didselectrowatindexpath methods.
(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
/*
When a row is selected, the segue creates the detail view controller as the destination.
Set the detail view controller's detail item to the item associated with the selected row.
*/
if ([[segue identifier] isEqualToString:#"Showcategorydetails"]) {
NSIndexPath *selectedRowIndex = [self.tableView indexPathForSelectedRow];
CategoryDetailsController *detailViewController = [segue destinationViewController];
detailViewController.category_title = [maincategories_array objectAtIndex:selectedRowIndex.row];
}
}

UITableView with multiple viewcontollers

I just filled my UITableView with Planets. I would like each cell clicked to open into a new Xib (if this sounds like the wrong approach please direct). I can get a secondviewcontroller working, its getting the thirdviewcontroller and fourthviewcontroller working? Thanks.
Place your main view controller (the one with the table) inside a UINavigationController. Then, when the user selects a row, push a new view controller onto it.
The following function will help. As Ben Gottlieb said your main view controller will need to be in a UINavigationController. You need to implement the delegate method for didSelectRowAtIndexPath and this is where you create the new controller for your new view and load it.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
YourViewController *controller = [[YourViewController alloc] initWithNibName:#"YourViewController"bundle:nil];
[[self navigationController] pushViewController:yourViewController animated:YES];
[yourViewController release]; // don't leak memory
}
Based on the row number you can decide which nib to load.