views:

71

answers:

2

I have an ItemAddViewController, which presents itself as a modal view. One of the fields pushes a new view controller, CategorySelectionViewController, which allows the user to select a single category.

ItemAddViewController.h

@property (nonatomic, retain) Category *category;

CategorySelectionViewController.h

@property (nonatomic, retain) Category *category;

CategorySelectionViewController.m

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSManagedObject *currentCategory = category;

if (currentCategory != nil) {
    NSInteger   index = [categories indexOfObject:currentCategory];
    NSIndexPath *selectionIndexPath = [NSIndexPath indexPathForRow:index inSection:0];
    UITableViewCell *checkedCell = [tableView cellForRowAtIndexPath:selectionIndexPath];
    checkedCell.accessoryType = UITableViewCellAccessoryNone;
}

//set the checkmark accessory
[[tableView cellForRowAtIndexPath:indexPath] setAccessoryType:UITableViewCellAccessoryCheckmark];

//update the category
category =[categories objectAtIndex:indexPath.row];
NSLog(@"%@", category);
// Deselect row
[tableView deselectRowAtIndexPath:indexPath animated:YES];

}

ItemAddViewController.m

- (void)viewWillAppear:(BOOL)animated {
  NSLog(@"%@", category);
}

Category is set on CategorySelectionViewController creation. When category is selected on the category selection screen, NSLog reports the correct object. When it gets back to ItemAddViewController, it's null again. The two should be the same object, so I'm not sure what I'm doing wrong.

Basically, I need a good method to pass data between two view controllers.

A: 

The parentViewController method of the UIViewController class should give you a pointer to the view controller that's "managing" the current one. Once you've got that, you can set the category property on it.

That said, I haven't done much with view controllers on iOS yet myself, so I'm not sure what the semantics of "what parentViewController should point to for a given view" is... but I'd venture that your ItemAddViewController instance should probably be the parent for your CategorySelectionViewController.

Here's an example of how you might do it:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    NSManagedObject *currentCategory = category;

    if (currentCategory != nil) {
        NSInteger   index = [categories indexOfObject:currentCategory];
        NSIndexPath *selectionIndexPath = [NSIndexPath indexPathForRow:index inSection:0];
        UITableViewCell *checkedCell = [tableView cellForRowAtIndexPath:selectionIndexPath];
        checkedCell.accessoryType = UITableViewCellAccessoryNone;
    }

    //set the checkmark accessory
    [[tableView cellForRowAtIndexPath:indexPath] setAccessoryType:UITableViewCellAccessoryCheckmark];

    //update the category
    [self parentViewController].category = [categories objectAtIndex:indexPath.row];
    NSLog(@"%@", category);
    // Deselect row
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
}

EDIT: The documentation says this for the parentViewController method:

Parent view controllers are relevant in navigation, tab bar, and modal view controller hierarchies. In each of these hierarchies, the parent is the object responsible for displaying the current view controller.

I'd take this to mean that the parentViewController for your modal view's controller points to whatever view controller received the message presentModalViewController:animated:.

David
Very good answer.
Michael
Interesting. However, it appears that the parent view controller is the navigation controller, not the ItemAddViewController (and the parent of the navigation controller is the tab bar controller)
DVG
A: 

@David's is a good answer, but that would keep the data in the parentViewController. If you want the data to be local to the ItemAddViewController (the child controller), then you can create a local iVar in the second view and assign a value to it before displaying it or pushing it onto the navigation controller. See my answer to a previous SO question here to see how it is done.

Neal L