Lizzeiy
Lizzeiy

Reputation: 426

Pass cell array item to another view controller

So this is a common question which I have been reading up on, I am still learning so please keep that in mind.

Basically my app currently lets you add an item to the tableview then when you select a cell from the table view it shows another view controller which is meant to display the detailed information for that cell.

Diagram

In my tableView implementation file .m, I have the code to go to the view controller when a cell is clicked:

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

    SelectedItemViewController *selectView = [[SelectedItemViewController alloc] initWithNibName:@"SelectedView" bundle:nil];

    [selectView.titleView setText:@"test"];

    [self performSegueWithIdentifier:@"showSelected" sender:indexPath];
}

The 'setText' piece of code was me just testing to see if I was able to change the textLabel in the ViewCellController.

When a user saves a new item, this is the following segue code that is called when it returns back to the TableView. 'toDoItem' is an NSMutableArray.

 -(IBAction)unwindToList:(UIStoryboardSegue *)segue {
    AddToDoItemViewController* source = [segue sourceViewController];
    ToDoItem* item = source.toDoItem;
    if (item != nil){
        [self.toDoItems addObject:item];
        [self.tableView reloadData];
    }
}

Obviously I am doing something wrong.

What I am trying to understand is how I can:

  1. Select a cell, take the data from that index in the array so not just the cell data, data includes: Title, Description, DueDate and completion.

  2. Display it in another view controller.

  3. Manipulate the completion boolean value and save it so it remains that way when clicked again.

I don't want a full answer just something to point me in the right direction so I can work it out on my own, Thanks!

Upvotes: 0

Views: 1994

Answers (2)

Gil Sand
Gil Sand

Reputation: 6040

From what I understand you're in a simple Tableview detail situation.

You have a list of items, and you want to keep a specific item in the next view, so you can display it's details (or edit, or interact somehow).

For example, i'm thinking of a contact list or a recipe list. You have a list of meals, you can see their title and rating, and say you wanna see the ingredients, you have to tap on it.

Correct me if I'm wrong here, otherwise, this is fairly simple.

You'll need a tableview (in a UITableViewController or a simple UIViewController where you add your own tableview). Either way, you tableview is apparently already done, so I can skip that part. This controller should be in a UINavigationController which should be your ONLY navigation controller. I'll be blunt and say that if you're a beginner (just as much as I am), you'll probably make apps that only have one navigation controller for a while.

You also have an array of custom objects, which you most certainly have. Say it's a Contact, you have an array of Contact objects.

When you build your tableview, you use that array of contacts and make your cells accordingly.

here is a very short example :

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{

    static NSString *identifier = @"ContactCell";

    //I'm assuming you're using a custom cell    
    ContactCell *cell     = [self.tableView dequeueReusableCellWithIdentifier:identifier];

    if (cell == nil) {
        cell = [[ContactCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
    }


    Contact *contact = [_dataArray objectAtIndex:indexPath.row];
    cell.nameLabel.text = contact.name;     
    cell.phoneNumberLabel.text = contact.phone;
    return cell;

}

This is just a short example to make my point ; note that you have to set up datasource and delegate, as well as other methods (-numberOfRowsInSection:) for a tableview to work properly.

Fine, you have a list of contacts and a small text with their phone number, but you would like to display their address or anything that you already have in your array but are not displaying yet. All that data is already loaded, you just really really wanna show it. A good use is indeed to tap the cell and push another view. Pushing is good because you can use the backbutton that the OS creates for you, and that's why you needed the UINavigationController

To handle that, you'll need two methods, first the tableview method didSelectRowAtIndexPath, and then prepareForSegue.

there are many ways to work around this, but I'll try and make something simple. You wanna know which item you tapped and you wanna give it to the next view. So, well, to give it to the next view you need to have it first. We will :

  • find it in the array
  • keep some kind of reference to it (it's index path or the whole item)
  • pass it

You can use an ivar to keep that reference, there are better/different ways but this is pretty simple. Others might wanna make their own answer with a different style or edit mine with another way, at the end of my answer.

The ivar is simply an instance variable at the top of your .m file that you can access anywhere in that .m file. It's kind of like a @property but that only that class/controller can see.

You can use this at the very top of your controller, the line should already be there just before viewDidLoad, just add the curly braces and your variable.

@implementation MyTableViewController
{
    Contact *_myContactToPass;
}

The following method will just find the item and call the "passing" method

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

    _myContactToPass = [_dataArray objectAtIndex:indexPath.row];
    [self performSegueWithIdentifier:@"fromTableViewToDetails" sender:self];
}

In DetailsViewController, you need a @property in your .h file that is a Contact object, and some labels and buttons and all the good jazz you need. Fill all those labels with the _contact property, and because you will always pass it before loading that view, they'll load that dynamic data from the selected contact and not static labels from storyboard.

- (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:@"fromTableViewToDetails"]){

        DetailsViewController *vc = (DetailsViewController*)segue.destinationViewController;
        vc.contact = _myContactToPass;  
}

Notes :

  • I'm assuming you have created a push segue in storyboard called fromTableViewToDetails
  • I'm assuming that you know how to do just that
  • I'm very disapointed that you couldn't find a simple tableview tutorial to learn that from yourself, which is a very very important step for any developer : search, read, try, retry, learn. I have answered with as much detail as possible and will answer your questions, but a simple google search would've led you to amazing websites that you will now remember :

    AppCoda.com

    RayWenderlich.com

Once you know how to work their tutorials of very static data, you can read another tutorial about databases and simply mix both. Even though I'm sure there are many tutorials that will show a complete step by step on how to load data to an array, display it, edit/delete some of it, and re-save it permanently.

Once you're comfortable with all that, you can start reading about Core data (wihch is a bit tough to handle at first, but quite amazing), or simply FMDB and SQLite. If there is one advice I can give you, do NOT use Sqlite by itself, use the FMDB wrapper. sqlite3 is just a massive pain to code from scratch.

Hope this helps. :)

Upvotes: 1

André Slotta
André Slotta

Reputation: 14030

  1. in your detailviewcontroller you could set toDoItem to be a weak property...
  2. in didselectrow of your mainviewcontroller after instantiating your detailviewcontroller you could then set its todoitem to be the todoitem from your mainviewcontroller at the given index path

in your detailviewcontroller you are then working with the item from the mainviewcontroller and

  1. in your unwind segue the only thing you have to to is reload the tableviews data.

hope you understand what i mean :)

Upvotes: 0

Related Questions