Improve the Recipe App With a Better Detail View Controller

39 Flares 39 Flares ×

Several weeks ago, we showed you how to use Segue in Storyboard to pass data between different view controllers. We’ve built a simple app to display a list of recipes. When user taps on any of the recipes, the app navigates to a detailed view and brings up the recipe name. This is very simple app. But if you understand how it works, this is the foundation to help you advance into a full-fledge iOS developer.

After publishing the tutorial, I got lots of requests to improve the detail view. The original detail view is primitive with the recipe name only. How can we improve it and display more information such as the preparation time, ingredient and the dish photo? In this tutorial, we’ll work on it together and make a better app. Before we move on, however, make sure you check out the below tutorial:

You have to understand the basic OOP concept before you can work on this tutorial. If you haven’t done so, take some time and read through the article. You can’t become a full-fledged iOS developer without learning objects and classes.

The Final Deliverable

To give you an idea about the improvement, let’s first take a look at the final deliverable. As you can see from the sample screenshot, the revamped Recipe app shows user detailed information about a recipe.

recipe app with improved detail view

Recipe app with improved detail view

Revisit the Segue Data Passing

Storyboard Segue Identifier

Storyboard Segue Identifier

In the Segue tutorial, we explained how to make use of Segue to pass the recipe name from the list view to the detail view. Here is the code:

1
2
3
4
5
6
7
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([segue.identifier isEqualToString:@"showRecipeDetail"]) {
        NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
        RecipeDetailViewController *destViewController = segue.destinationViewController;
        destViewController.recipeName = [recipes objectAtIndex:indexPath.row];
    }
}

We simply set the property (i.e. recipeName) in the RecipeDetailViewController to pass the recipe name. Obviously, you can add other properties in the detail view controller to pass other recipe-related values. However, this is not the best practice. If you’ve read the OOP tutorial, you know it’s better to create a Recipe class and group all the properties within the class.

Let’s Get Started

First, download this Xcode project. You’ll use this project as a baseline to build the app.

Creating a Recipe Class

We’ll first create the Recipe Class. Right click on RecipeBook folder and select “New File…”. Choose the “Objective-C class” template (under Cocoa Touch) and click “Next”. Name the class as “Recipe” and as a subclass of “NSObject”. Click “Next” and save the file in your Xcode project folder.

Create the Recipe Class

Create the Recipe Class with NSObject as subclass

Once completed, Xcode will create the Recipe.h and Recipe.m files. In the header file, add the properties of the Recipe class:

1
2
3
4
5
6
7
8
@interface Recipe : NSObject

@property (nonatomic, strong) NSString *name; // name of recipe
@property (nonatomic, strong) NSString *prepTime; // preparation time
@property (nonatomic, strong) NSString *imageFile; // image filename of recipe
@property (nonatomic, strong) NSArray *ingredients; // ingredients

@end

In the implementation file (i.e. Recipe.m), we add the @synthesis directive. The @synthesize directive tells the compiler to generate the setters and getters for accessing the properties we define in the header.

1
2
3
4
5
6
7
8
@implementation Recipe

@synthesize name;
@synthesize prepTime;
@synthesize imageFile;
@synthesize ingredients;

@end

Now we’ve created a Recipe class with various properties including recipe name, preparation time, image and ingredients. Later we’ll make use of it to instantiate different recipe objects and pass it to the detail view controller.

Populate the Recipe Data

To keep thing simple, we’ll populate the recipe data right in the “RecipeBookViewController”. In real app, this kind of data are usually stored in property list file or database.

In the “viewDidLoad” method of “RecipeBookViewController.m”, we initialize the Recipe objects (with different preparation time, ingredients, etc) and put them into the “recipes” array.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
- (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];

}

Redesign the Detail View Controller

Originally, the detail view controller only displays the name of recipe. We’re going to revamp it to show users more information about a recipe. First, download this image pack and add all the images to the projects.

Recipe Images Added

Add the Recipe Photos to the Project

What’s @2x image?

Since the release of iPhone 4 with Retina display, your app should prepare to support different screen resolutions (i.e. 320×480 for older generation of iPhone and 640×960 for iPhone 4 or later). Apple has made it fairly easy for iOS developers to support multiple resolutions. Applications should include two separate files for each image resource. One file provides a standard-resolution version of a given image, and the second provides a high-resolution version of the same image. The naming conventions for each pair of image files is as follows:

Standard: <ImageName>.<filename_extension>
High resolution: <ImageName>@2x.<filename_extension>

