Challenges: implemented as a dynamic array of array


#1

Bronze Challenge :
The new data type was created in the BNRItemStore class to keep with the same style. All the methods included are meant to replace their respective methods, but can safely coexist with other methods already in place. Sections dealing with allItems can be placed into their respective method to continue old functionality.

BNRItemStore.h

[code]@interface BNRItemStore : NSObject
{
// bronze challenge specific data structures, will hold an array of an array, first index will be section, second index will be the actual items stored in each section.
// section 0 will be “> $50” and section 1 will be "<= $50"
NSMutableArray *allItemsBronze;
int numberSectionsBronze;
}

  • (NSArray *)allItemsBronze:(NSInteger)section;
  • (int)numberSectionsBronze;
    [/code]
    BNRItemStore.m
- (id)init
{
    numberSectionsBronze = 2;
    self = [super init];
    if (self) {
        allItemsBronze = [[NSMutableArray alloc] init];
        for (int i = 0; i < numberSectionsBronze; i++)
        {
            [allItemsBronze addObject:[[NSMutableArray alloc] init]];
        }
    }
    return self;
}
- (BNRItem *)createItem
{
    BNRItem *p = [BNRItem randomItem];
    // ******* Bronze Challenge ******
    // reminder arrays start at 0 index
    // section 0 will be "> $50" and section 1 will be "<= $50"
   if ([p valueInDollars] > 50 ){
        [[allItemsBronze objectAtIndex:0] addObject:p];
    }
    else {
        [[allItemsBronze objectAtIndex:1] addObject:p];
    }
    return p;
}
- (NSArray *)allItemsBronze:(NSInteger)section{
    // doing a type casting with no check for negative number or numbers that are too large
    return [allItemsBronze objectAtIndex:(NSUInteger)section];
}
- (int)numberSectionsBronze{
    return numberSectionsBronze;
}

Flow of BNRItemStore.m

  • init initializes allItemsBronze into an array of an array
  • createItem evaluates the random item generated and places the item in allItemsBronze at array index 0 or array index 1
  • allItemsBronze now returns the subarray based upon the section value provided instead of the always returning the upper level array

ItemsViewController.m

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [[[BNRItemStore sharedStore] allItemsBronze:section] count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell"];
    NSLog(@"finished dequeue");
    if (!cell) {
        cell = [[UITableViewCell alloc]
                    initWithStyle:UITableViewCellStyleDefault
                    reuseIdentifier:@"UITableViewCell"];
    }

    BNRItem *p = [[[BNRItemStore sharedStore] allItemsBronze:[indexPath section]] objectAtIndex:[indexPath row]];
    [[cell textLabel] setText:[p description]];
    
    return cell;
}

// additional methods from UITableVIewDataSource needed to complete bronze challenge
// will define section section 0 as  "> $50" and section 1 as "<= $50"
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return [[BNRItemStore sharedStore] numberSectionsBronze];
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
    return [NSArray arrayWithObjects:@">$50",@"<=$50",nil];
}

Flow of ItemViewController.m

  • tableView:numberOfRowsInSection now returns the count of the array elements based upon the section parameter passed.
  • tableView:cellForRowAtIndexPath the BNRItem obtained by the pointer p now utilizes allItemsBronze:objectAtIndex instead which will pull the values correctly
  • numberOfSectionsInTableView implemented as required

Major issues encountered during implementation

  • arrays start at 0 index.
  • the number of sections value is expected to start at 1.
  • dynamically created arrays are pretty cumbersome to access.

#2

Silver Challenge: quick and dirty

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

  • (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@“UITableViewCell”];
    if (!cell) {
    cell = [[UITableViewCell alloc]
    initWithStyle:UITableViewCellStyleDefault
    reuseIdentifier:@“UITableViewCell”];
    }

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

    return cell;
    }
    [/code]

  • not a good way of implementing the requirements because it “falsifies” the information. This essentially tells the program that there is 1 more array item than there truly is and then catches for that while creating more cells and skips the array out of bounds call and instead places in the text for No more items in the cell created. If anything else in the program tracks for this information, then this could cause problems that would be hard to trace.

Silver Challenge proper implementation
BNRItemStore.m

[code]- (BNRItem *)createItem
{
BNRItem *p = [BNRItem randomItem];
[allItems addObject:p];

if ([p valueInDollars] > 50 ){
    [[allItemsBronze objectAtIndex:0] insertObject:p atIndex:[[allItemsBronze objectAtIndex:0] count]-1];
}
else {
    [[allItemsBronze objectAtIndex:1] insertObject:p atIndex:[[allItemsBronze objectAtIndex:1] count]-1];
}
return p;

}
[/code]

  • inserts the object in front of the last object in the appropriate array.

BNRItem.m

- (NSString *)description { NSString *descriptionString; if ([itemName isEqualToString:@"No more items!"]){ descriptionString = [[NSString alloc] initWithFormat:@"No more items!"]; } else { descriptionString = [[NSString alloc] initWithFormat:@"%@ (%@): Worth $%d, recorded on %@", itemName, serialNumber, valueInDollars, dateCreated]; } return descriptionString; }

  • description is changed so that it only outputs “No more items” if that is the string (removes the value in dollars, serial number, and date created)

#3

ItemsViewController.m

[code]- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@“UITableViewCell”];
if (!cell) {
cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:@“UITableViewCell”];
}

BNRItem *p = [[[BNRItemStore sharedStore] allItemsBronze:[indexPath section]] objectAtIndex:[indexPath row]];

if ([[p description] isEqualToString:@"No more items!"])
{
    [[cell textLabel] setFont:[UIFont boldSystemFontOfSize:15]];
    
} else
{
    [[cell textLabel] setFont:[UIFont boldSystemFontOfSize:20]];
}
[[cell textLabel] setText:[p description]];


return cell;

}

  • (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    {
    if ([[[BNRItemStore sharedStore] allItemsBronze:[indexPath section]] count]-1 == [indexPath row])
    {
    return 44.0;
    } else
    {
    return 60.0;
    }
    }

  • (void)viewDidLoad{
    NSLog(@“viewdidload called”);
    [[self tableView] setBackgroundView:[[UIImageView alloc] initWithImage:[UIImage imageNamed:@“joeeye.jpg”]]];
    }

[/code]
Flow of ItemViewController.m

  • tableView makes the assumption that the last item in the array will always have the description “No more items!” and will change the font based upon that.
  • tableView:heightForRowAtIndexPath needs to be implemented if the rows will be of different heights, it tests the cell based upon the value in indexPath to see if it is the last item in the row of that section.
  • viewDidLoad will set the background view for the tableView to the image “joeeye.jpg”. I don’t have proper images of the correct sizes to implement for retina and non retina display, however from what I recall, it’s just an issue of putting two view files into the project such the regular image is labeled as “background.jpg” and the retina version is labeled as “background@2x.jpg”

Major issues encountered

  • rowHeight property of UITableView doesn’t allow itself to be reset when I placed it in the control block that tests for the last item in the array.
  • needed to set the font height specifically for the last item in the array in order for large sized arrays to work properly when scrolling.