Mohamed Reda
Mohamed Reda

Reputation: 15

How to go from UITableViewController to multiple View Controllers

I'm a new iOS developer and when I make project for Recipes I face this problem I need go from each cell to a separate view controller each view controller have an array of images and it's displayed as UIPageViewController. This is my array on the first view controller is called (RecipeViewController)

- (void)viewDidLoad
{

    [super viewDidLoad];
    // Initialize table data

    Recipe *recipe1 = [Recipe new];
    recipe1.name = @"Egg Benedict";
    recipe1.prepTime = @"30 min";
    recipe1.imageFile = @"egg_benedict.jpg";
    recipe1.ingredients = [NSArray arrayWithObjects:@"2 fresh English muffins", @"4 eggs", @"4 rashers of back bacon", @"2 egg yolks", @"1 tbsp of lemon juice", @"125 g of butter", @"salt and pepper", nil];

    Recipe *recipe2 = [Recipe new];
    recipe2.name = @"Mushroom Risotto";
    recipe2.prepTime = @"30 min";
    recipe2.imageFile = @"mushroom_risotto.jpg";
    recipe2.ingredients = [NSArray arrayWithObjects:@"1 tbsp dried porcini mushrooms", @"2 tbsp olive oil", @"1 onion, chopped", @"2 garlic cloves", @"350g/12oz arborio rice", @"1.2 litres/2 pints hot vegetable stock", @"salt and pepper", @"25g/1oz butter", nil];

    Recipe *recipe3 = [Recipe new];
    recipe3.name = @"Full Breakfast";
    recipe3.prepTime = @"20 min";
    recipe3.imageFile = @"full_breakfast.jpg";
    recipe3.ingredients = [NSArray arrayWithObjects:@"2 sausages", @"100 grams of mushrooms", @"2 rashers of bacon", @"2 eggs", @"150 grams of baked beans", @"Vegetable oil", nil];

    Recipe *recipe4 = [Recipe new];
    recipe4.name = @"Hamburger";
    recipe4.prepTime = @"30 min";
    recipe4.imageFile = @"hamburger.jpg";
    recipe4.ingredients = [NSArray arrayWithObjects:@"400g of ground beef", @"1/4 onion (minced)", @"1 tbsp butter", @"hamburger bun", @"1 teaspoon dry mustard", @"Salt and pepper", nil];

    Recipe *recipe5 = [Recipe new];
    recipe5.name = @"Ham and Egg Sandwich";
    recipe5.prepTime = @"10 min";
    recipe5.imageFile = @"ham_and_egg_sandwich.jpg";
    recipe5.ingredients = [NSArray arrayWithObjects:@"1 unsliced loaf (1 pound) French bread", @"4 tablespoons butter", @"2 tablespoons mayonnaise", @"8 thin slices deli ham", @"1 large tomato, sliced", @"1 small onion", @"8 eggs", @"8 slices cheddar cheese", nil];

    Recipe *recipe6 = [Recipe new];
    recipe6.name = @"Creme Brelee";
    recipe6.prepTime = @"1 hour";
    recipe6.imageFile = @"creme_brelee.jpg";
    recipe6.ingredients = [NSArray arrayWithObjects:@"1 quart heavy cream", @"1 vanilla bean, split and scraped", @"1 cup vanilla sugar", @"6 large egg yolks", @"2 quarts hot water", nil];

    Recipe *recipe7 = [Recipe new];
    recipe7.name = @"White Chocolate Donut";
    recipe7.prepTime = @"45 min";
    recipe7.imageFile = @"white_chocolate_donut.jpg";
    recipe7.ingredients = [NSArray arrayWithObjects:@"3 1/4 cups flour", @"2 teaspoons baking powder", @"1/4 teaspoon salt", @"2 beaten eggs", @"2/3 cup sugar", @"2 ounces melted white chocolate", @"1/2 cup milk", nil];

    Recipe *recipe8 = [Recipe new];
    recipe8.name = @"White Chocolate Mocha";
    recipe8.prepTime = @"5 min";
    recipe8.imageFile = @"starbucks_coffee.jpg";
    recipe8.ingredients = [NSArray arrayWithObjects:@"2/3 cup whole milk", @"6 tablespoons white chocolate chips", @"coffee", @"whipped cream", nil];

    Recipe *recipe9 = [Recipe new];
    recipe9.name = @"Vegetable Curry";
    recipe9.prepTime = @"30 min";
    recipe9.imageFile = @"vegetable_curry.jpg";
    recipe9.ingredients = [NSArray arrayWithObjects:@"1 tablespoon olive oil", @"1 onion, chopped", @"2 cloves garlic", @"2 1/2 tablespoons curry powder", @"2 quarts hot water", nil];

    Recipe *recipe10 = [Recipe new];
    recipe10.name = @"Instant Noodle with Egg";
    recipe10.prepTime = @"8 min";
    recipe10.imageFile = @"instant_noodle_with_egg.jpg";
    recipe10.ingredients = [NSArray arrayWithObjects:@"1 pack of Instant Noodle", @"2 eggs", nil];

    Recipe *recipe11 = [Recipe new];
    recipe11.name = @"Noodle with BBQ Pork";
    recipe11.prepTime = @"20 min";
    recipe11.imageFile = @"noodle_with_bbq_pork.jpg";
    recipe11.ingredients = [NSArray arrayWithObjects:@"1 pack of Instant Noodle", @"BBQ pork", @"Salt and Pepper", nil];

    Recipe *recipe12 = [Recipe new];
    recipe12.name = @"Japanese Noodle with Pork";
    recipe12.prepTime = @"20 min";
    recipe12.imageFile = @"japanese_noodle_with_pork.jpg";
    recipe12.ingredients = [NSArray arrayWithObjects:@"1 pack of Japanese Noodle", @"2 green onions", @"2 garlic cloves, minced", @"4 boneless pork loin chops", nil];

    Recipe *recipe13 = [Recipe new];
    recipe13.name = @"Green Tea";
    recipe13.prepTime = @"5 min";
    recipe13.imageFile = @"green_tea.jpg";
    recipe13.ingredients = [NSArray arrayWithObjects:@"Green tea", nil];

    Recipe *recipe14 = [Recipe new];
    recipe14.name = @"Thai Shrimp Cake";
    recipe14.prepTime = @"1.5 hours";
    recipe14.imageFile = @"thai_shrimp_cake.jpg";
    recipe14.ingredients = [NSArray arrayWithObjects:@"8 oz (250g) peeled and deveined raw shrimp", @"2 tablespoons red curry paste", @"1 large egg", @"2 teaspoon fish sauce", @"1 tablespoon sugar", @"2 tablespoons coconut milk", @"2 tablespoons roughly chopped Thai basil leaves", nil];

    Recipe *recipe15 = [Recipe new];
    recipe15.name = @"Angry Birds Cake";
    recipe15.prepTime = @"4 hours";
    recipe15.imageFile = @"angry_birds_cake.jpg";
    recipe15.ingredients = [NSArray arrayWithObjects:@"12 tablespoons (1 1/2 sticks) unsalted butter", @"2 1/2 cups all-purpose flour", @"1 tablespoon baking powder", @"1 teaspoon salt", @"1 3/4 cups sugar", @"2 large eggs, plus 3 large egg yolks", @"1 cup of milk", nil];

    Recipe *recipe16 = [Recipe new];
    recipe16.name = @"Ham and Cheese Panini";
    recipe16.prepTime = @"10 min";
    recipe16.imageFile = @"ham_and_cheese_panini.jpg";
    recipe16.ingredients = [NSArray arrayWithObjects:@"2 tablespoons unsalted butter", @"4 cups thinly sliced shallots", @"2 teaspoons fresh thyme", @"1/4 cup grainy Dijon mustard", @"8 slices rustic white bread", @"8 slices Gruyere cheese", @"8 ounces sliced cooked ham", nil];

    recipes = [NSArray arrayWithObjects:recipe1, recipe2, recipe3, recipe4, recipe5, recipe6, recipe7, recipe8, recipe9, recipe10, recipe11, recipe12, recipe13, recipe14, recipe15, recipe16, nil];
}

