iOS Can I get a small explanation about this bit of code?

Tander

macrumors 6502a
Original poster
Oct 21, 2011
676
1
Johannesburg, South Africa
Hey guys,

So I am busy reading an objective-c book by Big Nerd Ranch. I'm on chapter 17 at the moment and managed to complete the required challenge at the end of the chapter. However, I just have two question that I would like to understand.


In the following bit of code - StockHolding is a custom class that has instance variables and the stocks (an array) points to three instances of stockholding with values setting its stock value and cost in dollars.

At first I tried to access the array to get the data from the objects it pointed to - but it seems that was not going to work as the array doesn't know what data its objects contain - just where they are in memory, right?

What I want to know is why was it necessary to create a new instance of stockholding (holdings) in this for loop to access those variables?
How does the new instance of stockholding know what the values of my stocks are?

Code:
        for (StockHolding *holdings in stocks){

            NSLog (@ "%@ has %d shares. Cost: $%.2f. Stock value: $%.2f", [holdings stockName],
[holdings numberOfShares], 
[holdings costInDollars], 
[holdings valueInDollars]);
        }
I'm going to try have a guess here to see if maybe I understand it a little better?

We create an instance of our class in the for loop so that we have access to its instance methods and variables - then we use the stocks array to get the variables from those objects in the array?

I may be completely off.. :(

Any advice?

Thanks guys!
 

robbieduncan

Moderator emeritus
Jul 24, 2002
24,638
61
Harrogate
You are confusing instances with variable names. holdings is not an instance. It points to an instance. A pre-existing instance. Not a new one. Each iteration through the loop the pointer is updated to point at the next instance from the collection stocks.
 

dantastic

macrumors 6502a
Jan 21, 2011
569
645
What you have there is called Fast Enumeration. It's a way of iterating through an array really fast. You are not creating a new instance of StockHolding you are merely accessing an existing instance from the array.

You can have a peek here under fast enumeration https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/FoundationTypesandCollections/FoundationTypesandCollections.html

Code:
for (NSString *myString in allMyStrings) {
    NSLog(@"String: %@", myString);
}

for (int i = 0; i < allMyStrings.count; i++) {
    NSString *myString = [allMyStrings objectAtIndex:i];
    NSLog(@"String: %@", myString);
}
These two loops provide the same functionality but the former one is much faster. If you look at the second loop, you are just accessing the object, not creating a new instance.
 

robbieduncan

Moderator emeritus
Jul 24, 2002
24,638
61
Harrogate
What you have there is called Fast Enumeration. It's a way of iterating through an array really fast. You are not creating a new instance of StockHolding you are merely accessing an existing instance from the array.

You can have a peek here under fast enumeration https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/FoundationTypesandCollections/FoundationTypesandCollections.html

Code:
for (NSString *myString in allMyStrings) {
    NSLog(@"String: %@", myString);
}

for (int i = 0; i < allMyStrings.count; i++) {
    NSString *myString = [allMyStrings objectAtIndex:i];
    NSLog(@"String: %@", myString);
}
These two loops provide the same functionality but the former one is much faster. If you look at the second loop, you are just accessing the object, not creating a new instance.
Can you prove the former is faster? I honestly believe it won't be faster. My understanding is the name is related to it being faster to type rather then faster to execute.
 

dantastic

macrumors 6502a
Jan 21, 2011
569
645
Can you prove the former is faster? I honestly believe it won't be faster. My understanding is the name is related to it being faster to type rather then faster to execute.
Let's not take my word for it.
Code:
	NSMutableArray *myArray = [[NSMutableArray alloc] init];
	for (int i = 0; i < 10000000; i++) {
		[myArray addObject:[NSString stringWithFormat:@"String %i", i]];
	}
	
	NSDate *t0 = [NSDate date];
	NSMutableArray *forArray = [[NSMutableArray alloc] init];
	for (int i = 0; i < myArray.count; i++) {
		
		NSString *myString = [myArray objectAtIndex:i];
		[forArray addObject:[myString copy]];
	}
	NSDate *t1 = [NSDate date];
	

	NSDate *t2 = [NSDate date];
	NSMutableArray *enumArray = [[NSMutableArray alloc] init];
	for (NSString *myString in myArray) {
		
		[enumArray addObject:[myString copy]];
	}
	NSDate *t3 = [NSDate date];
	
	
	NSLog(@"\nFor loop: %f\nEnum loop: %f", [t1 timeIntervalSinceDate:t0], [t3 timeIntervalSinceDate:t2]);
Code:
For loop: 2.092580
Enum loop: 1.366328
That's pretty significant I recon.
 

robbieduncan

Moderator emeritus
Jul 24, 2002
24,638
61
Harrogate
Cool: I know in Java tests have shown that using the Iterator is slower than a straight for loop. I would be interested in seeing the results if you saved the count into a variable instead of checking it every iteration of the for loop...
 

dantastic

macrumors 6502a
Jan 21, 2011
569
645
Modified the code slightly to read the count of the array into an int before setting the t0 time stamp and then using the int instead of querying the array.count.

Code:
For loop: 1.946401
Enum loop: 1.407935
It did improve the result. Considering as well the fast enumeration loop was slightly slower this time the for loop can be considered improved a good bit.
 

Tander

macrumors 6502a
Original poster
Oct 21, 2011
676
1
Johannesburg, South Africa
You are confusing instances with variable names. holdings is not an instance. It points to an instance. A pre-existing instance. Not a new one. Each iteration through the loop the pointer is updated to point at the next instance from the collection stocks.
Okay so we are point at the instance of stockholding using the pointer *holdings. That clears it up a little. :)