The UIImage class handles all of the work needed to load high-resolution images into your application. When you load an image with UIImage, it automatically determine the screen resolution and loads the corresponding image file. For instance,

UIImage* anImage = [UIImage imageNamed:@"photo-frame"];

The above code will load “[email protected]” on device with high resolution. While on the standard screen resolution, it loads up the “photo-frame.png”.

Select the Storyboard and locate the “Recipe Detail View Controller”. First and foremost, delete the “Label” component and add an image view to the detail view. Set the width and height of the image view to 297 and 199 respectively.

Detail View - Add Image View

Detail View - Add Image View

Select the attribute inspector and set the image to “photo-frame.jpg”. As you set the image, it’ll be automatically loaded and displayed in the Storyboard. This image is used to display a photo frame for the recipe photo.

Detail View - Photo Frame

Detail View - Photo Frame

Next, we add another image view that serves as a placeholder of the recipe photo. Drag the image view from the Object Library and place it over the photo frame like the screen shown below.

Detail View - Recipe Photo Image View

Image View for Recipe Photo

Now, add a label and change the text to “Ingredients”. In the attribute inspector, you can change the font size and type by altering the “Font” option. Just use the default system font or pick the one you like. Next, add another label for preparation time. Lastly, drag the Text View object to the view. The Text View is an UI element for displaying multiple lines of text. We’ll use it to display the list of ingredient. Below is the screenshot for your reference:

Detail View - Label and Text View

Detail View - Label and Text View

Establish the Connection Between Variables and UI Elements

With the redesigned interface, we’ll establish the connection between our code and the UI elements. In the Storyboard, select the “Recipe Detail View Controller” and switch to the Assistant Editor.

Show Assistant Editor

Show Assistant Editor and Hide Utility Area

Press and hold the control key, click the image view and drag it towards the “RecipeDetailViewController.h”. As you place the pointer between the “@interface” and “@end” keywords, you should see a prompt that allows you to insert an outlet. Name the outlet variable as “recipePhoto”.

Detail View - Establish Variable Connection

Detail View - Establish Variable Connection

Repeat the same step for the “PrepTime” label and Text View. Name the outlet of PrepTime label as “prepTimeLabel” and that of text view as “ingredientTextView”. Lastly, add a property for recipe. This property allows other controllers to pass the recipe details. After all the changes, the RecipeDetailViewController.h should like this:

1
2
3
4
5
6
7
8
9
10
11
12
#import <UIKit/UIKit.h>
#import "Recipe.h"

@interface RecipeDetailViewController : UIViewController

@property (weak, nonatomic) IBOutlet UIImageView *recipePhoto;
@property (weak, nonatomic) IBOutlet UILabel *prepTimeLabel;
@property (weak, nonatomic) IBOutlet UITextView *ingredientTextView;

@property (nonatomic, strong) Recipe *recipe;

@end

In the viewDidLoad method of the RecipeDetailViewController.m, change it to the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- (void)viewDidLoad
{
    [super viewDidLoad];
   
    self.title = recipe.name;
    self.prepTimeLabel.text = recipe.prepTime;
    self.recipePhoto.image = [UIImage imageNamed:recipe.imageFile];

    NSMutableString *ingredientText = [NSMutableString string];
    for (NSString* ingredient in recipe.ingredients) {
        [ingredientText appendFormat:@"%@\n", ingredient];
    }
    self.ingredientTextView.text = ingredientText;
   
}

Here, we add code to setup the Recipe Detail View. Line 5 of the code alters the title of navigation bar to the name of recipe. Line 6 and 7 configure the preparation time label and set the recipe photo.

Line 9 to 13 turns the ingredients array into multiple lines of text for the ingredient text view. The “\n” character is an escape character to say “Put a carriage return here”. In other words, it’s a new line indicator.

Passing Recipe to Detail View Controller

As we’ve learnt in the Segue tutorial before, Segues manages the transition between view controllers. When a segue is triggered, before the visual transition occurs, the storyboard runtime invokes prepareForSegue:sender: method of the current view controller. By implementing this method, we can pass any needed data to the view controller that is about to be displayed. Here, we’ll pass the selected recipe object to the detail view controller.

In the prepareForSegue method of RecipeBookViewController.m, change the code to:

1
2
3
4
5
6
7
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([segue.identifier isEqualToString:@"showRecipeDetail"]) {
        NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
        RecipeDetailViewController *destViewController = segue.destinationViewController;
        destViewController.recipe = [recipes objectAtIndex:indexPath.row];
    }
}

