My Gold Challenge solution

I didn’t see one like it here unless I missed it. This uses inheritance and method overriding to finish the challenge. I hope this helps someone.

Main.m

//  main.m
//  RandomItems

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

int main(int argc, const char * argv[]) {
    @autoreleasepool {

        //Create a container to hold two items
        BNRContainer *container = [[BNRContainer alloc]initWithItemName:@"ContainerA" valueInDollars:10 serialNumber:@"Ek329w"];
        
        //Create two items to put in the container
        BNRItem *myItem = [[BNRItem alloc]initWithItemName:@"Pookie" valueInDollars:20 serialNumber:@"455443d"];
        BNRItem *myItem2 = [[BNRItem alloc]initWithItemName:@"Mittens" valueInDollars:20 serialNumber:@"ljljk4"];
        
        //Add the items to the container
        [container addItem: myItem];
        [container addItem: myItem2];
        
        //Create a second container that will go into the first container
        BNRContainer *myCont = [[BNRContainer alloc]initWithItemName:@"ContainerB" valueInDollars:20 serialNumber:@"lkjljjlj9"];
        
        //Create two items to put in this container
        BNRItem *myItem3 = [[BNRItem alloc]initWithItemName:@"Fluffy" valueInDollars:30 serialNumber:@"sdsd55sd"];
        BNRItem *myItem4 = [[BNRItem alloc]initWithItemName:@"Pookums" valueInDollars:30 serialNumber:@"uu66uii"];
        
        //Add the two items to the second container
        [myCont addItem:myItem3];
        [myCont addItem:myItem4];
        
        //Add the second container to the first container
        [container addItem: myCont];
        
        //Call the description of the first container to complete the gold challange!
        NSLog(@"%@", [container description]);
    }
    return 0;
}

BNRItem.h

[code]//
// BNRItem.h
// RandomItems

#import <Foundation/Foundation.h>

@interface BNRItem : NSObject
{
NSString *_itemName;
NSString *_serialNumber;
int _valueInDollars;
NSDate *_dateCreated;
}

+(instancetype)randomItem;

//Designated initializer
-(instancetype)initWithItemName:(NSString *)name
valueInDollars:(int)value
serialNumber:(NSString *)sNumber;

-(instancetype)initWithItemName:(NSString *)name
andSerialNumber:(NSString *)sNumber;

-(instancetype)initWithItemName:(NSString *)name;

-(void)setItemName:(NSString *)str;
-(NSString *)itemName;

//SILVER CHALLENGE
-(void)setSerialNumber:(NSString *)str;
-(NSString *)serialNumber;

-(void)setValueInDollars:(int)v;
-(int)valueInDollars;

-(NSDate *)dateCreated;

@end
[/code]

BNRItem.m

[code]//
// BNRItem.m
// RandomItems

#import “BNRItem.h”

@implementation BNRItem

+(instancetype)randomItem
{
// Create an immutable array of three adjectives
NSArray *randomAdjectiveList = @[@“Fluffy”, @“Rusty”, @“Shiny”];

// Create an immutable array of three nouns
NSArray *randomNounList = @[@"Bear", @"Spork", @"Mac"];

// Get the index of a random adjective/noun from the lists
// Note: The % operator, called the modulo operator, gives
// you the remainder. So adjectiveIndex is a random number
// from 0 to 2 inclusive.
NSInteger adjectiveIndex = arc4random() % [randomAdjectiveList count];
NSInteger nounIndex = arc4random() % [randomNounList count];

// Note that NSInteger is not an object, but a type definition
// for "long"

NSString *randomName = [NSString stringWithFormat:@"%@ %@",
                        randomAdjectiveList[adjectiveIndex],
                        randomNounList[nounIndex]];

int randomValue = arc4random() % 100;

NSString *randomSerialNumber = [NSString stringWithFormat:@"%c%c%c%c%c",
                                '0' + arc4random() % 10,
                                'A' + arc4random() % 26,
                                '0' + arc4random() % 10,
                                'A' + arc4random() % 26,
                                '0' + arc4random() % 10];


BNRItem *newItem = [[self alloc] initWithItemName:randomName
                                   valueInDollars:randomValue
                                     serialNumber:randomSerialNumber];
return newItem;

}