When you say pre-existing instance - is that stockholding you're referring it?
 

Tander

macrumors 6502a
Original poster
Oct 21, 2011
676
1
Johannesburg, South Africa
What you have there is called Fast Enumeration. It's a way of iterating through an array really fast. You are not creating a new instance of StockHolding you are merely accessing an existing instance from the array.

You can have a peek here under fast enumeration https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/FoundationTypesandCollections/FoundationTypesandCollections.html

Code:
for (NSString *myString in allMyStrings) {
    NSLog(@"String: %@", myString);
}

for (int i = 0; i < allMyStrings.count; i++) {
    NSString *myString = [allMyStrings objectAtIndex:i];
    NSLog(@"String: %@", myString);
}
These two loops provide the same functionality but the former one is much faster. If you look at the second loop, you are just accessing the object, not creating a new instance.
Thanks - the link does help. So what I get from that is we point to each object in the array, using the instance stockholding and we call this instance holdings. Which is why [holdings currentSharePrice] works in the NSLog function, right?

Since currentSharePrice is an instance variable inside our stockholding class - so we can now access it using an instance of the class?
 

robbieduncan

Moderator emeritus
Jul 24, 2002
24,638
61
Harrogate
stocks contains a number of instances of StockHolding. Instances don't have names: it makes no sense to ask if an instance is "stockholding" or any other name. Instances do, however, have memory addresses.

If we step aware from Objective-C for a bit and pretend that stocks is a plain old array (not a NSArray which I assume it is). An array is a contiguous block of memory starting at an address like this:
Code:
Memory:   0000 0001 .... 0100
Contents: [       ] [       ]  [       ]
If this is an integer array then the contents could be numbers:

Code:
Memory:   0000 0001 .... 0100
Contents: [   1] [  5]      [-10]
So far, so simple. But what if our array contains pointers:

Code:
Memory:   0000   0001    .... 0100
Contents: [1001] [1100]      [1111]
So now the first element of our array does not contain a value: it contains a pointer to a value. This is the situation we have in this example. An instance of any class is simply a structure in memory. This structure is, in reality, quite complicated but we can simplify it to something like this:

