Chapter 9 Solutions - Bronze / Silver / Gold Challenges w/Ou



[size=135]Bronze Challenge: Renaming the Delete Button to REMOVE[/size]

Used this delegate method in the UITableViewController to rename the Delete button to Remove



  • (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath {

    return @“Remove”;

[size=135]Silver Challenge: Add a last row “No more Items!” / persistent / cannot be edited, moved, or reordered[/size]

1.- I created the “No more Items!” row within the private initializer for the ItemStore singleton. this way the row is displayed upon launch when the tableview asks its datasource for its rows.


[code]- (instancetype)initPrivate {
self = [super init];
if (self) {
_privateItems = [[NSMutableArray alloc] init];

    /// adding a last row of 'no more items!' during initialization
    [self.privateItems addObject:@"No more items!"];

return self;


2.- Modified the createItem method in the ItemStore so that the “No more Items!” row is always displayed last. Any newly added items are always inserted BEFORE the last “no more items” row.


[code]- (ZGCItem *)createItem {

ZGCItem *item = [ZGCItem randomItem];

// making it so new items are created before the last 'no more items row'
// (using insert with index count - 1 index to keep the last row last)
[self.privateItems insertObject:item atIndex:self.privateItems.count - 1];

// Logging array with index numbers everytime an item is added, used during challenge...
for (ZGCItem *i in self.privateItems) {
    NSLog(@"%lu: %@", (unsigned long)[self.privateItems indexOfObject:i], i);

return item;


3.- I Used this datasource method to prevent the last row “no more items!” from being removed Or moved


  • (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {

    BOOL isEditable = YES;
    NSUInteger count = [[[ZGCItemStore sharedStore] allItems] count];

    if (indexPath.row == count - 1) {
    isEditable = NO;

    return isEditable;

[size=135]Gold Challenge: Really prevent reordering - preventing other rows from getting dragged underneath last ‘No More items’ row[/size]

I Used this delegate method in the UItableViewController. If proposed destination row equals our last row index, return an index path = to the sourceIndexpath so the row returns to its original position, else, allow the row to move by returning the proposed destination row.


[code]- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath {

NSArray *items = [[ZGCItemStore sharedStore] allItems];

// Define max row index (-1 since it's 0 based index)
NSInteger maxRow = items.count - 1;

// returns to its original position, else, allow the row to move by the returning the desired destination row.
if (proposedDestinationIndexPath.row == maxRow) {
    NSLog(@"Destionation Row: %ld - not allosed", proposedDestinationIndexPath.row);
    return sourceIndexPath;

return proposedDestinationIndexPath;