Gold Challenge


#1

Hey,

This is my solution to the Gold Challenge, just posting to see if I have done anything wrong or any areas to improve on? (I have left my comments in)

Also I do have one question: In my method valueInDollarsOfAllItemsInContainer in BNRContainer.m I go through each object and check what class it is and run the corresponding method is this the best way to deal with an array with different object types?

main.m

#import <Foundation/Foundation.h>
#import "BNRItem.h"
#import "BNRContainer.h"

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        
        // Create a mutable array object, store its address in items variable
        NSMutableArray *items = [[NSMutableArray alloc] init];
  
        ////   1 Manually creating the insance variables needed to create the object BNRItem    ////
        
//        // Send the message addObject: to the NSMutableArray pointed to
//        // by the variable items, passing a string each time
//        [items addObject:@"One"];
//        [items addObject:@"Two"];
//        [items addObject:@"Three"];
//        
//        // Send another message, insertObject:atIndex:, to that same array object
//        [items insertObject:@"Zero" atIndex:0];
//        
//        // For every item in the array as determind by sending count to items
//        for (int i = 0; i < [items count]; i++){
//            // We get the ith object from the array and pass it as an argument to
//            // NSLog, which implicitly sends the  description message to that object
//            NSLog(@"%@", [items objectAtIndex:i]);
//        }
//        
//        BNRItem *p = [[BNRItem alloc] init];
//        
//        NSLog(@"%@", p);
//        
//        // This creates a new NSString, "Red Sofa" and gives it to the BNRItem
//        [p setItemName:@"Red Sofa"];
//        
//        // This creates a new NSString, "A1B2C" and gives it to the BNRItem
//        [p setSerialNumber:@"A1B2C"];
//        
//        // We send the value 100 to be used as the valueInDollars of this BNRItem
//        [p setValueInDollars:100];
     
        ////   2 Using initializer to create object     ////
        
//        BNRItem *p = [[BNRItem alloc] initWithItemName:@"Red Sofa"
//                                        valueInDollars:100
//                                          serialNumber:@"A1B2C"];
//        
//        //Remember, NSLog sent with %@ as the token will print the
//        // description of the corresponding argument
//        NSLog(@"%@", p);
        
        ////    3 Using a class method to create multipul random instance variable values    ////
        
        for (int i = 0; i < 10; i++) {
            BNRItem *p = [BNRItem randomItem];
            [items addObject:p];
        }
        
        //*** BRONZE CHALLENGE *** - Add a bug to find the 11th item and note the exception.
        // 2013-01-14 23:35:07.806 RandomPossessions[77432:303] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 11 beyond bounds [0 .. 9]'
        //NSLog(@"%@", [items objectAtIndex:11]);

        // Old Enumeration
//        for (int i = 0; i < [items count]; i++) {
//            NSLog(@"%@", [items objectAtIndex:i]);
//        }
        
        BNRContainer *q = [[BNRContainer alloc] initWithItemName:@"CONTAINER 1" valueInDollars:99 serialNumber:@"C1" subItems:items];
        
        [items addObject:q];
        
        BNRContainer *r = [[BNRContainer alloc] initWithItemName:@"CONTAINER 2" valueInDollars:10 serialNumber:@"C2" subItems:items];
        
        NSLog(@"%@", r);
        
        // Fast Enumeration
//        for (BNRItem *item in items) {
//            NSLog(@"%@", item);
//        }
        
        
        // Destroy the array pointed to by items
        items = nil;
    }
    return 0;
}

BNRItem.h

[code]#import <Foundation/Foundation.h>

@interface BNRItem : NSObject
{
NSString *itemName;
NSString *serialNumber;
int valueInDollars;
NSDate *dateCreated;
}

  • (id)randomItem;
  • (id)initWithItemName:(NSString *)name
    valueInDollars:(int)value
    serialNumber:(NSString *)sNumber;

  • (id)initWithItemName:(NSString *)name
    serialNumber:(NSString *)sNumber;

  • (void)setItemName:(NSString *)str;

  • (NSString *)itemName;

  • (void)setSerialNumber:(NSString *)str;

  • (NSString *)serialNumber;

  • (void)setValueInDollars:(int)i;

  • (int)valueInDollars;

  • (NSDate *)dateCreated;

