Silver Challenge


#1

I got the silver challenge to work, my solution is listed below. However, before I “fixed” the “No more items” row so that it couldn’t be moved, I ran the program and tried re-ordering the rows. It worked fine until I tried to reorder the “No more items” row and then it crashed. I suspect it is because I have a TableView with one more row than my data source has arrays and when a data filled row is assigned an index number greater than the number in the array the program crashes, ie its not the “No more items” getting moved up but rather a data filled table occupying the last row. Does this make sense and is this correct?

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

@implementation ItemsViewController

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

    }
    return self;
    }

  • (UIView *)headerView
    {
    if (!headerView) {
    [[NSBundle mainBundle] loadNibNamed:@“HeaderView” owner:self options:nil];
    }
    return headerView;
    }

  • (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 arrayWithObject:ip]
    withRowAnimation:UITableViewRowAnimationTop];
    }

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

  • (CGFloat)tableView:(UITableView *)tv heightForHeaderInSection:(NSInteger)sec
    {
    return [[self headerView] bounds].size.height;
    }

  • (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
    {

    UITableViewCell *cell = [tableView dequeueReusableHeaderFooterViewWithIdentifier:@“UITableViewCell”];

    if (!cell) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@“UITableViewCell”];
    }

    if ([indexPath row] < [[[BNRItemStore sharedStore] allItems] count]) {
    BNRItem *p = [[[BNRItemStore sharedStore] allItems] objectAtIndex:[indexPath row]];
    [[cell textLabel] setText:[p description]];
    }
    else {
    [[cell textLabel] setText:@“No more items”];
    }

    return cell;
    }

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

  • (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];        
    

    }
    }

  • (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
    {
    if ([indexPath row] == [[[BNRItemStore sharedStore] allItems] count]) {
    return NO;

    }else
    {
    return YES;
    }
    }

  • (void)tableView:(UITableView *)tableView
    moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath
    toIndexPath:(NSIndexPath *)destinationIndexPath
    {

    [[BNRItemStore sharedStore] moveItemAtIndex:[sourceIndexPath row]
    toIndex:[destinationIndexPath row]];

}

@end[/code]


#2

Hey JK - I had the same experience with my silver solution - it was crashing because index was out of bounds until I disabled the row move beyond the “No More Items” row. I guess the reason is we’re adding one extra row in the view with

[code]

  • (NSInteger)tableView:(UITableView *)tableView
    numberOfRowsInSection:(NSInteger)section
    {
    return [[[BNRItemStore sharedStore] allItems] count] + 1;
    }[/code]
    but the model has one item less. So if you try to go beyond “No More Items” the tableView crashes because the data source is one item short…