Hi I am new to iOS programming and My requirement is to send the table cell text to detail view and display that text in detail view.
Master view
I have connected those view controller with segue. My master view controller is adding data in table view using below function.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
CustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[CustomTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell...
cell.textLabel.text = [_types objectAtIndex:indexPath.row];
return cell;
}
After that I am assigning the text of current selected table view cell to 1 variable using below function.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
_type = [_types objectAtIndex:indexPath.row];
}
And for passing the selected table view cell's data to detail view controller I used below function.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"CellSelection"])
{
CellSelectionViewController *controller = (CellSelectionViewController *)segue.destinationViewController;
controller.msg = _type;
}
}
Detail View
In detail view I am just alerting the passed data sent from master view.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Test" message:_msg delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
}
Now my problem is
When I click on any cell, it loads the detail view but sending null value.
When I go back and again click on a cell, it sends the value which I selected previously.
Anybody knows what is the problem here?
It looks like you're using didSelectRowAtIndexPath and a segue. You should use one or the other. So, you could either:
You could retire your didSelectRowAtIndexPath method and then have a prepareForSegue that:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"CellSelection"])
{
CellSelectionViewController *controller = (CellSelectionViewController *)segue.destinationViewController;
controller.msg = [_types objectAtIndex:[self.tableView indexPathForSelectedRow].row];
}
}
Alternatively, you could remove the segue from the table view cell to the next scene, but rather define it to be between the two view controllers, give it an identifier, and then have didSelectRowAtIndexPath invoke it after your property was set:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
_type = [_types objectAtIndex:indexPath.row];
[self performSegueWithIdentifier:#"yoursegueidhere" sender:#"self];
}
But don't have both a segue from the cell and a didSelectRowAtIndexPath method. You have no assurances as to the order they will be performed. I'd be inclined to adopt the first approach and retire didSelectRowAtIndexPath altogether.
Related
This question already has answers here:
How to get indexpath in prepareForSegue
(4 answers)
Closed 6 years ago.
I have a TableViewCell with CutomCells,that includes images view, when user selects some row, the image that is in this row should be shown in another viewController.
Connection among these Controllers is done through segue, where I tries to set the image.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"ImageVC"])
{
ImageViewController * ivc = segue.destinationViewController;
ivc.myTemporaryImage = [self.dataDictionary objectForKey:self.names[self.selectedCell]];
}
}
to define which one row was selected I use TableViewDelegates method:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.selectedCell = indexPath.row;
[self.dataDictionary objectForKey:self.names[indexPath.row]];
}
The issue here that image is not reflected, cause firstly fires method: prepareForSegue, and only after that - didSelectRowAtIndexPath. But I need to change this order. Could you advice how to do this?
Also I tried to create ImageViewController programmatically, without using segue, directly in method didSelectRowAtIndexPath, but in this image is not shown in this case.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.dataDictionary objectForKey:self.names[indexPath.row]];
ImageViewController * ivc = [[ImageViewController alloc]init];
ivc.myTemporaryImage = [self.savedImages objectForKey:self.names[indexPath.row]];
[self.navigationController pushViewController:ivc animated:YES];
}
Could you please how to manage this issue?
You have to remove the direct reference to your segue in your cell, then, in your tableView delegate call it programmatically:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.selectedCell = indexPath.row;
[self performSegueWithIdentifier:#"ImageVC", sender: [self.savedImages objectForKey:self.names[indexPath.row]]]
}
Then in prepareForSegue:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"ImageVC"])
{
ImageViewController * ivc = segue.destinationViewController;
ivc.myTemporaryImage = sender;
}
}
I think you can save the indexPath at the willSelectRowAtIndexPath method.
I'm having an issue with my app.
I have 3 View controllers, let's name them Oil, App and Prop . Those 3 View Controllers are embed in Navigation controllers. And in those View Controllers I got 3 table view.
So from Up to Bottom and Left to Right :
Prop View Controller -> Prop Detail View Controller
Oil View Controller -> Oil Detail View Controller-> Web View Controller
App View Controller-> App Detail View Controller
So in the middle (Oil) Everything works fine, I click on a cell, and the Oil Detail View Controller is displayed, with the information I passed through my Segue.
OilViewController.m :
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *sectionTitle = [aromaSectionTitles objectAtIndex:indexPath.section];
NSArray *sectionAroma = [tableData objectForKey:sectionTitle];
aromaNom = [sectionAroma objectAtIndex:indexPath.row];
[self performSegueWithIdentifier:#"Detail" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"Detail"]) {
OilDetailViewController *test = segue.destinationViewController;
test.aromaName = aromaNom;
test.botaniqueName.text = botaniqueName;
}
}
And I'm also performing Segue between Oil Detail View Controller and Web View Controller like this :
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"webView"]) {
NSLog(#"Segue is catched");
WebViewViewController *webView = segue.destinationViewController;
webView.aromaUrl = _aromaName;
}
}
I click on the orange button and it displays the webview.
But now if I do the SAME thing in Prop or App it doesn't work properly.
For example in Prop Detail VC I got a Label that displays the Property selected, but it displays me the View Controller with the label containing the old selected property before displaying me the right property selected in the label. So I have 2 Prop Detail View displayed AND embed in my Navigation Controller.
I made a video of the simulator : http://videobam.com/VwgLx
The code in PropViewController.m :
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *sectionTitle = [aromaPropSectionTitles objectAtIndex:indexPath.section];
NSArray *sectionProp = [propData objectForKey:sectionTitle];
propName = [sectionProp objectAtIndex:indexPath.row];
NSLog(#"prop name = %#", propName);
[self performSegueWithIdentifier:#"PropDetail" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"PropDetail"]) {
PropDetailViewController *propView = segue.destinationViewController;
propView.propStr = propName;
NSLog(#"PREPARE FOR SEGUE PROP VIEW CONTROLLER");
}
}
And in PropDetailViewController.m :
- (void)viewDidLoad {
[super viewDidLoad];
self.propLabel.text = _propStr;
NSLog(#"VIEW DID LOAD PROP DETAIL");
// Do any additional setup after loading the view.
}
Finally the logs :
Thanks in advance for your help, I'm stuck with this, and nobody in my team knows iOs .. So i'm alone with this !
So I finally managed to find a proper solution .. I still don't know why it works on Oil and causes problems on other views but still; here is the solution :
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *sectionTitle = [aromaPropSectionTitles objectAtIndex:indexPath.section];
NSArray *sectionProp = [propData objectForKey:sectionTitle];
propName = [sectionProp objectAtIndex:indexPath.row];
NSLog(#"prop name = %#", propName);
[self performSegueWithIdentifier:#"PropDetail" sender:self];
}
Delete the method above. And do everything you do in this method in the prepareForSegue method instead :
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"PropDetail"]) {
PropDetailViewController *propView = segue.destinationViewController;
NSIndexPath *indexPath = [self.propTableView indexPathForSelectedRow];
NSString *sectionTitle = [aromaPropSectionTitles objectAtIndex:indexPath.section];
NSArray *sectionApp = [propData objectForKey:sectionTitle];
NSString *name = [sectionApp objectAtIndex:indexPath.row];
propView.propStr = name;
}
}
Now it works fine ! But it's not logic that it works in a place, and doesn't in an other ..
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];
}
I have a table view controller that displays all fetchresults for an entity. when a row is selected, I want that row to pass its information to a detail view controller. problem is I get stuck on how to only show the entity selected and not all of them before I segue.I thought with just what I had in didSelectAtIndexPath it should be changing the textfield's text in the next view controller, but it doesnt. Am I missing something? here is what I have so far.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
Athlete *athlete = (Athlete *)[athleteArray objectAtIndex:indexPath.row];
AthleteDetail *athleteDetail= [self.storyboard instantiateViewControllerWithIdentifier:#"showAthlete"];
athleteDetail.firstDetailTextField.text = athlete.first;
[self.navigationController pushViewController:athleteDetail animated:YES];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:#"showAthlete"]){
//prepare
}
}
UITableView has - (NSIndexPath *)indexPathForSelectedRow method. Use it to get index of selected row.
You'll have sth like:
NSIndexPath *index = [self.yourTableView indexPathForSelectedRow];
NSUInteger currentRow = [index row];
YourDataObject * d = // take out data from your model using currentRow
YourDetailViewController *vc = [segue destinationViewController];
// pass your data to detailViewController
[vc setData:d];
I have two Table View Controller in a Navigation Controller. The Cloth table is the main view and when I click on one of the cells go to another view controller that gives me the detail, when I select the option i want and return to the Return of the Navigation button, I lose the information. How do I take the value to the main view?
Here my code: Main View - AddClothViewController
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([[list objectAtIndex:indexPath.row] isEqual:#"Categorias"] )
{
CategoriesViewController *DVC = [[CategoriesViewController alloc] initWithNibName:#"CategoriesViewController" bundle:nil];
[self.navigationController pushViewController:DVC animated:YES];
}
}
Here my code: Categories ViewController
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Set the checkmark accessory for the selected row.
[[tableView cellForRowAtIndexPath:indexPath] setAccessoryType:UITableViewCellAccessoryCheckmark];
// This is my main View Controller when i declare a variable category and I try to access from
//here
AddClothViewController *DVC = [[AddClothViewController alloc] initWithNibName:#"AddClothViewController" bundle:nil];
DVC.clothNew.categoria = [list objectAtIndex:indexPath.row ];
}
I resolved my problem by using this tutorial.
(Simple delegate tutorial for ios development)