So when I press "Egg Benedict" I need to go to the view controller with image array and when I select "Mushroom Ristto" go to another view controller with another image array and so on for each 16 array what I have. and i use prepareForSegueand the code as the following

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:@"themeDetails"]) {
    NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
    ThemeDetailViewController *destViewController = segue.destinationViewController;
    destViewController.theme = [titleLabel objectAtIndex:indexPath.row];
}

if this correct or need to modify my (`ReciepeViewController.h)is as follow

@property (nonatomic, strong) ReciepeDetailViewController *reciepeDetailController;

please help me; i make search many times on google and youtube but didn't get anything

Upvotes: 0

Views: 180

Answers (2)

CouchDeveloper
CouchDeveloper

Reputation: 19124

You should create a dynamic table view.

I would suggest the following improvements to your code:

First, I would create a JSON file which contains your recipes, which will become a resource file in the application bundle:

Create a file "recipes.json" with the following content:

[
    {
        "preparation_time": 30, 
        "image_url": "egg_benedict.jpg", 
        "name": "Egg Benedict", 
        "ingredients": [
            "2 fresh English muffins", 
            "4 eggs", 
            "4 rashers of back bacon", 
            "2 egg yolks", 
            "1 tbsp of lemon juice", 
            "125 g of butter", 
            "salt and pepper"
        ]
    }, 
    {
        "preparation_time": 30, 
        "image_url": "mushroom_risotto.jpg", 
        "name": "Mushroom Risotto", 
        "ingredients": [
            "1 tbsp dried porcini mushrooms", 
            "2 tbsp olive oil", 
            "1 onion, chopped", 
            "2 garlic cloves", 
            "350g/12oz arborio rice", 
            "1.2 litres/2 pints hot vegetable stock", 
            "salt and pepper", 
            "25g/1oz butter"
        ]
    }
]

(note: I've only put two recipes from your code sample into the JSON file)

Then, Iín your View Controller in viewDidLoad load the recipes and create a JSON representation, which is an array of dictionaries:

NSBundle* mainBundle = [NSBundle mainBundle];
NSURL* recipesDataURL = [mainBundle URLForResource:@"recipes" withExtension:@"json"];
if (recipesDataURL) {
    NSData* data = [NSData dataWithContentsOfURL: recipesDataURL];
    if (data) {
        NSError* error;
        NSArray* recipes = [NSJSONSerialization JSONObjectWithData:data 
                                                           options:0 
                                                             error:&error];
        if (recipes == nil) {
            // error: couldn't parse the JSON
            return;
        }
        self.recipes = recipes;
    }
    else {
        // error: couldn't load the data with the given URL
        return;
    }
}
else {
    // error: couldn't locate the resource in the bundle
    return;
}

self.recipes is a property of your view controller which is an array of recipes (NSDictionary).

A recipe itself is a NSDictionary. If you want, you can create a dedicated class Recipe and initialize a recipe object (e.g. initWithParameters: with that dictionary which contains the "parameters". It may however totally sufficient to use a NSDictionary as a recipe object.

If you use a dynamic table view, you need to implement a few delegate methods. The official documentation has more info, please take a look at the various topics available regarding UITableView: UITableView Programming Guide for iOS

Basically and as a jump start, your TableViewDataSource Delegate will access the array self.recipes in order to get the number of rows and the recipe object's properties when setting up a cell. For example:

UITableViewDataSource delegate:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [self.recipes count];
}

- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath 
{
    UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:@"MyIdentifier"];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
                                      reuseIdentifier:@"MyIdentifier"];
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
    }
    NSDictionary* recipe = [self.recipes objectAtIndex:indexPath.row];
    cell.textLabel.text = recipe[@"name];
    return cell;
}

Edit:

You can show a detail view, which displays all the details of a recipe as already shown in other answers. I would suggest to following:

Your Detail View Controller has a public property recipe of type NSDictionary:

@property (nonatomic, strong) NSDictionary* recipe; 

When you don't leverage storyboard, you can show the detail view controller as follows:

In your TableViewController.m:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{
    NSDictionary* recipe = [self.recipes objectAtIndex:[indexPath row]];
    ShowRecipeViewController* viewController = (ShowRecipeViewController*)[[ShowRecipeViewController alloc] initWithNibName:@"ShowRecipeViewController" bundle:nil];
    viewController.recipe = recipe;
    [[self navigationController] pushViewController: viewController animated:YES];
}

I would suggest however to use storyboards. In this case, the detail view controller will get the property recipe set in prepareForSegue:sender:.

See also: Passing data between View Controllers using Segue

Upvotes: 1

Tapas Pal
Tapas Pal

Reputation: 7207

You have an better option, go to a single ViewController and make it dynamic respective your data. But as you want to go multiple ViewController for respective data, just do the below...

Add a property in your Recipe interface and synthesize it

@property (nonatomic, retain) UIViewController *MyViewController;

Now in your viewDidLoad method do the below

-(void)viewDidLoad
{
    [super viewDidLoad];
    ObjectHolderArray=[[NSMutableArray alloc] init]; // it's mutable array for holding all the object of recipe which we are going to create

    Recipe *recipe1 = [Recipe new];
    recipe1.name = @"Egg Benedict";
    recipe1.prepTime = @"30 min";
    recipe1.imageFile = @"egg_benedict.jpg";
    recipe1.ingredients = [NSArray arrayWithObjects:@"2 fresh English muffins", @"4 eggs", @"4 rashers of back bacon", @"2 egg yolks", @"1 tbsp of lemon juice", @"125 g of butter", @"salt and pepper", nil];
    recipe1.MyViewController=[[eggBenedictViewController alloc] init]; //set your respective viewController
    [ObjectHolderArray addObject:recipe1]; // add your object to your array

    Recipe *recipe2 = [Recipe new];
    recipe2.name = @"Mushroom Risotto";
    recipe2.prepTime = @"30 min";
    recipe2.imageFile = @"mushroom_risotto.jpg";
    recipe2.ingredients = [NSArray arrayWithObjects:@"1 tbsp dried porcini mushrooms", @"2 tbsp olive oil", @"1 onion, chopped", @"2 garlic cloves", @"350g/12oz arborio rice", @"1.2 litres/2 pints hot vegetable stock", @"salt and pepper", @"25g/1oz butter", nil];\
    recipe1.MyViewController=[[mushroomRisottoViewController alloc] init]; //set your respective viewController
    [ObjectHolderArray addObject:recipe2]; // add your object to your array
   // and so on
}

Now in didSelectRowAtIndexPath do the below

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{
   Recipe *recipeObject=[ObjectHolderArray objectAtIndex:[indexpath row]]; //get the selected recipe object

   UIViewController *myController=(UIViewController *)[recipeObject MyViewController];
   // Now you have your respective viewcotroller and also all the required data for going to next viewController
  // then what you are waiting for? simply push your viewcontroller

}

Upvotes: 0

Related Questions