@end
[/code]

BNRItem.m

#import "BNRItem.h"

@implementation BNRItem

+(id)randomItem
{
    // Create an array of three adjectives
    NSArray *randomAdjectiveList = [NSArray arrayWithObjects:@"Fluffy", @"Rusty", @"Shiny", nil];
    
    // Create an array of three nouns
    NSArray *randomNounList = [NSArray arrayWithObjects:@"Bear", @"Spork", @"Mac", nil];
    
    // Get the index of a random adjective/noun from the lists
    // Note: The % operator, called modulo operator, gives
    // you the remainder, So adjectiveIndex is a random
    // number between 0 and 2 inclusive.
    NSInteger adjectiveIndex = rand() % [randomAdjectiveList count];
    NSInteger nounIndex = rand() % [randomNounList count];
    
    // Note that NSInteger is not an object, but a type definition
    // for "unsigned long"
    
    NSString *randomName = [NSString stringWithFormat:@"%@ %@",
                            [randomAdjectiveList objectAtIndex:adjectiveIndex],
                            [randomNounList objectAtIndex:nounIndex]];
    
    int randomValue = rand() % 100;
    
    NSString *randomSerialNumber = [NSString stringWithFormat:@"%c%c%c%c%c",
                                    '0' + rand() % 10,
                                    'A' + rand() % 26,
                                    '0' + rand() % 10,
                                    'A' + rand() % 26,
                                    '0' + rand() % 10];
    
    // Self here referes to BNRItem e.g. [BRItem alloc]
    BNRItem *newItem = [[self alloc] initWithItemName:randomName
                        valueInDollars:randomValue
                                         serialNumber:randomSerialNumber];
    
    return newItem;
    
}

-(id)init
{
    return [self initWithItemName:@"Item"
                   valueInDollars:0
                     serialNumber:@""];
}

-(id)initWithItemName:(NSString *)name valueInDollars:(int)value serialNumber:(NSString *)sNumber
{
    //Call the supercalss's designated initialiser
    self = [super init];
    
    // Did the suoerclass's designated initializer succeed?
    if (self) {
        // Give the instance variable inital values
        [self setItemName:name];
        [self setSerialNumber:sNumber];
        [self setValueInDollars:value];
        dateCreated = [[NSDate alloc] init];
    }
    
    // Return the address of the newly initialized object
    return self;
}

// *** SILVER CHALLENGE *** adding another initializer
- (id)initWithItemName:(NSString *)name serialNumber:(NSString *)sNumber
{
    return [self initWithItemName:name valueInDollars:0 serialNumber:sNumber];
}

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

-(void)setItemName:(NSString *)str
{
    itemName = str;
}

-(NSString *)itemName
{
    return itemName;
}

-(void)setSerialNumber:(NSString *)str
{
    serialNumber = str;
}

-(NSString *)serialNumber
{
    return serialNumber;
}

-(void)setValueInDollars:(int)i
{
    valueInDollars = i;
}

-(int)valueInDollars
{
    return valueInDollars;
}

-(NSDate *)dateCreated
{
    return dateCreated;
}

@end

BNRContainer.h

[code]#import <Foundation/Foundation.h>
#import “BNRItem.h”

@interface BNRContainer : BNRItem
{

NSMutableArray *subItems;
int valueInDollarsOfAllItemsInContainer;

}

  • (id)init;

  • (id)initWithItemName:(NSString *)name
    valueInDollars:(int)value
    serialNumber:(NSString *)sNumber
    subItems:(NSMutableArray *)items;

  • (int)valueInDollarsOfAllItemsInContainer;

  • (void)setSubItems:(NSMutableArray *)sItems;

  • (NSMutableArray *)subItems;

@end
[/code]

BNRContainer.m

[code]#import “BNRContainer.h”

@implementation BNRContainer

-(id)init
{
return [self initWithItemName:@"Container"
valueInDollars:0
serialNumber:@"C1"
subItems:[[NSMutableArray alloc] init]];
}

