Silver Solution


#1

I am not sure if this is exactly what they had in mind for a solution, but it works well and uses very little code!

-(NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section
{
    if (section ==[tableView numberOfSections]-1) return @"No more items!";
    else return Nil;
}

#2

This is what I did. Also extremely simple:

- (NSArray *) allItems { [self.privateItems addObject:@"No More Items!"]; return self.privateItems; }


#3

Read a solution on stack overflow and I think it’s pretty good,
as it doesn’t matter how many objects you put in your store.

Everything is done in BNRItemsViewController.m

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

and

[code]- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Get a new or recycled cell
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell"
forIndexPath:indexPath];

// Set the tect 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]) {
    NSArray *items = [[BNRItemStore sharedStore] allItems];
    BNRItem *item = items[indexPath.row];
    
    cell.textLabel.text = [item description];
}else if (indexPath.row == [[[BNRItemStore sharedStore] allItems] count]){
    cell.textLabel.text = @"No more items!";
}

return cell;

}[/code]


#4

Here is very elegant solution I came up with.

In the BNRItemStore.m file I add one line of code to the initializer:

- (instancetype)initPrivate {
    if ( self = [super init] ) {
        _privateItems = [[NSMutableArray alloc] init];
        [_privateItems addObject:@"No more items!"]; //This particular line makes the UITableView display "No more items!" when you have an empty array of items. Very simple.
    }
    
    return self;
}

And then I modify one line of code in the createItem method, so it looks like this:

- (BNRItem *)createItem {
    BNRItem *item = [BNRItem randomItem];
    [[self privateItems] insertObject:item atIndex:[[self privateItems] count] - 1]; //Simple add of items before the last "No more items!" cell.

    return item;
}

Cheers,
Yarik


#5

[quote=“vincentsfong”]This is what I did. Also extremely simple:

- (NSArray *) allItems { [self.privateItems addObject:@"No More Items!"]; return self.privateItems; }[/quote]

Hi vincentsfong,

Your code will duplicate “No more items!” if we call this method more than once.

Cheers,
Yarik


#6

I took a VERY different and probably much more difficult approach to get the No more items! entry at the end of every section:

I added a new method to my BNRItemStore.h and implemented it like this in my BNRItemStore.m

[code]- (NSString *)createLastItem
{
NSString *lastItem;
if (self.privateItems) {
NSArray *theItems = [[BNRItemStore sharedStore] allItems];
NSInteger numberOfSections = [theItems count];
for (int i = 0; i < numberOfSections; i++) {
NSString *item = @“No more items!”;
[self.privateItems[i] addObject:item];
}
}

return lastItem;

}[/code]

And then edited my BNRItemsViewController.m

- (instancetype)init { // Call the superclass's designated intializer self = [super initWithStyle:UITableViewStyleGrouped]; if (self) { for (int i = 0; i < 5; i++) { [[BNRItemStore sharedStore] createItem]; } [[BNRItemStore sharedStore] createLastItem]; } return self; }


#7

I’ve been trying to use tableView:willDisplayCell:forRowAtIndexPath: and trying to make the row number of the index equal to the array count minus one. Can’t seem to get it to work though…


#8

@Falco08: Not sure exactly what you mean, but on my run through the book I found a pretty sophisticated solution to this challenge that gets reused in a chapter later on and I tried to re-create it on my second run through the book just now and came up with this, which I think might be what you are talking about?

Quite simple actually, first you need to make sure that the amount of rows per section displayed is the count of that section in the array you will be filling it with plus one, thusly:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { NSArray *theItems = [[BNRItemStore sharedStore] allItems]; NSArray *sectionItems = theItems[section]; NSInteger sum = [sectionItems count] +1; return sum; }

Then when filling it with the actual data, you run a check, and change the text on the very last row in each section with the text No more items!, the rest of it you leave as is:

[code]- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Create an instance of UITableViewCell, with default appearance
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell"
forIndexPath:indexPath];
NSArray *items = [[BNRItemStore sharedStore] allItems];
NSInteger sumOne = [items[0] count];
NSInteger sumTwo = [items[1] count];

if (indexPath.section == 0) {
    if (indexPath.row == sumOne) {
        cell.textLabel.text = @"No more items!";
    } else {
        BNRItem *item = items[indexPath.section][indexPath.row];
        cell.textLabel.text = [item description];
    }
}
if (indexPath.section == 1) {
    if (indexPath.row == sumTwo) {
        cell.textLabel.text = @"No more items!";
    } else {
        BNRItem *item = items[indexPath.section][indexPath.row];
        cell.textLabel.text = [item description];
    }
}

return cell;

}[/code]

I thought this was quite an elegant solution myself.
Hope i can help someone with it!


#9

[quote=“Arthurzwit”]Quite simple actually, first you need to make sure that the amount of rows per section displayed is the count of that section in the array you will be filling it with plus one, thusly:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { NSArray *theItems = [[BNRItemStore sharedStore] allItems]; NSArray *sectionItems = theItems[section]; NSInteger sum = [sectionItems count] +1; return sum; }
[/quote]

I’m wondering how sectionItems is being counted. Doesn’t the “section” parameter pass in either a 0 or a 1? How are the items in the sectionItems array being grouped?


#10

[quote=“catonkeyboardjsjsjsj”][quote=“Arthurzwit”]Quite simple actually, first you need to make sure that the amount of rows per section displayed is the count of that section in the array you will be filling it with plus one, thusly:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { NSArray *theItems = [[BNRItemStore sharedStore] allItems]; NSArray *sectionItems = theItems[section]; NSInteger sum = [sectionItems count] +1; return sum; }
[/quote]

I’m wondering how sectionItems is being counted. Doesn’t the “section” parameter pass in either a 0 or a 1? How are the items in the sectionItems array being grouped?[/quote]
It passes in all the objects in the section that the tableView is currently displaying. Keep in mind that section is a variable used in this specific tableView delegate method. Not entirely sure but I imagine that it is a number that’s passed, namely the number of the section we are currently “on”.
By passing the method set variable section you get all the items in every specific sub array that you set in your allItems array, which it then counts in the next line [sectionItems count].
I’m clearly not too goot at explaining myself haha. I hope I’m making sense.


#11

[quote=“Arthurzwit”]It passes in all the objects in the section that the tableView is currently displaying. Keep in mind that section is a variable used in this specific tableView delegate method. Not entirely sure but I imagine that it is a number that’s passed, namely the number of the section we are currently “on”.
By passing the method set variable section you get all the items in every specific sub array that you set in your allItems array, which it then counts in the next line [sectionItems count].
I’m clearly not too goot at explaining myself haha. I hope I’m making sense.[/quote]

You’re making perfect sense now! Thanks so much for following up. If it’s alright with you - could I take a look at your numberofSectionsInTableView: method? I’m trying to get a handle on how you’re determining whether or not one or two sections is necessary and how that plays into the other methods.


#12

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { NSArray *theItems = [[BNRItemStore sharedStore] allItems]; return [theItems count]; }

It simply counts the amount of array’s in your allItems array.


#13

[quote=“Arthurzwit”]- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { NSArray *theItems = [[BNRItemStore sharedStore] allItems]; return [theItems count]; }

It simply counts the amount of array’s in your allItems array.[/quote]

This is really helpful. Thanks so much! I’ve actually refactored my solution quite a bit and it now evaluates properly whether the allItems array is empty, has only one array, or has both arrays. The “No more items!” cell ONLY appears in the last row of the last section, even if there are no arrays in allItems. I couldn’t have finished this challenge without your help - thanks again, I very much appreciate it.