1

I want to check if the user has an open basket if so send them to the menu if not then send send them to my open basket view but i m getting an error. So my question is how to get rid of this problem ? and is my logic right ?

  'NSInvalidArgumentException', reason: '-[Merchant merchantId]: unrecognized selector sent to instance 0x7fad19529490'.

i m using this method to check for open baskets when the button addToOrderButtonTapped is press in the menuview

    [[OrderManager sharedManager]getBasketsForMerchant:merchant success:^(NSArray *baskets) {
        for (Basket *basket in baskets){
            if ([basket.status isEqualToString:kBasketStatusOpen]) {
                [self.openBaskets addObject:basket];
            }
        }if (self.openBaskets.count > 0){
            self.openBaskets = self.openBaskets;
            dispatch_async(dispatch_get_main_queue(), ^{
                [self performSegueWithIdentifier:kSegueMenu sender:self];
            });
        }
        else {
            dispatch_async(dispatch_get_main_queue(), ^{
                [self performSegueWithIdentifier:KSegueOpenBasket sender:self];
            });
        }
    } failure:^(NSError *error, NSHTTPURLResponse *response) {
        dispatch_async(dispatch_get_main_queue(), ^{
            NSString *localizedString = NSLocalizedString(@"Order.ErrorLoadingOpenOrders", "Get error message");
            [self showMessage:localizedString withTitle:MessageTypeError];
            [MBProgressHUD hideAllHUDsForView:self.view animated:YES];
        });
    }];

The menuview

 //
 //  MenuItemViewController.m
 //  BaseApp
 //

  #import "MenuItemViewController.h"
  #import "RoundedButton.h"
  #import "MenuOptionCell.h"
  #import "MenuItem.h"
  #import "MenuOptionButton.h"
  #import "MenuChoice.h"
  #import "OrderManager.h"
  #import "TypeOfChoiceCell.h"
  #import "MenuOption.h"
  #import "OrderPricingTableViewCell.h"
  #import "RKManagedObjectStore.h"
  #import "NSManagedObjectContext+RKAdditions.h"
  #import "MerchantManager.h"
  #import "Merchant.h"
  #import "OrdersViewController.h"
  #import "MenuItem.h"
  #import "MenuViewController.h"
  #import "OrderConfirmationViewController.h"
  #import "OrderManager.h"
  #import "APIClient.h"
  #import "MenuManager.h"
  #import "DiscoverViewController.h"
  #import "DiscoverCollectionViewCell.h"
  #import "MerchantManager.h"
  #import "MenuViewController.h"
  #import "MenuManager.h"
  #import "MerchantDetailsViewController.h"
  #import "OpenOrdersViewController.h"

   typedef NS_ENUM(NSUInteger, MenuOptionsSection) {
MenuOptionsSectionRequired = 0,
MenuOptionsSectionOptional = 1
 };
 static NSString *const OpenBasketsSegue = @"OpenBaskets";
 static NSString *const kSegueMenu = @"ShowMenu";
 static NSString *const KSegueOpenBasket = @"OpenBaskets";
 @interface MenuItemViewController () <UITableViewDelegate,   UITableViewDataSource>

  @property (nonatomic, weak) IBOutlet UILabel *menuItemName;
  @property (nonatomic, weak) IBOutlet UILabel *quantityLabel;
  @property (nonatomic, weak) IBOutlet UILabel *menuItemPrice;
  @property (nonatomic, weak) IBOutlet UILabel *subTotalLabel;
  @property (nonatomic, weak) IBOutlet UITextView *menuItemDescription;
  @property (nonatomic, weak) IBOutlet RoundedButton *addToOrderButton;
  @property (nonatomic, weak) IBOutlet UITableView *tableView;
  @property (nonatomic, weak) IBOutlet UIView *cartView;
  @property (nonatomic, weak) IBOutlet UIButton *subtractButton;
  @property (nonatomic) NSDecimalNumber *temporarySubtotal;
  @property (nonatomic, strong) NSMutableArray<MenuOption *>  *requiredChoices;
  @property (nonatomic, strong) NSMutableArray<MenuOption *> *optionalChoices;
  @property (nonatomic, strong) NSMutableArray<NSMutableArray *>  *optionChoicesSection;
  @property (nonatomic, strong) NSMutableArray<NSDictionary *> *options;
  @property (nonatomic, strong) NSMutableArray <Basket *>*openBaskets;
  @property (nonatomic) BOOL launchViewFirstTime;

   @end

   @implementation MenuItemViewController


   #pragma - Lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title = @"Menu Item";
