Gold challenge problem


#1

Hi,

I’ve got pretty much all the Gold challenge points covered, and working great.
Except when I print the list of item’s contained within the Container, I get the values printed as though they are memory address locations (they aren’t, but thats the best I can describe them as) instead of actual values…
Anyone got any ideas?

The output I get is:

2014-09-15 20:54:22.742 RandomItems[93851:303] Container: Container1, Total value: $491, contains items: ( "Fluffy Bear (4N7R4): Worth \U00a344, recorded on 2014-09-15 19:54:22 +0000", "Shiny Mac (2U2T2): Worth \U00a317, recorded on 2014-09-15 19:54:22 +0000", "Rusty Spork (7T4G7): Worth \U00a357, recorded on 2014-09-15 19:54:22 +0000", "Fluffy Spork (7B6J1): Worth \U00a393, recorded on 2014-09-15 19:54:22 +0000", "Rusty Bear (3E5T3): Worth \U00a319, recorded on 2014-09-15 19:54:22 +0000", "Fluffy Spork (8R8N3): Worth \U00a361, recorded on 2014-09-15 19:54:22 +0000", "Rusty Bear (5J0F5): Worth \U00a322, recorded on 2014-09-15 19:54:22 +0000", "Shiny Bear (8H1E7): Worth \U00a335, recorded on 2014-09-15 19:54:22 +0000", "Shiny Mac (3T0Y9): Worth \U00a31, recorded on 2014-09-15 19:54:22 +0000", "Fluffy Bear (5X0Z4): Worth \U00a397, recorded on 2014-09-15 19:54:22 +0000" ) Program ended with exit code: 0

Here’s my code (excuse all the comments):

BNRContainer.m:

[code]#import “BNRContainer.h”

@interface BNRContainer ()
{
NSMutableArray *_listOfBNRItems;
}

@end

@implementation BNRContainer

  • (void)setListOfBNRItems:(NSArray *)itemList;
    {
    _listOfBNRItems = [itemList mutableCopy];
    }

  • (NSArray *)listOfBNRItems
    {
    return [_listOfBNRItems copy];
    }

  • (void)addBNRItem:(BNRItem *)addItem
    {
    // Is listOfBNRItems nil?
    if (!_listOfBNRItems) {
    // Create the array
    _listOfBNRItems = [[NSMutableArray alloc]init];
    }
    [_listOfBNRItems addObject:addItem];
    }

  • (int)totalValueOfContainerAndContents
    {
    int valueOfItems = 0;
    for (BNRItem *item in self.listOfBNRItems) {
    valueOfItems = valueOfItems + item.valueInDollars;
    }

    return self.containerValueInDollars + valueOfItems;
    }

  • (NSString *)description
    {

    NSString *descriptionString = [[NSString alloc]initWithFormat:@“Container: %@, Total value: $%d, contains items: %@”,
    self.containerName,
    self.totalValueOfContainerAndContents,
    self.listOfBNRItems];

    return descriptionString;
    }

@end
[/code]

main.m:

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

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

@autoreleasepool {
    
    NSMutableArray *items = [[NSMutableArray alloc]init];
    BNRContainer *containerOfItems = [[BNRContainer alloc]init];
    containerOfItems.containerName = [NSString stringWithFormat:@"Container1"];
    containerOfItems.containerValueInDollars = 45;
    
    for (int i = 0; i < 10; i++) {
        BNRItem *item = [BNRItem randomItem];
        [items addObject:item];
        [containerOfItems addBNRItem:item];
    }

/* BRONZE CHALLENGE - Trying to printing a non-existent eleventh item in the array /
// NSInteger arrayLength = [items count];
// NSLog(@"%@", [items objectAtIndex:(arrayLength + 1)]);
/
END OF BRONZE CHALLENGE */

/* SILVER CHALLENGE - Create another initialiser - see .h file */

/* GOLD CHALLENGE - Create a subclass of BNRItem - see BNRContainer class */

    NSLog(@"%@", containerOfItems.description);
    
    items = nil;
    
}
return 0;

}
[/code]

BNRItem.m

#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 superclass's designated initialiser
    self = [super init];

    // Did the superclass's designated initialiser 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 initiated object
    return self;
}

// SILVER CHALLENGE
// Create a new initialiser for the BNRItem class. Not the designated initialiser
- (instancetype)initWithItemName:(NSString *)name
                    serialNumber:(NSString *)sNumber
{
    return [self initWithItemName:name
                     serialNumber:@""];
}
// SEE .h FILE FOR DECLARATION OF THIS INITIALISER
// END OF SILVER CHALLENGE

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

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

