Gold challenge


#1

Hello there,

I figured out a different approach than in the other topic here to solve the Gold challenge:
Similar to the HeaderView I created another XIB file containing a UIView and a UITableViewCell as it’s subview and implemented heightForFooterInSection:
and viewForFooterInSection: . It works well, this cell is unmovable and always at the bottom of the other cells, but it has a different Style compaired to the other Cells (It’s all white without rounded edges). How do I set this cell to the same style like the others?

Thanks in advance


#2

I am sorry to probably have found the least imaginative and most boring way of doing this challenge, just add this>

[code] numberOfRowsInSection:(NSInteger)section
{
return [[[BNRItemStore sharedStore] allItems] count] + 1;
}

  • (UITableViewCell*) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
    // First check if there is a cell that has gone off screen that can be reused

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

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

    // Fetch item

    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!”];
    [cell setUserInteractionEnabled:NO]; // <<<< HERE!
    }

    return cell;
    }[/code]

And then this:

-(NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath { if([[[BNRItemStore sharedStore] allItems] count] != [proposedDestinationIndexPath row]) { return proposedDestinationIndexPath; } else { return sourceIndexPath; } }

It is in the middle of the night and I was trying to figure out why my code wasn’t working so yes I ripped most of this from TheEskil, however the only problem with my code was that I was missing to add the +1 to the number of rows so the “No more Items!” wasn’t appearing. Anyway just remove user interaction from the button and voila finished.


#3

Hello everyone!

With the solution of benne90, when you enter editing mode you still see the reordering controls in the “No more items” row (If I am not wrong). So to avoid view these controls, I have put this row in a second section.

[code]- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
{
int numberOfRowsInSection;
switch (section) {
case 0:
numberOfRowsInSection = [[[BNRItemStore sharedStore] allItems] count];
break;
case 1:
numberOfRowsInSection = 1;
default:
break;
}
return numberOfRowsInSection;
}

  • (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
    {
    return 2;
    }[/code]

And I have implemented tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath, indicating which rows shows the reordering controls:

- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath { switch ([indexPath section]) { case 0: return YES; break; case 1: default: return NO; break; } }

So the implementation of tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath in my case is the following:

- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath { if ([sourceIndexPath section] == [proposedDestinationIndexPath section]) { return proposedDestinationIndexPath; } else { return sourceIndexPath; } }


#4

I took a slightly different approach. I modified the data source to support the notion of an extra item that’s not editable

BNRItemStore.h

- (BOOL)canEdit:(int) index;

BNRItemStore.m

- (id)init
{
    self = [super init];
    if(self) {
        allItems = [[NSMutableArray alloc] init];
        [allItems addObject:@"No more items!"];
    }
    return self;
}

- (BOOL) canEdit:(int)index
{
    if([allItems count] - 1 == index) {
        return NO;
    } else {
        return YES;
    }
}

I then implemented the methods canMoveRowAtIndexPath, canEditRowAtIndexPath, and targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath on the controller

ItemsViewController.m

- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath   
{
    return [[BNRItemStore sharedStore] canEdit:[indexPath row]];
}

- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
    return [[BNRItemStore sharedStore] canEdit:[indexPath row]];
}

- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath
{
    if ([[BNRItemStore sharedStore] canEdit:[proposedDestinationIndexPath row]] == YES) {
        return proposedDestinationIndexPath;
    } else {
        return sourceIndexPath;
    }
}

#5

I like these different solutions to the problems we’re seeing on these forums. Thanks to Big Nerd Ranch for having this place to interact with my fellow learners!

Initially I thought that the route that voutmaster took was “illegal” given the never alter the data source mantra, but the more that you think about it, in the “real world” it could be just as likely that an un-editable row could come from the data. E.g. a list of songs in your (not-on-device) music library, combined with those that are in your music library. The external songs may not be editable, the local ones could be.


#6

A slight variation on the above, to both remove the move control for the final fixed item, and to slot the moving item into the spot above the final item - IMO it looks a bit less visually jarring if the item settles into a spot close to the location to which the user dragged it.

-Andre

- (BOOL)tableView:(UITableView *)tableView
    canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
    if ([indexPath row] >= [[[BNRItemStore sharedStore] allItems] count]) {
        return NO;
    }
    return YES;
}

- (NSIndexPath *)tableView:(UITableView *)tableView
    targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath
       toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath
{
    NSUInteger lastIndex = [[[BNRItemStore sharedStore] allItems] count];
    if ([proposedDestinationIndexPath row] >= lastIndex) {
        return [NSIndexPath indexPathForRow:lastIndex-1
                                  inSection:[proposedDestinationIndexPath section]];
    }
    return proposedDestinationIndexPath;
}