-(id)initWithItemName:(NSString *)name valueInDollars:(int)value serialNumber:(NSString *)sNumber subItems:(NSMutableArray *)items
{
//Call the supercalss’s designated initialiser
self = [super initWithItemName:name valueInDollars:value serialNumber:sNumber];

// Did the suoerclass's designated initializer succeed?
if (self) {
    // Give the instance variable inital values
    NSMutableArray *copyItems = [[NSMutableArray alloc] initWithArray:items];
    [self setSubItems:copyItems];
    
}

// Return the address of the newly initialized object
return self;

}

-(NSString *)description
{
NSString *descriptionStringAllItems = @"";

// Create a string with all the Items to print
for (BNRItem *item in subItems) {
    descriptionStringAllItems = [descriptionStringAllItems stringByAppendingFormat:@"\n %@", item];
}

NSString *descriptionString = [[ NSString alloc] initWithFormat:@"\n Container: %@ \n Value in dollars of all items: %d \n --------------------- \n \t Items in Container \n --------------------- %@ \n ---------------------",
                               [self itemName],
                               [self valueInDollarsOfAllItemsInContainer],
                               descriptionStringAllItems];

return descriptionString;

}

-(int)valueInDollarsOfAllItemsInContainer
{
// Go through all items and add up values
valueInDollarsOfAllItemsInContainer = 0;
for (id item in subItems) {
if ([item isKindOfClass:[BNRContainer class]]) {
valueInDollarsOfAllItemsInContainer += [item valueInDollarsOfAllItemsInContainer];
} else if ([item isKindOfClass:[BNRItem class]])
{
valueInDollarsOfAllItemsInContainer += [item valueInDollars];
}
}

// Add the value of the Container Object too!
valueInDollarsOfAllItemsInContainer += valueInDollars;

return valueInDollarsOfAllItemsInContainer;

}

-(void)setSubItems:(NSMutableArray *)sItems
{
subItems = sItems;
}

  • (NSMutableArray *)subItems
    {
    return subItems;
    }

@end
[/code]

Console Output:

2013-01-17 23:27:19.484 RandomPossessions[85491:303]
Container: CONTAINER 2
Value in dollars of all items: 1165

 Items in Container 

Rusty Spork (8Q2U8): Worth $73, recorded on 2013-01-17 23:27:19 +0000
Shiny Spork (5Y2V3): Worth $40, recorded on 2013-01-17 23:27:19 +0000
Rusty Spork (2F9Z7): Worth $40, recorded on 2013-01-17 23:27:19 +0000
Rusty Bear (8G5V6): Worth $99, recorded on 2013-01-17 23:27:19 +0000
Shiny Spork (3P9B1): Worth $10, recorded on 2013-01-17 23:27:19 +0000
Rusty Mac (6R5C1): Worth $93, recorded on 2013-01-17 23:27:19 +0000
Fluffy Spork (3E4O0): Worth $1, recorded on 2013-01-17 23:27:19 +0000
Fluffy Mac (3A6T4): Worth $30, recorded on 2013-01-17 23:27:19 +0000
Shiny Spork (8S3I1): Worth $77, recorded on 2013-01-17 23:27:19 +0000
Rusty Spork (4F6F9): Worth $65, recorded on 2013-01-17 23:27:19 +0000

Container: CONTAINER 1
Value in dollars of all items: 627

 Items in Container 

Rusty Spork (8Q2U8): Worth $73, recorded on 2013-01-17 23:27:19 +0000
Shiny Spork (5Y2V3): Worth $40, recorded on 2013-01-17 23:27:19 +0000
Rusty Spork (2F9Z7): Worth $40, recorded on 2013-01-17 23:27:19 +0000
Rusty Bear (8G5V6): Worth $99, recorded on 2013-01-17 23:27:19 +0000
Shiny Spork (3P9B1): Worth $10, recorded on 2013-01-17 23:27:19 +0000
Rusty Mac (6R5C1): Worth $93, recorded on 2013-01-17 23:27:19 +0000
Fluffy Spork (3E4O0): Worth $1, recorded on 2013-01-17 23:27:19 +0000
Fluffy Mac (3A6T4): Worth $30, recorded on 2013-01-17 23:27:19 +0000
Shiny Spork (8S3I1): Worth $77, recorded on 2013-01-17 23:27:19 +0000
Rusty Spork (4F6F9): Worth $65, recorded on 2013-01-17 23:27:19 +0000