self.menuItemName.text = self.menuCategory.selectedBasketLine.menuItem.name;
self.menuItemPrice.text = [NSString stringWithFormat:@"%@", [Basket  formattedCurrencyStringForAmount:self.menuCategory.selectedBasketLine.menuItem.price]];
self.quantityLabel.text = self.menuCategory.selectedBasketLine.quantity.stringValue;
self.temporarySubtotal = [self calculateTemporarySubtotal:[OrderManager sharedManager].currentBasket.subtotal menuItemPrice:self.menuCategory.selectedBasketLine.menuItem.price];
[self setSubtotalText:self.temporarySubtotal];
self.menuItemDescription.text = self.menuCategory.selectedBasketLine.menuItem.menuItemDescription;
self.subtractButton.alpha = 0.65;
self.requiredChoices = [[NSMutableArray alloc] init];
self.optionalChoices = [[NSMutableArray alloc] init];
self.optionChoicesSection = [[NSMutableArray alloc] init];
self.options = [[NSMutableArray alloc] init];
[self initializeChoiceArrays];
self.tableView.delegate = self;
self.tableView.dataSource = self;
     }

   - (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.launchViewFirstTime = YES;
if (self.optionChoicesSection.count > 0) {
    [self.tableView reloadData];
      } else {
    self.tableView.hidden = YES;
      }
      }

    - (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
self.launchViewFirstTime = NO;
     }

    - (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
for (MenuOption *menuOption in self.requiredChoices) {
    [menuOption resetNumberOfChoicesSelected];
      }
for (MenuOption *menuOption in self.optionalChoices) {
    [menuOption resetNumberOfChoicesSelected];
      }
self.menuCategory = nil;
     }

    - (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
[self.menuItemDescription setContentOffset:CGPointZero animated:YES];
     }


   #pragma - IBActions
   - (IBAction)addButtonTapped:(id)sender {
NSInteger count = self.quantityLabel.text.integerValue;
count++;
if (count > 1) {
    self.subtractButton.alpha = 1;
}
NSDecimalNumber *newSubTotal = [self.temporarySubtotal decimalNumberByAdding:self.menuCategory.selectedBasketLine.menuItem.price];
[self modifyCurrentBasketSubtotal:newSubTotal quantity:count];
     }

   - (IBAction)subtractButtonTapped:(id)sender {
NSInteger count = self.quantityLabel.text.integerValue;
if (count > 1) {
    count--;
    NSDecimalNumber *newSubTotal = [self.temporarySubtotal decimalNumberBySubtracting:self.menuCategory.selectedBasketLine.menuItem.price];
    [self modifyCurrentBasketSubtotal:newSubTotal quantity:count];
    if (count == 1) {
        self.subtractButton.alpha = 0.65;
    }
    }
    }

   - (IBAction)addToOrderButtonTapped:(id)sender {
MenuOption *menuOption;
Merchant *merchant  = [[Merchant alloc]init];
// First check if there are any missing required options that have to be selected
if ((menuOption = [self checkMissingRequiredOptionsHaveBeenSelected])) {
    NSString *localizedString = NSLocalizedString(@"AddMenuItem.RequiredChoicesNotSelected", @"Get string for error");
    NSString *formattedString = [NSString stringWithFormat:localizedString, menuOption.name];
    [self showMessage:formattedString withTitle:MessageTypeError];
    return;
}
// Now check if the minimum and maximum choice seletion have been met for the menu options
if ((menuOption = [self validateMinMaxForMenuOptionsHaveBeenMet])) {
    NSString *localizedString = NSLocalizedString(@"AddMenuItem.MinMaxNotFulfilled", @"Get string for error");
    NSString *formattedString = [NSString stringWithFormat:localizedString, menuOption.name];
    [self showMessage:formattedString withTitle:MessageTypeError];
    return;
    }
// Add the menu item to the basket
     if (self.menuItemAddedBlock) {
    self.menuItemAddedBlock(self, self.menuCategory);
   // [self dismissViewControllerAnimated:YES completion:nil];

     //checking for open basket here 
    [[OrderManager sharedManager]getBasketsForMerchant:merchant success:^(NSArray *baskets) {
        for (Basket *basket in baskets){
            if ([basket.status isEqualToString:kBasketStatusOpen]) {
                [self.openBaskets addObject:basket];
            }
        }if (self.openBaskets.count > 0){
            self.openBaskets = self.openBaskets;
            dispatch_async(dispatch_get_main_queue(), ^{
                [self performSegueWithIdentifier:kSegueMenu sender:self];
            });
        }
        else {
            dispatch_async(dispatch_get_main_queue(), ^{
                [self performSegueWithIdentifier:KSegueOpenBasket sender:self];
            });
        }
    } failure:^(NSError *error, NSHTTPURLResponse *response) {
        dispatch_async(dispatch_get_main_queue(), ^{
            NSString *localizedString = NSLocalizedString(@"Order.ErrorLoadingOpenOrders", "Get error message");
            [self showMessage:localizedString withTitle:MessageTypeError];
            [MBProgressHUD hideAllHUDsForView:self.view animated:YES];
        });
    }];


     }
     }

   - (IBAction)cancelButtonTapped:(UIBarButtonItem *)sender {
[self dismissViewControllerAnimated:YES completion:nil];
     }


      #pragma - UITableViewDelegate, UITableViewDataSource
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return self.optionChoicesSection.count;
     }

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

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MenuOptionCell *cell = (MenuOptionCell *)[tableView dequeueReusableCellWithIdentifier:[MenuOptionCell reuseIdentifier]];
cell.menuOption = self.optionChoicesSection[indexPath.section][indexPath.row];
cell.menuOptionCellButtonPressedBlock = ^(MenuOptionButton *button, MenuOption *option, MenuChoice *choice) {
    [self adjustSelectedOptions:option choice:choice indexPath:indexPath];
};
cell.menuOptionCellDefaultOptionDetectedBlock = ^(MenuOptionButton *button, MenuOption *option, MenuChoice *choice) {
    [self adjustSelectedOptions:option choice:choice indexPath:indexPath];
     };