Code:
Offset Item
0        isa
1        1st instance variable
2        2nd instance variable
....
where isa is a pointer to the class and the rest are the instance variables. These will either be the raw value in the case of primative types or a pointer to another object in the case of object types.

When we create the array stocks what is actually happening is something like this:

Code:
Stocks: [00100000, 00100010, 00100111]
0010000: isa pointer -> StockHolding class
0010001: 100
0010010: isa pointer -> StockHolding class
0010011: 400
0010100: isa pointer -> StockHolding class
0010101: -200
So we have an array which contains 3 pointers. These pointers point to 3 instances of StockHolding (3 memory addresses). Each of these objects has a single instance variable, the amount of the holding for this instance (100, 400 and -200). As we loop over the array holdings points first to 0010000 then the second time 0010010 and the third time 0010100. So it points to the existing instances, not new ones. When we as for the holding amount we get the amount from the instance we are pointing at: instance variables are at an instance level, not the class level:

Code:
StockHolding a = [[StockHolding alloc] init];
[a setSharePrice:100];
StockHolding b = a; // so now b and a point to the same instance
[b setSharePrice:200];
NSLog(@"%i",[a getSharePrice]);
200 will be printed as both a and b point to the same instance: they point to the same object in memory.
 

Tander

macrumors 6502a
Original poster
Oct 21, 2011
676
1
Johannesburg, South Africa
stocks contains a number of instances of StockHolding. Instances don't have names: it makes no sense to ask if an instance is "stockholding" or any other name. Instances do, however, have memory addresses.

If we step aware from Objective-C for a bit and pretend that stocks is a plain old array (not a NSArray which I assume it is). An array is a contiguous block of memory starting at an address like this:
Code:
Memory:   0000 0001 .... 0100
Contents: [       ] [       ]  [       ]
If this is an integer array then the contents could be numbers:

Code:
Memory:   0000 0001 .... 0100
Contents: [   1] [  5]      [-10]
So far, so simple. But what if our array contains pointers:

Code:
Memory:   0000   0001    .... 0100
Contents: [1001] [1100]      [1111]
So now the first element of our array does not contain a value: it contains a pointer to a value. This is the situation we have in this example. An instance of any class is simply a structure in memory. This structure is, in reality, quite complicated but we can simplify it to something like this:

Code:
Offset Item
0        isa
1        1st instance variable
2        2nd instance variable
....
where isa is a pointer to the class and the rest are the instance variables. These will either be the raw value in the case of primative types or a pointer to another object in the case of object types.

When we create the array stocks what is actually happening is something like this:

Code:
Stocks: [00100000, 00100010, 00100111]
0010000: isa pointer -> StockHolding class
0010001: 100
0010010: isa pointer -> StockHolding class
0010011: 400
0010100: isa pointer -> StockHolding class
0010101: -200
So we have an array which contains 3 pointers. These pointers point to 3 instances of StockHolding (3 memory addresses). Each of these objects has a single instance variable, the amount of the holding for this instance (100, 400 and -200). As we loop over the array holdings points first to 0010000 then the second time 0010010 and the third time 0010100. So it points to the existing instances, not new ones. When we as for the holding amount we get the amount from the instance we are pointing at: instance variables are at an instance level, not the class level:

Code:
StockHolding a = [[StockHolding alloc] init];
[a setSharePrice:100];
StockHolding b = a; // so now b and a point to the same instance
[b setSharePrice:200];
NSLog(@"%i",[a getSharePrice]);
200 will be printed as both a and b point to the same instance: they point to the same object in memory.
Okay that is making a lot more sense now. :cool:

I really appreciate the time you have taken in explaining this to me.
Doing this on my own with no one around who knows objective-c is difficult as I have to do a lot of the research on my own.

I am going to re-read your explanation again tomorrow as I am tired today so I don't think I am "absorbing" as much as I could be at this point in time.
 

robbieduncan

