Bronze/Silver Challenge Solution


#1

Ok I’ve completed the bronze and silver challenges, care to critique my work?

All this code is from my ItemsViewController.m, but I’m going to break it up to explain my thinking, so you can let me know if I’m on the right track.

#import "ItemsViewController.h"
#import "BNRItemStore.h"
#import "BNRItem.h"

@implementation ItemsViewController

#define UNDER50_SECTION 0
#define OVER50_SECTION 1

I decided to put the section indexes into constants (is a #define considered a constant in C/ObjC?). This way it’s a ton more readable, as you’ll see in my tableView:titleForHeaderInSection:. Is this a best practice, or at least a good practice?

init methods removed
#pragma mark UITableView Datasource methods

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
  return 2;
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
  NSString *title = nil;
  
  switch (section) {
    case UNDER50_SECTION:
      title = @"Items Under $50";
      break;
      
    case OVER50_SECTION:
      title = @"Items Over $50";
      break;

    default:
      break;
  }
  
  return title;
}

I found this fantastic little tidbit (assuming I’m using them right that is…), using #pragma mark in your code will create separators in the “method dropdown”. If you look at the top of your editor view, there are breadcrumbs pointing to your current file. It’ll say (in this chapter) Homepwner > Homepwner > ItemsViewController.m > (the method your in). If you click (the method your in) you’ll see a dropdown of the methods, constants, etc. Using pragma mark will put bold separators between the methods you put the pragma between. Use #pragma mark - for a regular line separator.

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
  switch (section) {
    case UNDER50_SECTION:
      return [[[BNRItemStore sharedStore] itemsUnder50] count] + 1;
      break;
      
    case OVER50_SECTION:
      return [[[BNRItemStore sharedStore] itemsOver50] count] + 1;
      break;
      
    default:
      return 0;
      break;
  }
}
- (UITableViewCell *)tableView:(UITableView *)tableView 
         cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
  BNRItemStore *sharedStore = [BNRItemStore sharedStore];
  NSString *label = @"";
  
  // 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"];
  }
  
  if ([indexPath section] == UNDER50_SECTION) {
    if ([indexPath row] < [[sharedStore itemsUnder50] count]) {
      BNRItem *p = [[sharedStore itemsUnder50] objectAtIndex:[indexPath row]];
      label = [p description];
    } else {
      label = @"No More Items";
    }
  } else {
    if ([indexPath row] < [[sharedStore itemsOver50] count]) {
      BNRItem *p = [[sharedStore itemsOver50] objectAtIndex:[indexPath row]];
      label = [p description];
    } else {
      label = @"No More Items";
    }
  }
  
  [[cell textLabel] setText:label];
  return cell;
}

@end

In tableView:cellForRowAtIndexPath: I decided to store sharedStore in a variable, as well as a label string. In web development, I know that duplication is evil if it can be avoided (which is almost always). I assume DRY code is a good practice for C/ObjC as well? Is there anything wrong with the way I used sharedStore or label?

Well… how’s it look?


#2

Well I like the look of it - still working on my solution. Your #pragma note was good. As an extra if you declare the pragma marks like this:

ie

Then the hyphens put line breaks in the drop down menu in XCode