1st "Challenge"


#1

Do I have to make a new string object (or any object for that matter) before I can put it into a mutable array?

NSMutableArray *array = [NSMutableArray array];
NSString *apples = [[NSString alloc] initWithFormat:@"Apples"];
NSString *oranges = [[NSString alloc] initWithFormat:@"Oranges"];
NSString *bacon = [[NSString alloc] initWithFormat:@"Bacon"];

[array addObject:apples];
[array addObject:oranges];
[array addObject:bacon];

for(NSString *foodItem in array){
    NSLog(@"We need to buy %@", foodItem);
}

Or is that the way the exercise was to be completed?


#2

You could just put constant strings into the array:

[code]NSMutableArray *array = [NSMutableArray array];

[array addObject:@“Apples”];
[array addObject:@“Oranges”];
[array addObject:@“Bacon”];

for (NSString *foodItem in array) {
NSLog(@“We need to buy %@”, foodItem);
}[/code]


#3

Looking at my first solution it didn’t occur to me to nest the constant NSStrings creation right into the array. I did use id in my enumeration though, just for fun.

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

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

@autoreleasepool {
    
    // Create an empty array
    NSMutableArray *grocList = [NSMutableArray array];
    
    // Create some grocery list items
    NSString *milk = @"Milk";
    NSString *bread = @"Bread";
    NSString *eggs = @"Eggs";
    NSString *booze = @"Booze";
    
    // Put those into our array
    [grocList addObject:milk];
    [grocList addObject:bread];
    [grocList addObject:eggs];
    [grocList addObject:booze];
    
    // Print out the array
    for (id listItem in grocList) {
        NSLog(@"Don't forget the %@!", listItem);
    }
    
}
return 0;

}[/code]


#4

here’s mine:

#import <Foundation/Foundation.h>

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

    @autoreleasepool {
        
        NSMutableArray *groceries = [[NSMutableArray alloc] init];
        [groceries addObject:@"Coffee"];
        [groceries addObject:@"More Coffee"];
        [groceries addObject:@"Even More Coffee"];
        for (NSString *g in groceries)
        {
            NSLog(@"Buy %@", g);
        }
    }
    
    return 0;
}

#5

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

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

@autoreleasepool {
    
    NSMutableArray *groceries = [NSMutableArray array];
    NSString *item1 = @"milk";
    NSString *item2 = @"bread";
    NSString *item3 = @"cheese";
    NSString *item4 = @"veggies";
    NSString *item5 = @"pizza";
    NSString *item6 = @"dog food";
    NSString *item7 = @"cat food";
    NSString *item8 = @"toothpaste";
    
    [groceries addObject:item1];
    [groceries addObject:item2];
    [groceries addObject:item3];
    [groceries addObject:item4];
    [groceries addObject:item5];
    [groceries addObject:item6];
    [groceries addObject:item7];
    [groceries addObject:item8];
    
    NSUInteger *numba = 0;
    
    for (NSString *item in groceries) {
        numba++;
        NSLog(@" %i. %@", numba, item);
        
    }
    
    
}
return 0;

}[/code]

I decided to “number” the list but got some odd results. My thinking was that for each iteration through the array it printed one item. However, It incremented my variable numba by 8 (the number of items in my array) - would you explain why, please?

2011-12-05 15:46:00.722 Groceries[550:707] 8. milk
2011-12-05 15:46:00.723 Groceries[550:707] 16. bread
2011-12-05 15:46:00.723 Groceries[550:707] 24. cheese
2011-12-05 15:46:00.724 Groceries[550:707] 32. veggies
2011-12-05 15:46:00.724 Groceries[550:707] 40. pizza
2011-12-05 15:46:00.725 Groceries[550:707] 48. dog food
2011-12-05 15:46:00.725 Groceries[550:707] 56. cat food
2011-12-05 15:46:00.726 Groceries[550:707] 64. toothpaste
Program ended with exit code: 0


#6

I can’t quite explain the behavior, but I can definitely explain the error.

