Reputation: 61
I've been following this tutorial online http://www.raywenderlich.com/50310/storyboards-tutorial-in-ios-7-part-2 in combination with trying to implement collection views and have run into a problem I can't seem to solve.
My app lists recipes from an array in a collection view and when you click on the Add button will segue to a table view controller in order to add a new recipe to that array.
I want to be able to click the Done button in order to go back to the previous screen and list all recipes within the collection view but am receiving an unrecognised selector set to instance error on the didAddRecipe method. I was hoping someone might be able to please lend me a hand.
Please also ignore my poorly written code. I'm still learning.
Edit: Whoops, should have included the specific error. I'm new to the debugger but as far as I can tell, its failing on the Done action within AddRecipeViewController.m, specifically the didAddRecipe.
- (IBAction)done:(id)sender
{
BeerRecipe *recipe = [[BeerRecipe alloc]init];
recipe.name = self.recipeName.text;
[self.delegate AddRecipeViewController:self didAddRecipe:recipe];
}
The error from the log give me:
[RecipesViewController AddRecipeViewController:didAddRecipe:]: unrecognized selector sent to instance 0x8e72b40
BeerRecipe.h
#import <Foundation/Foundation.h>
@interface BeerRecipe : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *beerstyle;
@property (nonatomic, copy) NSString *beertype;
@property (nonatomic, copy) NSString *parentRecipe;
@property (nonatomic, assign) NSInteger ibu;
@property (nonatomic, assign) double og;
@property (nonatomic, assign) double fg;
@property (nonatomic, assign) NSInteger timesBrewed;
@property (nonatomic, assign) NSDate *dateCreated;
@end
BeerRecipe.m
#import "BeerRecipe.h"
@implementation BeerRecipe
@end
RecipesViewController.h
#import <UIKit/UIKit.h>
#import "AddRecipeViewController.h"
@interface RecipesViewController : UIViewController <UICollectionViewDelegate, UICollectionViewDataSource, AddRecipeViewControllerDelegate>
@property (weak, nonatomic) IBOutlet UIImageView *beer_image;
@property (nonatomic, strong) NSMutableArray *recipes;
@end
RecipesViewController.m
#import "RecipesViewController.h"
#import "BeerRecipe.h"
#import "AddRecipeViewController.h"
@interface RecipesViewController ()
@end
@implementation RecipesViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma marks Collection Methods->
-(NSInteger) numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 1;
}
-(NSInteger) collectionView:(UICollectionView *) collectionView numberOfItemsInSection:(NSInteger)section {
return [self.recipes count];
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];
UILabel *beernamelabel = (UILabel *) [cell viewWithTag:1];
UILabel *beerstylelabel = (UILabel *) [cell viewWithTag:2];
//UILabel *creationdatelabel = (UILabel *) [cell viewWithTag:3];
UILabel *timesbrewedlabel = (UILabel *) [cell viewWithTag:4];
UILabel *parentrecipelabel = (UILabel *) [cell viewWithTag:5];
UILabel *beertypelabel = (UILabel *) [cell viewWithTag:6];
UILabel *oglabel = (UILabel *) [cell viewWithTag:7];
UILabel *fglabel = (UILabel *) [cell viewWithTag:8];
UILabel *ibulabel = (UILabel *) [cell viewWithTag:9];
BeerRecipe *recipe = (self.recipes)[indexPath.row];
beernamelabel.text = recipe.name;
beerstylelabel.text = recipe.beerstyle;
//creationdatelabel.text = recipe.dateCreated;
beertypelabel.text = recipe.beertype;
timesbrewedlabel.text = [NSString stringWithFormat:@"%d", recipe.timesBrewed];
parentrecipelabel.text = recipe.parentRecipe;
oglabel.text = [NSString stringWithFormat:@"%.3lf", recipe.og];
fglabel.text = [NSString stringWithFormat:@"%.3lf", recipe.fg];
ibulabel.text = [NSString stringWithFormat:@"%d", recipe.ibu];
return cell;
}
- (void)addRecipeViewController:(AddRecipeViewController *)controller didAddRecipe:(BeerRecipe *)recipe
{
[self.recipes addObject:recipe];
}
#pragma mark - AddRecipeViewControllerDelegate
- (void)AddRecipeViewControllerDidCancel:(AddRecipeViewController *)controller
{
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)AddRecipeViewControllerDidSave:(AddRecipeViewController *)controller
{
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:@"AddRecipe"]) {
UINavigationController *navigationController = segue.destinationViewController;
AddRecipeViewController *addRecipeViewController = [navigationController viewControllers][0];
addRecipeViewController.delegate = self;
}
}
AddRecipeViewController.h
#import <UIKit/UIKit.h>
#import "BeerRecipe.h"
@class AddRecipeViewController;
@protocol AddRecipeViewControllerDelegate <NSObject>
- (void)AddRecipeViewControllerDidCancel:(AddRecipeViewController *)controller;
- (void)AddRecipeViewController:(AddRecipeViewController *)controller didAddRecipe:(BeerRecipe *)recipe;
@end
@interface AddRecipeViewController : UITableViewController
@property (weak, nonatomic) IBOutlet UITextField *recipeName;
@property (weak, nonatomic) IBOutlet UISegmentedControl *shareRecipe;
@property (weak, nonatomic) IBOutlet UILabel *styleLabel;
@property (nonatomic, weak) id <AddRecipeViewControllerDelegate> delegate;
- (IBAction)cancel:(id)sender;
- (IBAction)done:(id)sender;
@end
AddRecipeViewController.m
#import "AddRecipeViewController.h"
#import "BeerRecipe.h"
#import "RecipesViewController.h"
@interface AddRecipeViewController ()
@end
@implementation AddRecipeViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (IBAction)cancel:(id)sender
{
[self.delegate AddRecipeViewControllerDidCancel:self];
}
- (IBAction)done:(id)sender
{
BeerRecipe *recipe = [[BeerRecipe alloc]init];
recipe.name = self.recipeName.text;
[self.delegate AddRecipeViewController:self didAddRecipe:recipe];
}
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 0) {
[self.recipeName becomeFirstResponder];
}
}
@end
CGAppDelegate.h
#import <UIKit/UIKit.h>
@interface CGAppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end
CGAppDelegate.m
#import "CGAppDelegate.h"
#import "BeerRecipe.h"
#import "RecipesViewController.h"
@implementation CGAppDelegate {
NSMutableArray *_recipes;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//_recipes = [[NSMutableArray alloc] init];
_recipes = [NSMutableArray arrayWithCapacity:20];
BeerRecipe *recipe = [[BeerRecipe alloc] init];
recipe.name = @"Sierra Nevada Clone v1";
recipe.beerstyle = @"American Pale Ale";
recipe.beertype = @"All Grain";
recipe.dateCreated = [NSDate date];
recipe.ibu = 60;
recipe.og = 1.012;
recipe.fg = 1.006;
recipe.timesBrewed = 0;
recipe.parentRecipe = @"Nil";
[_recipes addObject:recipe];
recipe = [[BeerRecipe alloc] init];
recipe.name = @"Celebration Ale";
recipe.beerstyle = @"American IPA";
recipe.beertype = @"All Grain";
recipe.dateCreated = [NSDate date];
recipe.ibu = 60;
recipe.og = 1.012;
recipe.fg = 1.006;
recipe.timesBrewed = 0;
recipe.parentRecipe = @"Nil";
[_recipes addObject:recipe];
UITabBarController *tabBarController = (UITabBarController *)self.window.rootViewController;
UINavigationController *navigationController = [tabBarController viewControllers][1];
RecipesViewController *recipesViewController = [navigationController viewControllers][0];
recipesViewController.recipes = _recipes;
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application
{
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
- (void)applicationWillTerminate:(UIApplication *)application
{
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
@end
Upvotes: 0
Views: 5501
Reputation: 14304
First of all, to prevent from crashing it is best practice to wrap calls on your delegates with:
if ([self.delegate respondsToSelector:@selector(AddRecipeViewController:didAddRecipe:)])
{
[self.delegate AddRecipeViewController:self didAddRecipe:recipe];
}
else
{
NSLog(@"Warning - delegate method not called");
}
Now to fix your problem - You're calling the method AddRecipeViewController:didAddRecipe:
when you should be calling addRecipeViewController:didAddRecipe:
(lowercase) - Method names are case sensitive and it is according to convention to always start them off with lowercase letters.
Upvotes: 2