B/S/G Challenges: works on Simulator but not on iPhone


#1

Hello all,

For the life of me, I could have sworn I had successfully completed the challenge, as everything works as intended on my iOS Simulator (6.1) but when I try running it on my iPhone, it crashes with error code EXC_BAD_ACCESS (code=EXC_ARM_DA_ALIGN…) in the line

in addNewItem: in ItemsViewController.m

Can anyone think of any reason why it would crash on my phone but work completely without error on my iOS simulator? I’ve tried the standard tricks – doing a Clean, deleting the app on my phone and rebuilding, etc. Same thing every time.

The full code for ItemsViewController.m is as follows:

[code]#import “ItemsViewController.h”
#import “BNRItemStore.h”
#import “BNRItem.h”

@implementation ItemsViewController

  • (id)init {
    self = [super initWithStyle:UITableViewStyleGrouped];
    if (self) {
    }

    return self;
    }

  • (id)initWithStyle:(UITableViewStyle)style {
    return [self init];
    }

  • (NSInteger)tableView:(UITableView *)tableView
    numberOfRowsInSection:(NSInteger)section {
    return [[[BNRItemStore sharedStore] allItems] count] + 1;
    }

  • (UITableViewCell *)tableView:(UITableView *)tableView
    cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    // Check for a reusable cell first, use that if it exists
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@“UITableViewCell”];

    // If there is no reusable cell of this type, create a new one
    if (!cell) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
    reuseIdentifier:@“UITableViewCell”];
    }

    // Set the text on the cell with the description of the item
    // that is at the nth index of items, where n = row this cell
    // will appear in on the tableview
    if ([indexPath row] == [[[BNRItemStore sharedStore] allItems] count]) {
    [[cell textLabel] setText:@“No more items!”];
    } else {
    BNRItem *p = [[[BNRItemStore sharedStore] allItems] objectAtIndex:[indexPath row]];

      [[cell textLabel] setText:[p description]];
    

    }

    return cell;
    }

  • (UIView *)headerView {
    // If we haven’t loaded the headerView yet…
    if (!headerView) {
    // Load HeaderView.xib
    [[NSBundle mainBundle] loadNibNamed:@“HeaderView” owner:self options:nil];
    }

    return headerView;
    }

  • (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    return [self headerView];
    }

  • (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
    // The height of the header view should be determined from the height of the view in the XIB file
    return [[self headerView] bounds].size.height;
    }

  • (IBAction)toggleEditingMode:(id)sender {
    if ([self isEditing]) {
    [sender setTitle:@“Edit” forState:UIControlStateNormal];
    [self setEditing:NO animated:YES];
    } else {
    [sender setTitle:@“Done” forState:UIControlStateNormal];
    [self setEditing:YES animated:YES];
    }
    }

  • (IBAction)addNewItem:(id)sender {
    BNRItem *newItem = [[BNRItemStore sharedStore] createItem];
    int lastRow = [[[BNRItemStore sharedStore] allItems] indexOfObject:newItem];

    NSIndexPath *ip = [NSIndexPath indexPathForRow:lastRow inSection:0];

    [[self tableView] insertRowsAtIndexPaths:[NSArray arrayWithObjects:ip] withRowAnimation:UITableViewRowAnimationTop];
    }

  • (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (editingStyle == UITableViewCellEditingStyleDelete) {
    BNRItemStore *ps = [BNRItemStore sharedStore];
    NSArray *items = [ps allItems];
    BNRItem *p = [items objectAtIndex:[indexPath row]];
    [ps removeItem:p];

      [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
    

    }
    }

  • (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath
    toIndexPath:(NSIndexPath *)destinationIndexPath {
    [[BNRItemStore sharedStore] moveItemAtIndex:[sourceIndexPath row] toIndex:[destinationIndexPath row]];
    }

  • (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath {
    return @“Remove”;
    }

  • (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
    return ([indexPath row] != [[[BNRItemStore sharedStore] allItems] count]);
    }

  • (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
    if ([indexPath row] == [[[BNRItemStore sharedStore] allItems] count]) {
    return UITableViewCellEditingStyleNone;
    } else {
    return UITableViewCellEditingStyleDelete;
    }
    }

  • (NSIndexPath *)tableView:(UITableView *)tableView
    targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath
    toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath {

    if ([sourceIndexPath row] == [[[BNRItemStore sharedStore] allItems] count]) {
    return sourceIndexPath;
    } else if ([proposedDestinationIndexPath row] == [[[BNRItemStore sharedStore] allItems] count]) {
    return sourceIndexPath;
    } else {
    return proposedDestinationIndexPath;
    }

}

@end[/code]

Thanks to any and all who can help.


#2

You used arrayWithObjects instead of the singular arrayWithObject. The compiler is expecting “nil” after your last argument if you use arrayWithObjects.

Interestingly, the simulator lets you get away with it although you should’ve received this compiler warning: http://msmvps.com/blogs/kevinmcneish/archive/2012/06/15/understanding-ios-compiler-warnings-missing-sentinel-in-method-dispatch.aspx


#3

I confess, I completely missed that. Getting used to a new IDE, but that’s no excuse, I know…

Thanks for the heads up!