You’ve stepped into one significant inconsistency (not necessarily a problem in general) with Objective-C: not everything is an object.

You need to declare NSUInteger numba, not *numba.

Edit: On second thought I can explain the behavior.

You initialized a pointer (*numba) to NULL by assigning it 0.

Each time you increment with numba++, you’re incrementing by one pointer’s worth of memory. An NSUInteger pointer is 8 bytes in size.

Don’t worry if all of this is gobbledygook. I struggle with it on occasion, and I’ve been playing with C pointers off and on for 15 years.


#7

lol yeah but this “gobbledygook” gave me unexpected results!

You are correct, though: removing the object declaration fixed the problem but I still don’t understand why. Hopefully it will become apparent. Are you saying that integer variables should never be declared as objects?

Thanks for the quick response.


#8

You’re quite welcome. Let me try a short version that may help tide you over for now.

When you declare a variable with an asterisk, you’re telling the compiler to expect a pointer to the type in question.

NSUInteger * foo;
^^^^^^^^^^ ^ ^^^
  Type     | Variable name
           |
           "foo is a pointer to an NSUInteger"

A pointer is an address in memory, not a value that you ordinarily think of as having meaning.

By leaving out the asterisk, you tell the compiler that foo is a plain old integer, one that you can work with using normal procedures.

Objects always use pointers because that’s the way the Objective-C language designers decided to do it. Simple data types can use pointers, but rarely do, and the syntax for working with those pointer references is different.


#9

Ah ok. And as you said before, because I set the POINTER to 0, the compiler interpreted that to mean null and not a value. *Light bulb comes on - thanks very much. Obviously I’m really new to this.


#10

My quick solution - feedback is appreciated

#import <Foundation/Foundation.h>

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

    @autoreleasepool {
        
        NSMutableArray *groceriesList = [NSMutableArray array];
        
        NSString *cheese = @"AMERICAN CHEESE";
        NSString *softDrink = @"Coke";
        NSString *meat = @"Steak";
    
        
        [groceriesList addObject:cheese];
        [groceriesList addObject:softDrink];
        [groceriesList addObject:meat];
        
        for(NSString *d in groceriesList)
        {
            NSLog(@"I need to buy some %@", d);
        }
        
        
        
        
    }
    return 0;
}

#11

Here was my solution, pretty similar to everyone else’s:

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

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

@autoreleasepool {
	
	// Create the groceries
	NSString *milk = @"Milk";
	NSString *butter = @"Butter";
	NSString *eggs = @"Eggs";
	NSString *ham = @"Ham";
	NSString *cheese = @"Cheese";
	
	// Create an array for the groceries
	NSMutableArray *groceryList = [NSMutableArray array];
	
	// Add the groceries to the array
	[groceryList addObject:milk];
	[groceryList addObject:butter];
	[groceryList addObject:eggs];
	[groceryList addObject:ham];
	[groceryList addObject:cheese];
	
	// Use fast enumeration to print the list
	for (NSString *foodItem in groceryList) {
		NSLog(@"You need: %@", foodItem);
	}
}
return 0;

}[/code]

I was, however, wondering if there was a way to add all of the objects to the array at once, rather than one at a time. My first thought was to try something like this:

The problem with this is that addObject: only accepts one argument. So is there another method to add all of these items to the array at once, instead of one at a time?


#12

You can do:

NSMutableArray *groceryList = [NSMutableArray arrayWithObjects:milk, butter, eggs, ham, cheese, nil];

(The nil signals the end of the list and is not actually in the array)


#13

Thanks for the quick reply Aaron! Love the book by the way; you’re my hero! :smiley:


#14

I’m glad you like the book. I’m pretty proud of it.

As for a hero, I’m probably not worthy. Its not like I cured cancer – I’ve written Objective-C code for 20 years, and I just got around to writing a decent book on it.


#15

This is what I did.[code]

#import <Foundation/Foundation.h>

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