cell.menuOptionCellDeselectedBlock = ^(MenuOptionButton *button, MenuOption *option, MenuChoice *choice) {
    [self adjustSelectedOptions:option choice:choice indexPath:indexPath];
      };
[cell configureCell:self.launchViewFirstTime];
return cell;
     }

     - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
TypeOfChoiceCell *cell = (TypeOfChoiceCell *)[tableView dequeueReusableCellWithIdentifier:[TypeOfChoiceCell reuseIdentifier]];
switch ((MenuOptionsSection)section) {
    case MenuOptionsSectionRequired:
        if (self.requiredChoices.count > 0) {
            cell.title =  NSLocalizedString(@"AddMenuItem.RequiredChoiceText", @"Get string for title");
            return cell;
        } else if (self.optionalChoices.count > 0) {
            cell.title =  NSLocalizedString(@"AddMenuItem.OptionalChoiceText", @"get string for title");
            return cell;
        }
    case MenuOptionsSectionOptional:
        if (self.optionalChoices.count > 0) {
            cell.title =   NSLocalizedString(@"AddMenuItem.OptionalChoiceText", @"Get string for title");
            return cell;
        }
        }
return nil;
        }

    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
MenuOption *option = self.optionChoicesSection[indexPath.section][indexPath.row];
return [MenuOptionCell heightForMenuOption:option];
      }

    - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return [TypeOfChoiceCell height];
       }

    - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