- (NSString *)description
{
    NSString *descriptionString = [[NSString alloc]initWithFormat:@"%@ (%@): 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

#2

It’s actually kind of interesting, seeing what Cocoa is doing here.

It’s not a memory address that’s being printed, but (roughly) the Unicode equivalent of the British pound sign…but with a twist.

That is, \u00a3 is Unicode for £. “\u” wants four hex digits. But with those four digits being followed by a number in the output, the display is using capital U (\U) which actually expects eight hex digits.

I tried NSLog-ing the string as you did, using the hard-coded “£”, and it worked fine for me. I also tried using \u00a3 in the format string instead of “£”, and that too worked fine. (This is on Mavericks with Xcode 5.1.1.)

Just for jollies, you might try using \u00a3 to see if that helps.


#3

You’re right you know :slight_smile:
I didn’t twig that I used a £ for one of the sections of code, but $ in the other sections (although it doesn’t make a difference to the actual calculations - only when displaying).
I tried what you suggested, using a lowercase u for \u00a3 within the format string, but it still didn’t work. Its strange that Xcode is the one that seems to be misinterpreting this as I don’t think my code is ‘wrong’…

I’ll do a little more digging, but at least I know the reason. Swapping over to a dollar sign, made everything work as it should…

Thanks for helping me spot it though! It would have taken me days/weeks to figure this out…


#4

Thanks for the feedback! Sorry it didn’t do the trick, but at least we know where the issue is.

Which version of Xcode are you using?

Here’s another long shot: including the currency symbol as a string:

Beyond that…I’m afraid I don’t know. If you find the answer, though, I’m interested in hearing!


#5

I’m using the same as you… Xcode version 5.1.1 on Mavericks (10.9.4).
I’ll give the other way a try later. Right now I have the application working by using just the $ symbol, which is good enough for now.
I’m having a more pressing problem now in that the sub-container when it returns its description, it displays loads of \n’s and doesnt actually put anything on new lines… The program works as it should, its just it doesn’t display correctly - which is annoying!

EDIT: I just tried using the @"\u00a3" way, and that worked… That being said, I’ve made some other changes to my code to simplify things, but not the description method…
Here’s the results:

2014-09-16 15:02:18.512 RandomItems[50165:303] Container: Main Container, Total value: £1174, contains items and containers: ( "Fluffy Bear (9W9S1): Worth $76, recorded on 2014-09-16 14:02:18 +0000", "Shiny Bear (3F0X6): Worth $89, recorded on 2014-09-16 14:02:18 +0000", "Rusty Bear (8I0L4): Worth $93, recorded on 2014-09-16 14:02:18 +0000", "Shiny Spork (0V0P1): Worth $17, recorded on 2014-09-16 14:02:18 +0000", "Fluffy Bear (3L6E0): Worth $95, recorded on 2014-09-16 14:02:18 +0000", "Container: Container1, Total value: \U00a3704, contains items and containers: (\n \"Shiny Bear (2Q8F8): Worth $58, recorded on 2014-09-16 14:02:18 +0000\",\n \"Shiny Mac (2K6B0): Worth $6, recorded on 2014-09-16 14:02:18 +0000\",\n \"Rusty Spork (5Q0Q7): Worth $99, recorded on 2014-09-16 14:02:18 +0000\",\n \"Shiny Mac (6T2T5): Worth $50, recorded on 2014-09-16 14:02:18 +0000\",\n \"Shiny Mac (0J9A5): Worth $93, recorded on 2014-09-16 14:02:18 +0000\",\n \"Rusty Mac (9X0N0): Worth $96, recorded on 2014-09-16 14:02:18 +0000\",\n \"Shiny Spork (1N5D0): Worth $18, recorded on 2014-09-16 14:02:18 +0000\",\n \"Shiny Bear (9V5G3): Worth $77, recorded on 2014-09-16 14:02:18 +0000\",\n \"Shiny Spork (5V7V5): Worth $81, recorded on 2014-09-16 14:02:18 +0000\",\n \"Rusty Bear (2Q7M0): Worth $81, recorded on 2014-09-16 14:02:18 +0000\"\n)" ) Program ended with exit code: 0

So I tried removing the %@/@"\u00a3" combo from the NSLog, and replacing with a proper £ sign again, and it worked.
HOWEVER… Notice the other issue I’m having where the sub-container doesn’t display properly, this STILL shows the \U00a3 code for the total value of the container, but now not for any of the items within!? Urgh.