@autoreleasepool {
    
    /* create an empty NSMutableArray */
    NSMutableArray *groceryItems = [NSMutableArray array];
    
    /* add grocery items to the list */
    [groceryItems addObject:@"Hot Dogs"];
    [groceryItems addObject:@"Buns"];
    [groceryItems addObject:@"Bacon"];
    [groceryItems addObject:@"Beans"];
    [groceryItems addObject:@"Onion"];
    [groceryItems addObject:@"Tomato"];
    [groceryItems addObject:@"Jalapeño sauce"];
    [groceryItems addObject:@"mayonnaise"];
    [groceryItems addObject:@"mustard"];

    /* display each item using fast enumeration */
    for (NSMutableArray *myItem in groceryItems){
        NSLog(@"Item to buy: %@", myItem);// display all the items
    }// end for
    
}// end autoreleasepool
return 0;

}// end main
[/code]


#16

You also want to set numba to -1 not 0

So when your loop starts for the first time you begin with 0 , 1 , 2 etc…


#17

I’m really enjoying the book so far. It’s been a really nice introduction to Objective-C (and it’s roots in C). I’m looking forward to finishing it and moving onto the next one!

This is what I ended up with for this challenge (about the same as everyone else:

#import <Foundation/Foundation.h>

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

    @autoreleasepool {
        
        NSMutableArray *groceryList = [NSMutableArray arrayWithObjects:@"milk", @"sugar", @"pizza", nil];
        for (NSString *g in groceryList) {
            NSLog(@"list item: %@", g);
        }
        
    }
    return 0;
}

#18

My solution is basically the same as [color=green]alexander2020’s[/color]. Except for the times, of course, seems to have a better diet than me! :laughing:

The desire to number the items as they printed out lead me to some searching before starting the second challenge. I think the simplest way would be to use a for loop and print out the loop counter.for (int i; i<= maxNumber, i++)... NSLog(@"Item %@ is %@.", i, itemName);...I don’t know how to get that ‘incrementing’ value with the fast enumeration method. There is also the problem of determining that ‘maxNumber’ which supposedly can be found with:int maxNumber = [arrayName [i]count[/i]]Then, the only problem is how to convert that int into a format that NSLog can use. I’ve tried this with no luck:NSString *maxCount = [NSString stringWithFormat:@"%d", maxNumber);


#19

This is my solution for challenge 1:

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

@autoreleasepool {
    
    NSMutableArray *groceries = [NSMutableArray array];
    
    NSString *bloemkool = @"bloemkool";
    NSString *sla = @"sla";
    NSString *witloof = @"witloof";
    
    [groceries addObject:bloemkool];
    [groceries addObject:sla];
    [groceries addObject:witloof];
    
    NSUInteger i;
    i = 0;
    
    for (NSString *groente in groceries) {
        i++;
        NSLog(@"%li - Groente : %@", i, groente);
    }
    
}
return 0;

}
[/code]


#20

Once again, I came up with something that works, but could be simplified greatly. I really appreciate having the chance to compare my code with others and learn from them!

[code]

#import <Foundation/Foundation.h>

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

@autoreleasepool {
        
    // Create  NSString instances for the groceries
    
    NSString *bananas = [NSString stringWithFormat:@"bananas"];
    NSString *grapes = [NSString stringWithFormat:@"grapes"];
    NSString *bread = [NSString stringWithFormat:@"bread"];
    NSString *eggs = [NSString stringWithFormat:@"eggs"];
    NSString *kombucha = [NSString stringWithFormat:@"kombucha"];

    // Create an empty array
    
    NSMutableArray *groceryList = [NSMutableArray array];
    
    
    // Add grocery items to the array

    [groceryList addObject:bananas];
    [groceryList addObject:grapes];
    [groceryList addObject:bread];
    [groceryList addObject:eggs ];
    [groceryList addObject];
            
    for (NSString *d in groceryList) {
        NSLog(@"Don't forget %@!", d);
    }

}
return 0;
}[/code]

Looking at the solutions offered here, I see that the “stringWithFormat” method is unnecessary. And I learned some great ways to simplify the code.