return 0.01f;
        }


       #pragma - Helpers
    - (void)setSubtotalText:(NSDecimalNumber *)subtotal {
if (!subtotal) {
    self.subTotalLabel.text = NSLocalizedString(@"AddMenuItem.SubtotalDefault", @"Get string for subtotal");
} else {
    NSString *localizedString = NSLocalizedString(@"AddMenuItem.SubtotalFormatted", @"Get string for subtotal");
    self.subTotalLabel.text = [NSString stringWithFormat:localizedString, [Basket formattedCurrencyStringForAmount:subtotal]];
      }
      }

    - (void)modifyCurrentBasketSubtotal:(NSDecimalNumber *)subtotal quantity:(NSInteger)quantity {
self.menuCategory.selectedBasketLine.quantity = [NSNumber numberWithInteger:quantity];
self.menuCategory.selectedBasketLine.subtotal = subtotal;
self.temporarySubtotal = subtotal;
[self setSubtotalText:subtotal];
self.quantityLabel.text = self.menuCategory.selectedBasketLine.quantity.stringValue;
     }

    - (NSDecimalNumber *)calculateTemporarySubtotal:(NSDecimalNumber *)orderManagerSubTotal menuItemPrice:(NSDecimalNumber *)menuItemPrice {
if (orderManagerSubTotal == 0) {
    return menuItemPrice;
} else {
    return [orderManagerSubTotal decimalNumberByAdding:menuItemPrice];
      }
     }

     - (MenuOption *)checkMissingRequiredOptionsHaveBeenSelected {
for (MenuOption *menuOption in self.requiredChoices) {
    if (!menuOption.selected) {
        return menuOption;
    }
     }
return nil;
     }

    - (MenuOption *)validateMinMaxForMenuOptionsHaveBeenMet {
for (MenuOption *menuOption in self.requiredChoices) {
    if ([menuOption validateIndividualMinMaxForMenuOption]) {
        return menuOption;
    }
}
for (MenuOption *menuOption in self.optionalChoices) {
    if (menuOption.selected) {
        if ([menuOption validateIndividualMinMaxForMenuOption]) {
            return menuOption;
        }
        }
        }
     return nil;
         }

    - (void)initializeChoiceArrays {
NSArray<MenuOption *> *menuOptions = [self.menuCategory.selectedBasketLine.menuItem.menuOptions allObjects];
for (MenuOption *menuOption in menuOptions) {
    if (menuOption.minimumChoices == nil) {
        menuOption.minimumChoices = [NSNumber numberWithInt:0];
    }
    if (menuOption.maximumChoices == nil) {
        menuOption.maximumChoices = [NSNumber numberWithInt:0];
    }
    // For now make an optional choice required if minimumChoices > 0
    if (menuOption.isRequired || [menuOption.minimumChoices intValue] > 0) {
        menuOption.isRequired = YES;
        [self.requiredChoices addObject:menuOption];
     } else {
        [self.optionalChoices addObject:menuOption];
     }
     }
if (self.requiredChoices.count > 0) {
    [self.optionChoicesSection addObject:self.requiredChoices];
    }
 if (self.optionalChoices.count > 0) {
    [self.optionChoicesSection addObject:self.optionalChoices];
    }
    }

    - (void)adjustSelectedOptions:(MenuOption *)option choice:(MenuChoice *)choice indexPath:(NSIndexPath *)indexPath {
self.menuCategory.selectedBasketLine.subtotal = self.menuCategory.selectedBasketLine.menuItem.price;
if (option.selected && option.menuChoices.count == 0) {
    [self.options addObject:@{kOption: option.menuOptionId ?: @"", kChoice: @""}];
    if (option.price) {
        self.temporarySubtotal = [self.temporarySubtotal decimalNumberByAdding:option.price];
    }
    if (option.isRequired) {
        self.requiredChoices[indexPath.row].selected = option.selected;
        self.requiredChoices[indexPath.row].numberOfChoicesSelected = option.numberOfChoicesSelected;
    } else {
        self.optionalChoices[indexPath.row].selected = option.selected;
        self.optionalChoices[indexPath.row].numberOfChoicesSelected = option.numberOfChoicesSelected;
    }
    } else {
    if (option.menuChoices.count == 0) {
        [self.options removeObject:@{kOption: option.menuOptionId ?: @"", kChoice: @""}];
        if (option.price) {
            self.temporarySubtotal = [self.temporarySubtotal decimalNumberBySubtracting:option.price];
        }
        if (option.isRequired) {
            self.requiredChoices[indexPath.row].selected = option.selected;
            self.requiredChoices[indexPath.row].numberOfChoicesSelected = option.numberOfChoicesSelected;
        } else {
            self.optionalChoices[indexPath.row].selected = option.selected;
            self.optionalChoices[indexPath.row].numberOfChoicesSelected = option.numberOfChoicesSelected;
        }
        }
        }
if (choice.selected && option.menuChoices.count > 0) {
    [self.options addObject:@{kOption: choice.menuOption.menuOptionId ?: @"", kChoice: choice.menuChoiceId ?: @""}];
    if (choice.price) {
        self.temporarySubtotal = [self.temporarySubtotal decimalNumberByAdding:choice.price];
     }
    if (option.isRequired) {
        self.requiredChoices[indexPath.row].selected = choice.selected;
        self.requiredChoices[indexPath.row].numberOfChoicesSelected = option.numberOfChoicesSelected;
    } else {
        self.optionalChoices[indexPath.row].selected = choice.selected;
        self.optionalChoices[indexPath.row].numberOfChoicesSelected = option.numberOfChoicesSelected;
       }
    } else {
    if (option.menuChoices.count > 0) {
        [self.options removeObject:@{kOption: choice.menuOption.menuOptionId ?: @"", kChoice: choice.menuChoiceId ?: @""}];
        if (choice.price) {
            self.temporarySubtotal = [self.temporarySubtotal decimalNumberBySubtracting:choice.price];
        }
        if (option.isRequired) {
            if ([option.numberOfChoicesSelected intValue] == 0) {
               self.requiredChoices[indexPath.row].selected = option.selected;
            } else {
                self.requiredChoices[indexPath.row].selected = !choice.selected;
            }
            self.requiredChoices[indexPath.row].numberOfChoicesSelected = option.numberOfChoicesSelected;
        } else {
            self.optionalChoices[indexPath.row].selected = choice.selected;
            self.optionalChoices[indexPath.row].numberOfChoicesSelected = option.numberOfChoicesSelected;
        }
     }
    }
   [self setSubtotalText:self.temporarySubtotal];
self.menuCategory.selectedBasketLine.attributes = self.options;
    }

     @end

