I'm a very beginner to iOS development. I made a navigation application in iOS to view some details in another view when table view cell tap. I did the following code,
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
LawyerViewController *dvc = [self.storyboard instantiateViewControllerWithIdentifier:#"LawyerViewController"];
NSLog(#"%#",[self.myObject objectAtIndex:indexPath.row]);
dvc.lawyer = [self.myObject objectAtIndex:indexPath.row];
[self.navigationController pushViewController:dvc animated:YES];
}
This is going to the next view. But dvc.lawyer is not null here. It's null on Next View page.
Reading the Value in Next page
NSLog(#"%#",self.lawyer.firstName);
How can I fix this.
Thanks in Advance!
You are supposed to instantiate ViewControllers in another way, if you use storyboard segues. You need to implement prepareForSegue where you can Access the segues destinationViewController like this:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"YOUR_SEGUE_NAME_HERE"])
{
// reference to the destination view controller
LawyerViewController *vc = [segue destinationViewController];
// Pass any data
vc.lawyer = self.myObject[[self.tableView indexPathForSelectedRow].row]; // Not tested
}
}
Related
I'm trying to make a simple iOS app by following this (https://www.appcoda.com/use-storyboards-to-build-navigation-controller-and-table-view/) tutorial but when I try to click on the listed items, I don't get redirected to the detail view and just stay on the same page. I'm fairly new to using both Xcode (I'm using Xcode 7) and objective-C so I have no idea what I'm doing. Any kind of help will be very appreciable.
In your case the storyboard ID is RecipeBookViewController
You have to set Storyboard ID for that View controller as explained below.
GO In Xcode utilities pan click on Identity Inspector and set
Storyboard ID = RecipeBookViewController
For more clarification see the Image, and add RecipeBookViewController against Storyboard ID
Follow this code:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[self performSegueWithIdentifier:#"Your Segue Name" sender:self];
}
pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
if ([segue.identifier isEqualToString:#"Your Segue Name"]) {
DetailViewController *vc= (DetailViewController *)segue.destinationViewController;
NSIndexPath *indexPath = [tableview indexPathForSelectedRow];
vc.(DetailViewController Object)= [(Your tableView Array name) objectAtIndex:indexPath.row];
}
}
In appCoda, they used segue to push so you might be not added this code in your project,
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"segue_Key"]) {
DetailViewController *nextVC = [segue destinationViewController];
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self performSegueWithIdentifier:#"segue_Key" sender:self];
}
If you facing issue in segue then remove the segue connection from storyboard and use below code ,
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
DetailViewController *obj = (DetailViewController *) [self.storyboard instantiateViewControllerWithIdentifier:#"DetailViewController"]; // Identifier must match with the storyboard VC ID, else project git crashed.
[self.navigationController pushViewController:obj animated:YES];
}
If you already done this, then let me know.
If you don't want to use a segue you should create your destination controller by code:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
destinationcontroller *loading = (destinationcontroller *)[self.storyboard instantiateViewControllerWithIdentifier:#"destinationcontroller"];
[self.navigationController pushViewController:loading animated:YES];
}
Up until now I have used prepareForSegue method to notify a view controller he is about to review a segue from a different view controller, but if i'm the vc that sending the segue, will my prepareForSegue (in he same class of the segue sender) will check if there is a code to preform before he fires the segue?
I'm asking because I got a solution here to preform a simple segue just to go from stable view row which represent notes to the creation page of the note for editing...very simple, but from some reason it's not presenting my note in the creation page, only takes me to a new clean creation page..
So I though maybe it's because the prepareForSegue method..here you can see the question to give you more details How to to create a segue to push back to editing mode from a table view?
Would really appreciate to get your help on this.
This are the 2 methods I added to my NotesList table view controller:
#pragma mark - delegate
- (void) tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self performSegueWithIdentifier:#"noteSegue" sender:nil];
}
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"noteSegue"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
NMNote *note = [self.notes objectAtIndex:indexPath.row];
NMCreateNotesViewController *destination = [segue destinationViewController];
destination.textField.text = note.content;
}
}
And I made sure the segue identifier in the storyboard is named noteSegue. So why its note working...Im getting a new TextView instead of populating it with the note content :/
This is the error i'm getting:
Thanks!
The prepareForSegue: method is called on the current VC not the destination. UIViewController Class Reference. You can use the method to obtain a reference to the destination VC and set variables/call methods on it before the segue is performed.
Calling the segue like this:
[self performSegueWithIdentifier:#"NAMEOFSEGUE" sender:nil];
You can then prepare the destination VC like this:
#import "NMCreateNotesViewController.h"
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"NAMEOFSEGUE"]) {
NMCreateNotesViewController *destination = [segue destinationViewController];
[destination createNote]; /* or something similar */
}
}
EDIT:
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NMNote *note = [self.notes objectAtIndex:indexPath.row];
[self performSegueWithIdentifier:#"noteSegue" sender:note];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"NAMEOFSEGUE"]) {
NMCreateNotesViewController *destination = [segue destinationViewController];
NMnote *note = (NMNote*) sender;
destination.textField.text = note.content;
}
}
To check if there is a code to preform before the segue you can use solution below:
if ([segue.destinationViewController isKindOfClass:[UIViewController class]]) {
UIViewController *nextVC = segue.destinationViewController;
if(nextVC respondsToSelector:#selector(yourMethod)){
[nextVC yourMethod];
}
}
You can check if you are sure to perform the specific segue by implementing this method
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender
If you have your note presenting code in viewDidLoad, try moving that to viewDidAppear (in your note editing VC). There used to be an issue when presenting from a TableView row where the segue would fire after VDL was executed.
I have two table view controllers, one containing all the US states, the other presenting a list of data for the selected state. I have set up a segue in my main storyboard from the view controller (not the cell), and given it an identifier. For reasons beyond the scope of this post, I need to programmatically perform the segue without using the prepareForSegue method.
The source table view controller (AllStatesTableViewController) needs to execute the segue in the didSelectRowAtIndexPath method of the tableview.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
stateID = [statesDict objectForKey:cell.textLabel.text];
DetailTableViewController *destination = [[DetailTableViewController alloc] init];
stateGauges = [[GaugeList alloc] initWithStateIdentifier:stateID andType:nil];
// at this point stateGauges is NOT nil
[destination setStateGauges:stateGauges];
[self performSegueWithIdentifier:#"sgShowStateDetail" sender:self];
}
The segue performs as intended in that it navigates to its destination, but stateGauges is nil in the destination table view controller. It is not nil in the source table view controller. stateGuages is declared as a property in DetailTableViewController. Obviously I am doing something wrong. Any suggestions?
Thanks! V
On your storyboard you need to choose to push your segue from your cell.
and use your prepareForSegue to pass data :
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"showDetail"])
{
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
DetailTableViewController *detailTableViewController = segue.destinationViewController;
// Pass data here
destViewController.stateGauges = stateGauges;
}
}
Have a look here for more information
I ran into this before too. I found that when I let the storyboard handle the segue, it instantiates a new view controller. This is why stateGauges is nil, because you set stateGauges in your programmatically created view controller, not the one the storyboard created. If you won't use prepareForSeque, remove the segue from your AllStatesViewController to your DetailTableViewController in your storyboard. Then programmatically instantiate the storyboard, the view controller, setGauges, then present your view controller. Also, make sure you put "ShowStateDetail" in the "Storyboard ID" field, in the Identity section, on that DetailTableViewController in your storyboard.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
stateID = [statesDict objectForKey:cell.textLabel.text];
DetailTableViewController *destination = [[UIStoryboard storyboardWithName:#"yourStoryBoardName" bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:#"ShowStateDetail"];
stateGauges = [[GaugeList alloc] initWithStateIdentifier:stateID andType:nil];
[destination setStateGauges:stateGauges];
[self presentViewController:destination animated:YES completion:nil];
}
Im working with table view controllers within story board.
I currently have one tableview controller embedded in navigation controller in my storyboard. This table view controller is linked to an ObjectiveC file.
Through code i can display another table view controller with the correct data using the tableView didSelectRowAtIndexPath method.
code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
WorkoutType *workoutType = (WorkoutType *)[self.fetchedResultsController objectAtIndexPath:indexPath];
WorkoutSetViewController *detailViewController = [[WorkoutSetViewController alloc] initWithWorkoutType:workoutType];
[self.navigationController pushViewController:detailViewController animated:YES];
}
But if i try to add another table view controller in storyboard, associate it with an objectiveC view controller file and connect the first TVC to it, That table view controller is not shown upon running the code.
I need to customise the second table view visually and have tried to use a segue push...as follows:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"show"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
WorkoutType *workoutType = (WorkoutType *)[self.fetchedResultsController objectAtIndexPath:indexPath];
//WorkoutSetViewController *detailViewController = [[WorkoutSetViewController alloc] initWithWorkoutType:workoutType];
WorkoutSetViewController *destViewController = segue.destinationViewController;
destViewController.workoutType = workoutType;
//[self.navigationController pushViewController:detailViewController animated:YES];
}
}
But when i run this code, the second table view controller doesn't even load although the application doesn't crash.
Whatever I am doing wrong must be simple, any help would be appreciated.
Thank You
Simple You have to navigate through below code. (No need to set storyboard when you working in same storyboard ViewController)
(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexpath.row==0)//for first row click
{
WorkoutSetViewController *objWorkoutSetVC=[[WorkoutSetViewController alloc] i nitWithNibName:#"WorkoutSetViewController" bundle:nil];
[self.navigationController pushViewController:objWorkoutSetVC animated:YES];
}
else if(indexpath.row==1)//for second row click
{
//Put code in which screen you have to navigate
}
}
Do NOT Alloc init your new view controller. Use this code instead:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
WorkoutSetViewController *detailViewController = (WorkoutSetViewController *)[storyboard instantiateViewControllerWithIdentifier:#"coolID"];
[self.navigationController pushViewController:detailViewController animated:YES];
For MainStoryboard write your storyboard name and for coolID write your view controller id name which you set in your storyboard.
I am trying to use Table Views and navigation controllers. This is the code I would use if I was using NIB files. This piece of code would work fine if I was using NIB files, but I decided to try storyboard -
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (_webViewController == nil) {
self.webViewController = [[[WebViewController alloc] initWithNibName:#"WebViewController" bundle:[NSBundle mainBundle]] autorelease];
}
RSSEntry *entry = [_allEntries objectAtIndex:indexPath.row];
_webViewController.entry = entry;
[self.navigationController pushViewController:_webViewController animated:YES];
}
I have created another scene in storyboard and have everything set up out there. When a user clicks a cell in this Table View they will be taken to that scene. This is what I wrote for the code but it is not right and I'm hopelessly stuck :( -
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"articleView"]){
UINavigationController *navigationController = segue.destinationViewController;
WebViewController *controller = (WebViewController *)navigationController.topViewController;
controller.webView = self;
}
Answer - Answers 2 and 3 are both right
I had a very similar problem 2 days ago, with the user selecting the disclosure accessory on a row and wanting to invoke a segue. What worked for me:
In storyboard, create segue "articleView" from the entire tableView controller (not the cell) to the next viewController.
Add the following method to your tableViewController:
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath {
[self performSegueWithIdentifier:#"articleView" sender:[self.tableView cellForRowAtIndexPath:indexPath]];
}
Just for you I also tested with tableView:didSelectRowAtIndexPath: and it works.
Enjoy,
Damien
If your table view is already embedded in a navigation controller (looks that way, from your first code snippet) then the destination view controller of your segue will be a WebViewController, not a navigation controller.
You can therefore have your prepareForSegue method pass the item directly across :
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"articleView"])
{
WebViewController *controller = (WebViewController *)segue.destinationViewController;
RSSEntry *entry = [_allEntries objectAtIndex:[self.tableView indexPathForSelectedRow].row];
controller.entry = entry;
}
}
You may find this excellent two-part tutorial helpful
http://www.raywenderlich.com/5138/beginning-storyboards-in-ios-5-part-1