Moderator emeritus
Jul 24, 2002
24,638
61
Harrogate
I am going to re-read your explanation again tomorrow as I am tired today so I don't think I am "absorbing" as much as I could be at this point in time.
This is probably a good idea. Sometimes stepping away and coming back makes everything just snap into place. The one thing I would suggest is learning plain old C. Pointers, memory etc are all based on that and a good understanding of that could help here.
 

Tander

macrumors 6502a
Original poster
Oct 21, 2011
676
1
Johannesburg, South Africa
This is probably a good idea. Sometimes stepping away and coming back makes everything just snap into place. The one thing I would suggest is learning plain old C. Pointers, memory etc are all based on that and a good understanding of that could help here.
Yeah I think I need to revisit the pointers section of my book. :(
 

Duncan C

macrumors 6502a
Jan 21, 2008
853
0
Northern Virginia
Yeah I think I need to revisit the pointers section of my book. :(

Definitely.

The take-away is this:

Any variable with a "*" in it's declaration is a pointer variable. It's a memory address that points to something else.

Example:
Code:
MyObject *anObject;
anObject = [[MyObject alloc] init];
anObject is a pointer variable that points to an object of type MyObject.

Note the asterisk in the declaration.


After the first declaration line, the pointer anObject may point to garbage memory, or to nil, depending on how your compiler is set up.

The RIGHT PART of the second line creates a new MyObject, initializes it, and returns it. The "=" operator then saves the result into the local POINTER variable anObject.

After that second line, the local variable anObject contains the address of a MyObject object.

In practice, everybody says "anObject contains the newly created object" because it's easier to say, but it's not really correct.


That is different than this line:

Code:
int anInt;
Note that there is no asterisk in the declaration of anInt.

Ih that code, the variable anInt actually holds an integer value, not a pointer. The compiler defines anInt as a block of memory that can hold an integer.
 

Tander

macrumors 6502a
Original poster
Oct 21, 2011
676
1
Johannesburg, South Africa
Hi Guys,

Okay so I have re-read both / all explanations and it's starting to be much clearer now.

I'm going to reread pointers and make sure I try understand them 100%.

Is it okay if I keep this thread open to discuss any question I may have regarding pointers in general and to see if my understanding is correct once I have reread about pointers in general?

Thanks again all! :cool:
 

Tander

macrumors 6502a
Original poster
Oct 21, 2011
676
1
Johannesburg, South Africa
I've decided to read a book called: The C Programming Language by Brian W. Kernighan and Dennis M. Ritchie - while also reading my current book, too.
BNR Objective-C programming

Maybe side by side they will make sense.
 

robbieduncan

Moderator emeritus
Jul 24, 2002
24,638
61
Harrogate
I've decided to read a book called: The C Programming Language by Brian W. Kernighan and Dennis M. Ritchie - while also reading my current book, too.
BNR Objective-C programming

Maybe side by side they will make sense.
That is, essentially, the C book. The OG if you like.
 

Tander

macrumors 6502a
Original poster
Oct 21, 2011
676
1
Johannesburg, South Africa
Is the K&R book that good?

I see there is a second edition with around 200-odd pages.

As a total beginner would I struggle with this book?
Also can I use xCode to compile / run the examples / exercises in the book on?
 

robbieduncan

Moderator emeritus
Jul 24, 2002
24,638
61
Harrogate
Is the K&R book that good?

I see there is a second edition with around 200-odd pages.

As a total beginner would I struggle with this book?
Also can I use xCode to compile / run the examples / exercises in the book on?
It is the book written by the guys who designed an implemented C. As such it has everything. The book recommended when I was at Uni was "A Book on C" by Kelly and Pohl. It was good enough to learn from
 

Tander

macrumors 6502a
Original poster
Oct 21, 2011
676
1
Johannesburg, South Africa
It is the book written by the guys who designed an implemented C. As such it has everything. The book recommended when I was at Uni was "A Book on C" by Kelly and Pohl. It was good enough to learn from
Having done a little C (From current book ) - maybe I should just read THE book of C and see how it goes?

If I find it difficult maybe I will get another book with a different learning style.
 

Duncan C

macrumors 6502a
Jan 21, 2008
853
0
Northern Virginia
Is the K&R book that good?

I see there is a second edition with around 200-odd pages.

As a total beginner would I struggle with this book?
Also can I use xCode to compile / run the examples / exercises in the book on?
I've read both the K&R book and the "A book on C" book by Kelly and Pohl. The K&R book is better written.

K&R is very clear and well written. It requires work from you in order to learn from it. If you read the entire teaching section of the book and do all the exercises, you will have a good working knowledge of C (including pointers) when you are done.
 

Tander

macrumors 6502a
Original poster
Oct 21, 2011
676
1
Johannesburg, South Africa
I've read both the K&R book and the "A book on C" book by Kelly and Pohl. The K&R book is better written.

K&R is very clear and well written. It requires work from you in order to learn from it. If you read the entire teaching section of the book and do all the exercises, you will have a good working knowledge of C (including pointers) when you are done.
Thanks Duncan. Would you say it's better to put down the Objective-C book and pickup the K&R book and finish it. Then carry on with the OC book?
Or side by side?

Was planning on reading both on a per chapter basics. So read chapter one of the K&R book. Then read the current chapter that I am on with the second book - rinse and repeat?
 

Duncan C

macrumors 6502a
Jan 21, 2008
853
0
Northern Virginia
Thanks Duncan. Would you say it's better to put down the Objective-C book and pickup the K&R book and finish it. Then carry on with the OC book?
Or side by side?

Was planning on reading both on a per chapter basics. So read chapter one of the K&R book. Then read the current chapter that I am on with the second book - rinse and repeat?
If you were reading the Big Nerd Ranch Objective C book I would say you could just read that book, as the first several chapters teach you a crash course in C.

I'm not as familiar with the other book even though I own it. (I teach classes on this stuff sometimes so I have quite a few books at different levels.)

I would not suggest reading a chapter of K&R, then a chapter of Objective C, then another chapter of K&R. That's going to leave you very confused.

If you're going to study C, read the entire K&R teaching section and do all the exercises, including creating linked lists, etc. If you do that, you will have not only a solid grounding in C, but a solid grounding in computer science. If I remember correctly, it goes through exercises in Linked Lists, binary trees, stacks, etc. Great fundamentals that many people starting out never get.

Expect it to hurt your head more than a little. Remember that by reading all of K&R you're covering a lot of the fundamentals of computer science, written by the guys who created UNIX and C.
 

Tander

macrumors 6502a
Original poster
Oct 21, 2011
676
1
Johannesburg, South Africa
If you were reading the Big Nerd Ranch Objective C book I would say you could just read that book, as the first several chapters teach you a crash course in C.

I'm not as familiar with the other book even though I own it. (I teach classes on this stuff sometimes so I have quite a few books at different levels.)

I would not suggest reading a chapter of K&R, then a chapter of Objective C, then another chapter of K&R. That's going to leave you very confused.

If you're going to study C, read the entire K&R teaching section and do all the exercises, including creating linked lists, etc. If you do that, you will have not only a solid grounding in C, but a solid grounding in computer science. If I remember correctly, it goes through exercises in Linked Lists, binary trees, stacks, etc. Great fundamentals that many people starting out never get.

Expect it to hurt your head more than a little. Remember that by reading all of K&R you're covering a lot of the fundamentals of computer science, written by the guys who created UNIX and C.
Thanks Duncan.

I'll finish the BNR book first and will start K&R book as weekend project (IE read it every weekend) as I cannot read it while at work as I have some deadlines to meet.

With regards to that K&R book - is it possible to follow it properly on my MacBook using xCode - or will I need a different compiler?