-(instancetype)initWithItemName:(NSString *)name
valueInDollars:(int)value
serialNumber:(NSString *)sNumber
{
//Call the superclasses desginated initializer
self = [super init];

//Did the superclasses designated initializer succeed?
if(self)
{
    //Give the instance variables initial values
    _itemName = name;
    _serialNumber = sNumber;
    _valueInDollars = value;
    
    //Set dateCreated to the current date and time
    _dateCreated = [[NSDate alloc]init];
}

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

}

-(instancetype)initWithItemName:(NSString *)name
andSerialNumber:(NSString *)sNumber
{
return [self initWithItemName:name
valueInDollars:0
serialNumber:sNumber];
}

//SILVER CHALLENGE
-(instancetype)initWithItemName:(NSString *)name
{
return [self initWithItemName:name
andSerialNumber:@""];
}

-(instancetype)init{
return [self initWithItemName:@“Item”];
}

-(NSString *)description
{
NSString *descriptionString = [NSString stringWithFormat:@"%@ (%@): Worth $%d, recorded on %@",
self.itemName,
self.serialNumber,
self.valueInDollars,
self.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)v
{
_valueInDollars = v;
}

-(int)valueInDollars
{
return _valueInDollars;
}

-(NSDate *)dateCreated
{
return _dateCreated;
}

@end[/code]

BNRContainer.h

[code]//
// BNRContainer.h
// RandomItems

#import “BNRItem.h”

@interface BNRContainer : BNRItem

-(void)addItem: (id)item;

//Remove item

@end
[/code]

BNRContainer.m

[code]//
// BNRContainer.m
// RandomItems

#import “BNRContainer.h”

@implementation BNRContainer
{
//Hold the items in the container
NSMutableArray *_items;

//Value of the container itself
int _containerValue;

}

-(int)valueInDollars
{
//Override this method to grab the value of everything in the current array
int contentValue = 0;

for (id item in _items) {
    contentValue += [item valueInDollars];
}

//Return the container value + the content value
return _containerValue + contentValue;

}

-(void)addItem:(id)item
{
//Make sure the object is a BNRItem or a subclass of BNRItem (like a BNRContainer)
if([item isKindOfClass:[BNRItem class]])
{
//If it is, add it to the items array
[_items addObject:item];
}

else{
    NSLog(@"Incorrect object type.");
}

}

//Override the default initalizer from the BNRItem superclass
-(instancetype)initWithItemName:(NSString *)name valueInDollars:(int)value serialNumber:(NSString *)sNumber{

//Call the base class's designated initializer
self = [super initWithItemName:name valueInDollars:value serialNumber:sNumber];

if(self)
{
    //Initialize the items array which is unique to the BNRContainer
    _items = [[NSMutableArray alloc]init];
    _containerValue = value;
}

//Return the newly instantiated object
return self;

}

-(NSString*)description
{
/GOLD CHALLENGE
The description has to return the container name, its value (contents + container),
and all items it contains, including BNRItems and BNRContainers.
*/

//Make a string to hold the description of all items in the _items array.
NSString *contents = [[NSString alloc]init];

//Iterate through the items and append the description to the string so it can be
//returned. (This will contain the description for all items in the _items array.
for (id item in _items) {
    NSString *str = [NSString stringWithFormat:@"\n\t%@", [item description]];
    contents = [contents stringByAppendingString: str];
}

//Format a nicer description string to return the container(s) and all of its contents.
NSString *description = [NSString stringWithFormat:@"\nContainer Name: %@ (%@) Total Value: $%d\
                                                     \nContainer Contents: %@",
                         [self itemName],
                         [self serialNumber],
                         [self valueInDollars],
                         contents];

return description;

}
@end
[/code]

Here’s the output:

Everything inside (including the containers initial values set in code, which I didn’t print in the output) everything adds up as it should.