Line 5 of the above code determines the selected recipe (base on the indexPath) and passes it to the Recipe Detail View Controller (i.e. the destViewController variable).

Run the App

You’ve made it! The final step is to execute the app and see how it works. If your app can run properly, it should give you a much polished Recipe Details.

recipe app with improved detail view

Recipe app with improved detail view

What’s Next?

I hope you enjoy the tutorial and love the app you just built. It’s not a complex app but it covers some of the most common UI elements such as navigation controller and tab bar controller. Don’t wait for the next tutorial to show you what to do next. I encourage you to tweak the app and make it even better. Say, use a table view (instead of text view) to list out all ingredients or add a new tab item. As I said before, you can’t become a good programmer by just reading a book or this tutorial. You have to explore, make mistake and most importantly code! So base on what you’ve learnt, tweak the app and turn it into your own.

As always, leave us comment to share your thought.

Update: You can download the source code of the Xcode project from here.

You May Like These:

Get Free Chapters of Our AppCoda Book

Learn iOS 7 Programming from Scratch

The Learn iOS 7 Programming from Scratch is a 400-page eBook written for beginners with little or even no programming experience. It is based on the tutorials of our popular programming course. The book starts with the basics and walks you through the process to create iOS apps using iOS 7 SDK and Xcode 5. Want to learn more? Check it out here and get two free chapters.


Build Your Own Game and Monetize on the Side

