Looks like no one’s replied in a while. To start the conversation again, simply ask a new question.

Passing data from Detail to Master

Hey there,

I have a TableViewController that has 3 cells, including a subtitle, with disclosure indicators.

When one is tapped, another TableViewController opens with cells showing values from an array, and with check marks.


Is there anyway to pass the value of the cell that the checkmark was chosen to the previous(Root)TableViewController's subtitle, so when the user taps back, they will see the value they checked on the first TableViewController cell's subtitle?


OR is there an better way to do it than pass it to a subtitle from a previous screen?


The reason I want to do this is I want all 3 cells' subtitles in the Root TableViewController to be filled with the users choice, then I have a button on the Root TableViewController that when tapped, searches a database using the choices in the subtitles.


Thanks in advance!

Posted on Jul 6, 2012 1:57 PM

Reply
Question marked as Best reply

Posted on Jul 7, 2012 12:49 PM

The best way to pass data between view controllers is to make your model accessible to both.


Do not use UI controls to store attributes. UI control values should just reflect the model.


Example of one way to do this.


Assume your model is a class. This sample has one property.

@interface Options : NSObject


@property (copy, nonatomic) NSString *color;


@end


Make the model available to parent and child view controllers. Either a property on the AppDelegate or properties on each view controller.

@property (strong, nonatomic) Options *options;

If the property is on view controllers, set it when pushing child view controllers.

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender

{

if ([[segue identifier] isEqualToString:@"ShowColorSelector"]) {

[[segue destinationViewController] setOptions:options];

}

}


The child view controller can then directly set model properties.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

{

options.color = [availableColorsobjectAtIndex:indexPath.row];

}


The parent view controller can update UI controls from the model when it is shown. This example uses static table view content, not cell prototypes; colorCellLabel is a an IBOutlet for the subtitle on one of the cells.

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated

{

if (viewController == self) {

colorCellLabel.text = options.color ? options.color : @"not set";

}

}

7 replies
Question marked as Best reply

Jul 7, 2012 12:49 PM in response to gmazza

The best way to pass data between view controllers is to make your model accessible to both.


Do not use UI controls to store attributes. UI control values should just reflect the model.


Example of one way to do this.


Assume your model is a class. This sample has one property.

@interface Options : NSObject


@property (copy, nonatomic) NSString *color;


@end


Make the model available to parent and child view controllers. Either a property on the AppDelegate or properties on each view controller.

@property (strong, nonatomic) Options *options;

If the property is on view controllers, set it when pushing child view controllers.

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender

{

if ([[segue identifier] isEqualToString:@"ShowColorSelector"]) {

[[segue destinationViewController] setOptions:options];

}

}


The child view controller can then directly set model properties.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

{

options.color = [availableColorsobjectAtIndex:indexPath.row];

}


The parent view controller can update UI controls from the model when it is shown. This example uses static table view content, not cell prototypes; colorCellLabel is a an IBOutlet for the subtitle on one of the cells.

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated

{

if (viewController == self) {

colorCellLabel.text = options.color ? options.color : @"not set";

}

}

Jul 10, 2012 9:07 AM in response to Llessur999

Thanks so much for your reply.

As I am new to xcode, can I go through what you wrote and see if I am understanding it correctly?

1. So create a class, Options, with a string, color.

2. Add the class to the parent AND child view controllers .m files and in the .h files of each, set the property for it, as you had:

@property (strong, nonatomic) Options *options;

3. Set the propery in the prepare for segue function in the parent VC .m file. (What is the setOptions:options?)

4. With the child vc setting the model properties section you have above, that will grab the value of the check box and store it in the color string? Is availableColors my array on the child vc or am I way off?

5. Make an IBOutlet for the subtitle of the first cell, for example, called colorCellLabel, and then create the final (void) function in my parent .m file??

Finally, I don't understand the syntax you have for:

colorCellLabel.text = options.color ? options.color : @"not set";

Will this then set the subtitle to the check box from the child VC?

I don't understand that line of code, with the ?, as well as the "not set". How come we are setting the label to "not set", or am I wrong and is it just saying to set it to the check box and if a checkbox hasn't been chosen the the subtitle label will say "not set"??


Thanks for all your help!

Jul 11, 2012 8:46 AM in response to gmazza

I will attempt to answer the questions. You might think the terminology is splitting hairs but it is important to understand how everything fits together.


> 1. So create a class, Options, with a string, color.

Yes. That class defines your model, so it should have whatever properties are necessary. In your case the class should probably fully describe the query parameters.


> 2. Add the class to the parent AND child view controllers .m files and in the .h files of each,

You are not adding the the class to the view controllers, you are adding a property that references an instance of the class. The class is defined in Options.h/m. There should only be one instance of the class. You are adding this property so that class instance is easily accessible from within the view controllers.


> 3... (What is the setOptions:options?)

This sets the options property on the destination view controller to the same options as the parent. The child view controller did not exist until the segue started; prepareForSegue is your opportunity to set properties on the destination view controller that are not immediately accessible inside the view controller.


setOptions is the synthesized accessor for the options property. I used setOptions:options rather than than .options = options because the latter would require casting destinationViewController. There is no functional difference.


> With the child vc setting the model properties section you have above, that will grab the value of the check box and store it in the color string?

Yes. There is only one instance of the Options class.


> Is availableColors my array on the child vc or am I way off?

Yes. For this test, that is just an array of color names corresponding with table row indexes so I didn't have to put a switch or a bunch of else if's and explicitly set it for each table row index. Your solution needs some similar way to map the checked table row to the associated option.


> and then create the final (void) function in my parent .m file??

That is a UINavigationControllerDelegate method. You need to make sure the UINavigationController delegate is set to the view controller, and the view controller class is marked with that protocol. If you don't know how delegates/protocols work, read the Objective-C Programming Guide or review a few of the sample apps. You can't get much done in iOS apps without using delegates.


> I don't understand the syntax you have for: colorCellLabel.text = options.color ? options.color : @"not set";

Before option.color is set for the first time, it is nil. This immediate ifstatement shows "not set" in the table cell in that scenario. Same as a regular if/else statement but more concise.


The view controllers in this sample project storyboard have static cells, so there isn't much code other than that above. I don't think we can post attachments. To better understand how everything fits together, I can send you the entire project late tonight (EDT) if you post an email address.

Jul 11, 2012 1:11 PM in response to Llessur999

k I will read over what you said carefully and try and understand it better.

my email address is lakershoww@yahoo.com and I really do appreciate all your help.

The code, along with your reply, along with all my manuals, should help me understand what is happening cause I don't just want it to work, i want to understand the code and what its doing.

Thanks so much!

Passing data from Detail to Master

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple ID.