This is the line of code thats giving me the error

 + (void)getBasketsForMerchant:(Merchant *)merchant success:(void (^)(NSArray *basket))success failure:(void (^)(NSError *, NSHTTPURLResponse *))failure {
NSMutableDictionary* params = @{@"expand": @"merchant"}.mutableCopy;
if (merchant) {
   params[@"merchant"] = merchant.merchantId;
}
[[RKObjectManager sharedManager] getObjectsAtPath:kOrdersEndpoint parameters:params success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult){
    NSArray* items = mappingResult.array;
    if (success) {
    success(items);
    }
 } failure:^(RKObjectRequestOperation *operation, NSError *error) {
   if (failure) {
      failure(error, operation.HTTPRequestOperation.response);
   } else {
        _defaultFailureBlock(operation, error);
   }
 }];
 }
Lou Franco
  • 87,846
  • 14
  • 132
  • 192
  • 2
    There's too much code in your question, you should have only paste the concerned part... – AnthoPak Jun 20 '16 at 18:01
  • 1
    okay thanks i m going to edit it –  Jun 20 '16 at 18:07
  • Does the error you get cause a line to be highlighted within XCode's debugger? It would be useful to know which line triggers it since as @AnthoninC. mentions, there is a large amount of code for us to work through. If there's no line highlighted, try adding a breakpoint on all exceptions ala this method: [link](http://stackoverflow.com/a/29486686/4191758) – eager to learn Jun 20 '16 at 18:07
  • The only thing we need to figure it out is `Merchant.h` – Lou Franco Jun 20 '16 at 18:11
  • I assume the line that crashes is `params[@"merchant"] = merchant.merchantId;`, in which case I agree with @LouFranco that `Merchant.h` is what we need to see and something wrong with the `merchantId` property is the culprit. – eager to learn Jun 20 '16 at 18:27

1 Answers1

3

This error:

'NSInvalidArgumentException', reason: '-[Merchant merchantId]: unrecognized selector sent to instance 0x7fad19529490'.

Means that you have an object at location 0x7fad19529490 and you tried to call "merchantId" on it. That object does not respond to merchantId.

So, look very carefully at the definition of Merchant. Did you get the spelling of merchantId right in fieldMappings? Is it merchantID with a capital D?

If you are sure that merchant has a property named merchantId exactly, then, the next likely thing is that the object at 0x7fad19529490 is not a Merchant.

The easiest thing to do is to add an exception breakpoint (use the +) at the bottom of the breakpoint navigator. When this exception happens, grab the pointer address from the error (it might be different each time) and see what it is in the debugger. To do that, at the (lldb) prompt, type:

 po (NSObject*)(0x7fad19529490)

but use the address from the error. If it's a Merchant, I expect it to say something like:

<Merchant: 0x7fad19529490>

Or, if you have overridden description, it will be the output of that.

Lou Franco
  • 87,846
  • 14
  • 132
  • 192
  • 1
    If the object wasn't a `Merchant` then the exception reason would say whatever class the object actually was, not "Merchant" – dan Jun 20 '16 at 18:15
  • Okay i m trying it but yeah its merchantId. –  Jun 20 '16 at 18:15
  • so i just got this (lldb) po 0x7fd3c50b1500 (entity: ; id: (null) ; data: ) (entity: ; id: (null) ; data: ) –  Jun 20 '16 at 18:16
  • Please post Merchant.h -- this output implies there is an "id", not a "merchantId". Type `po ((Merchant *)(0x7fd3c50b1500)).merchantId` – Lou Franco Jun 20 '16 at 18:24
  • @ngomambaku: out of curiosity, what did the problem turn out to be? – Lou Franco Jun 21 '16 at 13:03