Learn how to develop your first iOS game and make money on the side. The starter kit will come with full source code of a memory game for both iPhone and iPad, as well as, a complete guide to explain how the code works. Check out the starter kit to learn more.


  • Bubumuk

    It looks great! Thank you.

  • Pingback: best apps for health and wellness, iphone ipad health apps » Instaframe Pro – Photo Frame & Photo Captions for Instagram

  • Toby Powell

    your tutorials and site are fantastic! you do a great job of explaining the concepts, this is absolutely my favorite ios site, i’ve got a ton of books and done a ton of video tutorials but your tutorials really clarify the topics, thanks Simon, keep up the great work!

    • http://www.simonblog.com Simon Ng

      Thanks, Toby!

  • Thomas

    When I download the Xcode project I cannot find the “SimpleTable” folder. Mine says RecipeBook. What am I doing wrong?

  • Thomas

    When I download the Xcode project I cannot find the “SimpleTable” folder. Mine says RecipeBook. What am I doing wrong?

    • http://www.simonblog.com Simon Ng

      Typo. Yes, it should be RecipeBook folder.

  • James

    This is what I’ve been looking for thanks:)

  • Martin

    Hi, great tut. But, in RecipeDetailViewController.h you should’nt import Recipe.h, just use @class recipe :) Looking forward to see more tutorials :) Thanks

  • Thomas

    I can’t get this tutorial to work. I haven’t had any problems with any others but this one is not working. Seems like there are a few steps that you forgot to add? I am following this word for word and with no luck. Are you sure this is all correct?

    • http://www.simonblog.com Simon Ng

      What error did you get?

  • Kmo

    Great tutorial however, the build receives a SIGABRT error after compiling. Using Xcode 4.4.1 (4F1003).
    First I went through the tutorial hand jamming the code in myself and after he build the SIGABRT popped up. Then I started again and just copy and pasted the code directly, same SIGABRT:

    2012-08-18 15:31:01.532 RecipeBook[2859:f803] -[__NSCFConstantString
    name]: unrecognized selector sent to instance 0xa290
    2012-08-18 15:31:01.535 RecipeBook[2859:f803] *** Terminating app due
    to uncaught exception ‘NSInvalidArgumentException’, reason:
    ‘-[__NSCFConstantString name]: unrecognized selector sent to instance
    0xa290′
    *** First throw call stack:
    (0x14b9022 0xeb9cd6 0x14bacbd 0x141fed0 0x141fcb2 0×4630 0xe3a1e
    0xe3d11 0xf58fd 0xf5aef 0xf5dbb 0xf685f 0xf6e06 0xf6a24 0x452de6
    0x4474d0 0xad581 0xad7fa 0x94285d 0x148d936 0x148d3d7 0x13f0790
    0x13efd84 0x13efc9b 0x13a27d8 0x13a288a 0x1c626 0x1d5d 0x1cc5)
    terminate called throwing an exception(lldb)

    At this line:

    cell.textLabel.text = [recipes objectAtIndex:indexPath.row];

    Maybe Xcode doesn’t support this anymore?

    Anyway thanks for the great tutorials, followed a bunch so far with no issues. Excellent explanations.

    -Kmo

    • http://www.simonblog.com Simon Ng
      • Kmo

        My project turned into a disaster. I believe I found the mistake. I neglected to create the segue as instructed in the initial part of the tutorial. I am going to rebuild the project from the ground up again. Totally my bad. I knew it had something to do with either me or the Xcode build. Like maybe Apple updated Xcode and it deprecated some of the commands. If my new build fails to compile I will zip it up and send it to app coda support.

        By the way the site is great. This is by far the best Xcode tutorial website I have come across. The author(s) definitely do a great job of explaining the underlings of Xcode and why code is the way it is. I’ve learned more doing Appcoda’s tutorials the wrong way, than I have following other tutorials the right way lol. Thank you for putting time and effort into this sight.

        -Kmo

        • Kmo

          I identified the problem and was able to fix it. The recipe array (loaded with recipe1, recipe2, recipe3, ect.) was conflicting with the tableView array that was loading the tableView cells with the names of the recipes located here:

          cell.textLabel.text = [recipe objectAtIndex:indexPath.row];
          The fix was easy but not ideal for working with our recipe objects that were created. The fix is too create a new array and declare it within the recipeViewController.m file and then add the array with the strings attached.
          I.E.
          recipeViewController.m
          @interface minuteMealsViewController ()

          @end

          @implementation minuteMealsViewController {
          NSArray *recipes;
          NSArray *thumbnails;
          NSArray *recipeTitle; //This is my new array.
          }
          @synthesize tableView;
          Then fill the array as so:
          recipeTitle = [NSArray arrayWithObjects:@"Egg Benedict", @"Mushroom Risotto", @"Full Breakfast", @"Hamburger", @"Ham and Egg Sandwich", @"Creme Brelee", @"White Chocolate Donut", @"Starbucks Coffee", @"Vegetable Curry", @"Instant Noodle with Egg", @"Noodle with BBQ Pork", @"Japanese Noodle with Pork", @"Green Tea", @"Thai Shrimp Cake", @"Angry Birds Cake", @"Ham and Cheese Panini", nil]; //This is my new filled array, I put it right above the //”recipes” array as you can see and right below the “Recipe16″ object.

          recipes = [NSArray arrayWithObjects:recipe1, recipe2, recipe3, recipe4, recipe5, recipe6, recipe7, recipe8, recipe9, recipe10, recipe11, recipe12, recipe13, recipe14, recipe15, recipe16, nil];
          Then I changed my:
          cell.textLabel.text = [recipe objectAtIndex:indexPath.row];
          too:
          cell.textLabel.text = [recipeTitle objectAtIndex:indexPath.row];
          Now it works as advertised. However I would rather declare all of my object`s data once in the “.m” file and be able to pull that data when and where I need it. That would be the essence of OOP.
          Next is creating another segue that will lead the user to another view controller that will have the recipe instructions. Will update when I figure that one out. Good Luck.
          -Kmo

          • RMD

            Something a little easier that worked for me.
            Replace this line:
            cell.textLabel.text=[recipes objectAtIndex:indexPath.row];

            with:
            Recipe *thisRecipe=[recipes objectAtIndex:indexPath.row];
            cell.textLabel.text=thisRecipe.name;

            Mine worked after that.

          • Natarajan

            This worked for me too ..

  • adrian phillips

    i have the same issue as kmo. i built the app according to the tut and it has no warning but app crashes at start due and uncaught exception. here is the reason according to the log: Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘-[Recipe isEqualToString:]: unrecognized selector sent to instance 0x6e941f0′
    is there anyway you can upload the sample code so we can see where the problem is?

  • PK

    please give the updated and final running code this is not running and not the proper issue has been given. Kindly update I have followed from start and stucked in here.

  • adrian phillips

    hi simon,

    i sent you a zip project to the support email and wanted you to take a look at it if you have time. the app crashes at the point cell.textlabel.text. i would appreciate if you could let us know how to fix it.

    adrian

    • http://www.simonblog.com Simon Ng

      I’ll take a look soon.

  • JDG

    How could we put the receives in allphabetical order with an index showing down the side?

  • Daragh

    Hey Simon, I am having problems and getting the “Use of undeclared identifier ‘recipe’; did you mean ‘Recipe’?” issue on the RecipeDetailViewController.h file. I have followed all your tuts , and have redone this particular tut a number of times. Im sure its a small thing but cant figure it out ;-(

    • Daragh

      … Sorry I meant the RecipeDetailViewController.m file. I have enclosed a screen grab of same.

      • Zach Raybould

        Did you manage to fix ?

      • dottorfeelgood

        I have the same issue. Did you find out how to solve it?

      • Nate

        I FIXED IT (i think)
        You have to @synthesize recipe; in the detailviewcontroller.m
        I just tried it, I dont know if it would compile right though……

  • Zach Raybould

    I get the same error as Daragh (use of undeclared identifier ‘recipe’ ) in RecipeDetailViewController.m

    • Clayton

      Did you ever fix this error? this is what i am getting too!

  • Redet Pace

    These tutorials have helped me more than you know! I have a much better understanding of what I’m doing and how it should be done! I would love to see this app continue with using Core Data. Thank you!

  • Clayton Romberg

    This is my error at this point anyone know how to fix?

    • Clayton Romberg

      pic

    • Clayton Romberg

      i got it.

  • http://www.facebook.com/profile.php?id=619730457 Brendan Sue

    Do you have a final zip file with all the code? I am having trouble after using your initial zip file and following your tutorial exactly. I have the following screenshot to show the only part of the project where there are errors.

    • http://www.simonblog.com Simon Ng

      What are the errors?

      • http://www.facebook.com/profile.php?id=619730457 Brendan Sue

        It says ‘use of undeclared identifier ‘recipe’ in my ‘recipeDetailViewController.m’ for the four instances where the ‘recipe’ is referenced under method ‘viewDidLoad’

        • Jc

          Try adding self. In front of the recipe

        • Osvaldo Cipriano

          Like Kevin said you must add @synthesize recipe; into RecipeDetailViewController.m

  • kerm

    Hi Simon. Please help to fix (use of undeclared identifier ‘recipe’ ) in RecipeDetailViewController.m

    Tried tinkering around but I guess I’m too new for this.

    Very excited to finish this tutorial and make it work. I think it’s something about the xCode version.

    Thanks a lot for helping newbies like me and more power.

    • kevin

      you have to synthesize recipes in recipedetailviewcontroller.m
      @synthesize recipes;

      • Osvaldo Cipriano

        @synthesize recipe; not @synthesize recipes;

  • Nathan

    Hey Simon, can you give the completed zip file of this project? I (or we) are experiencing a lot of problems like sigabrt errors. Thanks

  • nansaeyuki

    Hello
    Your lecture has been a great help to me.
    Therefore, in this lecture made​​, an error occurs and the application.
    Mail was sent to you.
    Mail the attached example I made.
    Screen capture of the error I’m going to send an e-mail.
    Thank you.

    • http://www.simonblog.com Simon Ng

      I’ll take a look and reply you soon.

      • http://twitter.com/minasememory 망각인간

        thanks, i’ll waiting for your reply

  • Serkan

    hey give the running code. because u didnt tell how can we connect images and detail window data from a plist.!!

  • rufus

    someone can tell me how can we load images from a plist array to detailViewController ????? i cant load big images in to detailview.

  • LG

    Hey Could you send me the finale code folder to see what I’m doing wrong? I’d like to compare so I understand better where my mistake is?

    Thank you!

  • Newbie

    I’m trying to implement your ‘Recipe Book’ iPhone app as a learning experience, which has been successful up to the present point where I am unable to instantiate a custom class. My inexperience means I don’t know where to begin to address the problem. Compiler diagnostics show up as follows:

    Code fragment:
    Recipe *recipe1 = [Recipe new];
    recipe1.name = @”Egg Benedict”;

    Produces the error:
    Use of undeclared identifier ‘Recipe’

    Can you help me? Kind regards, Newbie.

    • http://twitter.com/Amethen Vladimir

      Import Recipe.h class to RecipeDetailViewController.h file

  • http://www.facebook.com/christopher.harris.77920526 Christopher Harris

    For those getting the following error:

    Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘-[Recipe isEqualToString:]:

    The issue is in RecipeBookViewController.m. Find the line “cell.textLabel.text = recipe.name;” in – (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { }

    The variable recipe is now a NSArray object, in previous tutorials it was an NSString object. Change the code as follows:

    Recipe *recipe = [recipes objectAtIndex:indexPath.row];
    cell.textLabel.text = recipe.name;

    Make sure you include “Recipe.h” in your RecipeBookViewController.h file. Happy coding.

    • Chelsea Richards

      Two thumbs up!!! Thanks for sharing your thoughts it
      helps me a lot to be honest!!! I’m looking forward for any of your updates and
      a post that you might want to share… XOXO:D
      FrameForge3D.com

    • http://twitter.com/smarterkey smarterkey

      I am a beginner learning to catch up with our programmers and i have just gone through the previous 3 tutorial and now this 1 and just completed this app…I’m amazed it worked 4me…Fantastic g8t tutorial.
      I made the following additions to the tutorial:
      1: Necessary to make the amendment as above regarding “recipe.name”
      2: If you copied the screen shots in tutorial precisely then you should already have included #import “Recipe.h”
      3: In DetailVC.m i had to amend in viewDidLoad from after each “=” to “=self.” followed by “recipe” property as per tutorial
      4 : Also i stupidly forgot to synthesize the “recipe” variable which was added into DetailVC.h on 1 of the screen shots.
      Good luck.

    • Khalid Mehmood Awan

      thanks for the quick help… appreciate it.

    • HLA

      I got same problem but i can soved it easly according your comment. thanks a lot….Christ

    • Yasassri Purnajith

      How to resolve the issue for the search ?

      • Nguyen Duc Hung

        Here is my code for search issue:
        All u need to do is replace SELF with name ( property of Recipe class).
        - (void)filterContentForSearchText:(NSString*)searchText
        {
        NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:@"name contains[cd] %@”, searchText];
        searchResults = [recipes filteredArrayUsingPredicate:resultPredicate];
        }

        • Le Phuoc Dai

          thank you Hung :)

        • Shrikanth

          Hi, Didn’t get correct result for search even after making necessary changes. May I get complete code for the same

          • Eran Shmilovitz

            Use the following to display correctly the search results in the table view.

            if (tableView == self.searchDisplayController.searchResultsTableView)
            {
            cell.textLabel.text = [[searchResults objectAtIndex:indexPath.row] name];
            } else {
            cell.textLabel.text = [[recipes objectAtIndex:indexPath.row] name];
            }

    • Eran Shmilovitz

      Another way to do this in just one line of code:
      cell.textLabel.text = [[recipes objectAtIndex:indexPath.row] name];

  • waldorfian

    I’m getting errors in the RecipeDetailViewController.m viewDidLoad method around the recipe object references. says it doesn’t recognize it. I don’t understand why. I have the property statement in the RecipeDetailViewController.h file and it is imported into the implementation file.

  • http://kelmer.tumblr.com kelmer

    Hi, great tutorials. I followed the tutorials right up to this one, but I am having trouble now, no matter what element I click on the list I always end up with the detail view for the first item on the list. I used your code word for word, the only difference is that instead of using the RecipeBookMainController for the TableList I used a separate RecipeListViewController, you think this might be the problem?

    • http://kelmer.tumblr.com kelmer

      My bad, I forgot to link tableView property with the actual tableview in storyboard!

  • Christian

    I have been following this tutorial since the first one. I am having trouble with this when i populate the recipe data in the RecipeBookViewController.m file. it gives me an error message where ever there is a “recipe1″ on the array. It says use of undeclared identifier “recipe1″. I am new to coding so i am unsure what this means. I know I entered everything in correctly and i imported the Recipe class, i think i might be missing something. Please help.

    • http://twitter.com/Amethen Vladimir

      Import Recipe.h class to RecipeDetailViewController.h file

  • http://binceipt.com/ Mark Thien

    Hi Samuel,

    Would you mind enhance this guide on table view with multiple sub categories? For example like the attached image.

  • bug

    great tuto, keep going! like this site!

  • http://twitter.com/saradimario creem

    After insert the new property into the “recipes” array the project show me some errors:
    “use of undeclared identifier ‘recipe’; did you mean recipes?” or “property name not found…” someone please can tell me why?

    • http://twitter.com/Amethen Vladimir

      Import Recipe.h class to RecipeDetailViewController.h file.

      • Daryl Breunissen

        I got the same error but how do you import Recipe.h class to RecipeDetailViewController.h file??

  • ICT student

    Hi

    I tried many times to implemented in my project that I have done by following each word in the document , when i build the app it does not show what I looking for, it does not display and details. Could you help me please to find the solution for it. I will send it to by email

  • ICT student

    Hi, I tried many times ti implemented on my project, I follow the steps and still does not display the details of the pizza, could you please help me to find the solution for it. I send it the file to you by email.

  • punur

    Thank you very much, excellent tutorial, and I had some issues , but after going thru the comments I have figured out. Thanks to everyone.

  • John Morris

    this tutorial does not work! I see many people describing the problem with the recipe class reference but the solutions offered do not correct the error. I tried adding a @class reference that didn’t resolve the errors. I tried a @synthesize statement and that resolved the errors but when I ran it, it crashed. I go this error:

    Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘-[Recipe isEqualToString:]: unrecognized selector sent to instance 0×7505880′

    It really pisses me off that I wasted my time with this tutorial!

    • http://www.simonblog.com Simon Ng

      To fix the error, please change the following line in the “cellForRowAtIndexPath:” method of “RecipeBookViewController.m”

      from:

      cell.textLabel.text = [recipes objectAtIndex:indexPath.row];

      to:

      Recipe *recipe = [recipes objectAtIndex:indexPath.row];
      cell.textLabel.text = recipe.name;

      “recipes” is an array of Recipe object. You should first grab a
      particular Recipe object and retrieve the “name” property to display
      the recipe name in the table.

  • http://twitter.com/jonocarnie Jonathan Carnie

    Apart from having to add a few self. ‘s to the recipe and modifying the cell.textLabel.text bit, the tut works perfectly. Thanks.

  • James

    3 days sitting, but figured out, and now working, thank you)

  • Osvaldo Cipriano

    Hi,

    Great tutorial.
    Is it possible to load the ingredients instead like this with an html? So recipe 1 load an html, recipe 2 another html?

    • http://www.simonblog.com Simon Ng

      Yes, you can change the detail view to a web view. When recipe 1 is selected, you pass the name of the html to the detail view and load the html page in the web view.

      • Osvaldo Cipriano

        Can you tell me how to code that?

        • Osvaldo Cipriano

          Just got it.

  • Hugh Jeremy

    Thanks for the tutorials, with this tutorial, whenever I press a cell to make it show the detailed view, it won’t go to it. It just highlights the cell I pressed. Help much appreciated :)

  • Hugh Jeremy

    Hi there, I have a problem I really can’t seem to solve. I am trying to do two things, http://www.appcoda.com/customize-table-view-cells-for-uitableview/ to customise the cell design and the content of a more detailed view such as this tutorial offers. I cant seem to get either to work and either have errors or get a SIGABRT error. I have a copy of my code on dropbox and I would really really appreciate it if you could fix my project and tell me where I went wrong (by email or any other way you prefer), I’m only 15 so simple instructions much appreciated. DropBox link: https://www.dropbox.com/sh/wss57sf88vk6u2m/AduYP5drpJ .Thanks very much for all your tutorials. Hugh

  • Patrice Mallette

    Thank you Simon for all your work! I agree with most comments here that it’s one of the best series of tutorials around.

    I also want to say to all the people learning Xcode that after reading all the comments and fixing the few typos, yes, the RecipeBook app is working. You too can figure it out!

  • Jubee

    can not run

  • Jubee

    i completed with no issues but when i run the app show this line of code

  • http://www.facebook.com/jaykingster.akasuki Jay Kingster Akasuki

    Great tutorial easy to fallow.But i have some problem that i can not solve by myself please any body tell me. How to add search bar like previous tutorial to this project.Especially in the section of viewDidload and prepareForSegue method of the RecipeDetailViewController.m

  • http://www.facebook.com/mikhail.dieterle Mikhail Dieterle

    I follow this tutorial but result is differ from designed. What I do wrong?

    • http://twitter.com/jmarti326 Juan Marti

      in the story board, in the botton you will see like a circle with a rectangle inside. Press that, after you press it fix the interface position and it will look good.

  • Arkantos

    Hello thanks for the tutorial, I wanted to ask how can I insert an information here. Plist file, I have to keep the class Recipe.NSObject or I have to change the plist?

  • http://www.facebook.com/stefano.dicati Stefano Dicati

    Hi, how i can put in project a search bar?

  • Stefan

    Hi guys!

    I’m might a little late, but i started this tutorial yesterday, and I got a problem. I followed all of the previous tutorials, but when i get to RecipeDetailViewController.m, i get the problem that it won’t recognize recipe. I read the comments, so i added the line @synthesize recipe; and now it runs. unfortunately the app breaks when I touch any of the recipes, and gives me the line:
    return UIApplicationMain(argc, argv, nil, NSStringFromClass([RecipeBookAppDelegate class]));

    Can anybody help me?

    Beforehand thanks :)

    • Varun Iyer

      I have the same problem too please help someone!

      • Khalid Mehmood Awan

        see comments by Christopher Harris above

    • Khalid Mehmood Awan

      the solution is given by Christopher Harris

  • Sidney

    I’m having the same problem I see others have had – recipe was not declared so I did what some of the posts said (synthesize recipe). The undeclared went a way but the app crashed. By the way, these are some of the best tutorials i’ve ever seen. This is the first time I was not able to figure out what was wrong. My name is Sidney. I tried to sign up but I couldn’t get past typing in the the capchatka characters.

  • INdraRosli

    Hello guys,

    Please help me on this error..

  • indraRosli

    Hello Guys,

    Please help me up on this error.Tq

  • Leo

    2 words!
    Love ya!

    • hehe

      wt ya

  • [email protected]

    I am using xCode 4.61. My problem is in prepareForSegue(RecipeBookViewController). The NSArray ingredients object always got a nil value. But i added the debug code in cellForRowAtIndexPath. This is normal.

    Can anybody help me?

    • http://www.simonblog.com Simon Ng

      I’m not sure how you initialize the array. I have just uploaded the source code of the project. Please download it as a reference. This may help to resolve the error.

      • paullauyc

        Thanks for your sample coding and solved my error.

        My problem in Recipe.h as below:

        //**INCORRECT**

        @property (nonatomic, weak) NSArray *ingredients; // <- "weak"

        //^^CORRECT^^

        @property (nonatomic, strong) NSArray *ingredients;

  • Pingback: A Recipe App | Sanjyboi's Blog

  • Alyssa DeChiaro

    How would you do something like this for data that is coming from somewhere else (local server) and not hard coded?

  • amp

    hi simon

    how would you change the cell for row at index path and the segue if you are to change the data source to plist instead of hard coding it in the view did load. lets say i wanted to add the detail view you just created to the plist tutorial you have on your this site. how would i go about that.?

    amp

  • iamxyt

    Can not download the image package

  • Art

    Thanks to Simon for the tutorial, and Christopher for solving the NSInvalidArgumentException issue.
    But does anybody know how to solve the NSInvalidArgumentException issue at the location as per below:
    searchResults = [recipes filteredArrayUsingPredicate:resultPredicate];

    Thanks

  • surendra kachhwaha

    instead of default UITableViewCell i used custom UITableViewCell which u made in Tutorial #4 then it is not going to detail page when i click on any cell in the table view. Can u tell me how to make connection between custom cell and detail view controller, thanks

  • Mark

    Any reason why

    self.title = recipe.name;

    in RecipeDetailViewController.m has the following error:

    Property ‘name’ not found on object of type ‘recipe’?

  • Daniel Encinas

    Hi. It’s my first comment.
    I need to know if there a easy way to load in this custom table data from a webservice like PARSE.
    I needed to make it run my app and actualize it on the road with new info.
    But all the tuts that I follow, are versy confuse or only works with a simple view.

    Thanks

  • Carl

    Hello, does anyone know how to implement a favorite function with this example ?

  • Osvaldo Cipriano

    If i want to show where the people can eat the dish in another view with map anotation what should i do?

  • Danevas

    Hello, I am wondering if someone can share a completed project with me that I can compare to. I am trying to add this detail view to my existing app from the previous tutorial that has a search feature in it. However I have been stuck for what seems like forever and would love to see a working example. Does anyone have a project that has both the detail view and the search working that could post a zip of the Xcode project? Thank you

  • EML

    Why not use tableView didSelectRowAtIndexPath: instead ?

  • CEMSOFT SOFTWARE

    just go on , very good tutorials.

  • Graham

    Hey. Just trying to work with this and noticed it doesn’t work properly now on ios7 changes (navigation bar goes across the image and things are aligned incorrectly). Is there an easy fix for this? Thanks!

  • Ioannis Gman

    hello.im wondering..in detail view how can we share image and label in Facebook or twitter??
    that would be very handy

  • Adrienne Henry

    Hi! first off.. thanks for the tutorial! I was wondering though.. is there a way to make a second, third and so on detail view controller?

  • Roger

    @simonng:disqus hello , I can not get to work the image in the Detail View Controller, I have my images in a array ? I could pass everything else expect the image.

    Thank you

39 Flares Twitter 8 Facebook 28 Google+ 2 LinkedIn 1 39 Flares ×