Explain object variable declaration and assignment - objective-c

In this snippet:
NSString *testString;
testString = [[NSString alloc] init];
Why, on the second line, do we not have to write *testString = ... in order to access the location where it's actually pointing?
After the first line, what is *testString and what is testString?

The first line you are creating the pointer of NSString type. Pointers in C++ and Objective-C are denoted by the asterisk (*) character when you declare them. The second line you are saying this pointer called "testString" references the memory location of the NSString object that you have allocated in memory.

All objects are referred to by pointers. The first line
NSString * testString;
declares the instance variable. If your variable type is an object (aside from type id), you need the *
from then on the reference to testString is pointer
If you create 2 strings. 2 physical objects are created (in memory)
NSString * testString = [[NSString alloc] init];
NSString * testString2 = [[NSString alloc] init];
//setting testString to testString2 will lose the pointer to testString for good
testString = testString2; //<--bad if you still care about testString (and leaks the memory too)
I recommend checking out Apple's guide on Objective-C. Specifically this section
http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/objectivec/Chapters/ocObjectsClasses.html#//apple_ref/doc/uid/TP30001163-CH11-SW1

Why, on the second line, do we not have to write *testString = ... in order to access the location where it's actually pointing?
The init method returns a generic pointer to an object -- its return type is id. testString is a pointer to an NSString, which is an object, so you are assigning a pointer to another pointer. Dereferencing the assigned-to pointer would be a type mismatch.
A variable name is a place (a label for a memory address) in which to put something. The type of the variable is the kind of thing that you can put there. In the case of a pointer, the kind of thing that you put in it is also a memory address. In order to get that address, you dereference the pointer. The kind of thing that you can put at that address is different from the kind that you put in the pointer itself.
After the first line, what is *testString and what is testString?
After the first line, *testString, or the thing at which testString points, is garbage (actually undefined). testString is a pointer (4 or 8 bytes depending on your system) to a address in memory, and it is also undefined.
After the second line, *testString is an NSString object. testString is still a pointer to an address, where there is a valid NSString object.

That's simply because we affect the pointer.
[[NSString alloc] init] returns a pointer to an NSString.
In Cocoa every object is dynamically allocated (as in malloc in C) and every NSObject is manipulated thru its pointer/address (in such a point that many ObjC programmer don't even know that they are manipulating pointers and not objects)

Related

NSString memory lifecycle

Trying to understand memory management in Objective C. Any help will be appreciated.
NSString *myString;
What above line does, does it allocate memory to myString? If so then how many bytes?
If declaration of myString allocate memory to myString object then how compiler or runtime system will know how big string myString object will receive. I mean string could be of any length. So how much memory should be allocated?
myString =[NSString stringWithFormat:#"Testing String"];
What will happened to the memory when object is no longer in use? Will the memory be released or will it be occupied by the content of myString until app is running?
NSString *myString; does not allocate a string. Rather it reserves enough bytes to hold a pointer to a string; the lifetime of that pointer is dependent upon where in code the line is placed (and is not otherwise controllable).
myString =[NSString stringWithFormat:#"Testing String"]; does the allocation*, and the string size is exactly enough to hold the string that results from your format; in this case enough for the characters "Testing String".
When the myString pointer goes out of scope, and assuming there have not been any other copies of the string, and if you're using ARC, the string will be deallocated. If you're not using ARC, you have the responsibility of deallocating it when you're done with it.
Allocation:
Generally speaking, an Objective C allocation will look like pointer = [Class alloc]; and in practice it's more likely to look like pointer = [[Class alloc] init]; (or any of the class's other init* methods). The [NSString stringWithFormat:(NSString *), ...] method is a convenience to lead to (either exactly or in essence) [[NSString alloc] initWithFormat:(NSString *), ...].

Pointers on Objective-c

From what I understand (and please correct me if I'm wrong):
int x, count = 10;
int *hello;
hello = &count;
x = *hello;
Here the variables x and count are declared to be of type integer. Additionally, the variable count is assigned the value of 10.
hello is a pointer to type integer. hello is then assigned the address of count.
In order to access the value of count, hello must have an asterisk in front of it, ie, *hello.
So, x is assigned the value of whatever is in count and in this case, 10.
However...
Fraction *myFraction = [[Fraction alloc] init];
[myFraction someMethod];
Here, if I understand correctly, myFraction is a pointer to an instance of Fraction class.
myFraction is pointing to (or rather assigned the address of) an object which has been assigned memory and initialised.
Surely, in order to access the object that myFraction points to, I ought to write:
[*myFraction someMethod];
Given the way in which x accessed the value of count, surely in order to access the object, one ought to write this and not:
[myFraction someMethod];
In addition, if I have
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *str = #"Programming can be a headache";
NSLog (#"%#\n", str);
Why is str being treated as an object above? Or is str an object and in which case, why would I want to make it point to an instance of NSString class? Surely, I ought to be able to just assign an object to str?
All the usage of objects in objective c is done through object references, e.g. pointers.
The Objective C syntax lets you treat objects without dereferencing them, this is different than C / C++ for that matter.
str is an object reference of type NSString (as myFraction) and #"Programming can be a headache" is an object reference of type NSString as well, so you can assign it to str.
Additional to Binyamin
Everything inside the brackets [ ] is objective-C and not simple C (so [*object message] is not common to use)
[object message], you send the "message" to your object, and the object responds with something (he can return something or he can do something without anything in return).
Everything with a * on the left is pointer. So *str is a pointer. And where is it point? to an object NSString. The #"blabla" returns the adress of one CONSTANT string that has generated directly by the compiler.
NSLog (#"%#\n", str); here the %# calls the +Description class method of NSString object called str. By default the description of an NSString Object returns the value of the string (the text). %# is not a simple replace like the %d with numbers (int,double etc). All objects have +Description method that inherit from the NSObject (note is Class method and not instant).
description
Returns a string that represents the contents of the receiving class.
(NSString *)description

NSString allocation and initializing

What is the difference between:
NSString *string1 = #"This is string 1.";
and
NSString *string2 = [[NSString alloc]initWithString:#"This is string 2.];
Why am I not allocating and initializing the first string, yet it still works? I thought I was supposed to allocate NSString since it is an object?
In Cocoa Touch,
-(IBAction) clicked: (id)sender{
NSString *titleOfButton = [sender titleForState:UIControlStateNormal];
NSString *newLabelText = [[NSString alloc]initWithFormat:#"%#", titleOfButton];
labelsText.text=newLabelText;
[newLabelText release];
}
Why do I not allocate and initialize for the titleOfButton string? Does the method I call do that for me?
Also, I'm using XCode 4, but I dislike iOS 5, and such, so I do not use ARC if that matters. Please don't say I should, I am just here to find out why this is so. Thanks!
The variable string1 is an NSString string literal. The compiler allocates space for it in your executable file. It is loaded into memory and initialized when your program is run. It lives as long as the app runs. You don't need to retain or release it.
The lifespan of variable string2 is as long as you dictate, up to the point when you release its last reference. You allocate space for it, so you're responsible for cleaning up after it.
The lifespan of variable titleOfButton is the life of the method -clicked:. That's because the method -titleForState: returns an autorelease-d NSString. That string will be released automatically, once you leave the scope of the method.
You don't need to create newLabelText. That step is redundant and messy. Simply set the labelsText.text property to titleOfButton:
labelsText.text = titleOfButton;
Why use properties? Because setting this retain property will increase the reference count of titleOfButton by one (that's why it's called a retain property), and so the string that is pointed to by titleOfButton will live past the end of -clicked:.
Another way to think about the use of retain in this example is that labelsText.text is "taking ownership" of the string pointed to by titleOfButton. That string will now last as long as labelsText lives (unless some other variable also takes ownership of the string).

Memory Management Questions

I have been programming in Objective-C for a couple weeks now, and I think its time that I think more about my memory management and so I have a couple scenarios I would like clarification on.
NSString *myString = #"Hello, World";
If I were to on the next line do
NSString *anotherString = myString;
Is it getting copied? or is another string just a pointer to myString? if it's just a pointer how would I make anotherString a copy of myString that has its own memory?
What if I were to
[anotherString release];
What actually gets released, just anotherString, or does myString go away too?
Then if I were to do
anotherString = nil;
Does that actually free up memory and for use or does it still have the space allocated with empty memory? Obviously the pointer can still be used. What does it do to myString?
This will really help me become better at managing the memory properly, instead of just [object release]; randomly and causing crashes.
Thank you VERY MUCH in advance to whoever replies.
When you do:
NSString *myString = #"Hello, World";
NSString *anotherString = myString;
...you're creating a single NSString instance, and two pointers to it. So to answer your questions, no it is not being copied. Yes, anotherString is just a pointer, and so is myString, the actual NSString instance is off in memory-land, at the address that both pointers are now pointing to.
To make a copy of the string, you would do:
NSString *anotherString = [myString copy];
When you do:
[anotherString release];
The NSString instance that anotherString points to is released. Nothing happens to anotherString itself. It continues to point to your now-invalidated object instance. If myString was pointing to the same instance, then yes, this causes myString to "go away" as well.
And if you do:
anotherString = nil;
...then you've caused a memory leak, because you reassigned the pointer without releasing the thing it was pointing at. Except not in this case because #"Hello, World" is a literal value that is loaded onto the stack and is not retained by your code.
In any case, setting anotherString to nil does nothing to your string, it just changes what anotherString points to. Your actual NSString instance is still off in memory-land, completely unaware that you just threw away your reference to it (possible exception: reference counted/garbage collected environments).
And yes, calling [object release] randomly will cause crashes. As a general rule you should only call release on something if:
You called alloc and init... on it.
You called retain on it.
You obtained the object as a result of calling copy on some other object.
Note that these stack, so if you alloc something, retain it, and then copy it, you need to have 3 calls to release, two for the object that you alloc'ed, and one for the copy.
As a side note, you may find it clearer to write your object declarations like:
NSString* myString = #"Hello, World";
NSString* anotherString = myString;
...which makes it more obvious that what you are declaring are pointers to NSString's and not NSString's themselves. Personally I think your original syntax, while commonly used, is also backwards.
This string:
NSString *myString = #"Hello, World";
is created on the stack. It's loaded into memory when the app starts. You don't own the memory backing the object, and therefore shouldn't release it.
If you want to copy a string to the heap (where you can manage the memory), you simply do this:
NSString *anotherString = [myString copy];
Then you're responsible for releasing that object when you're done with it.
[anotherString release];
Setting a pointer to nil just clears the pointer, not the object it's pointing to. It's still in memory.
NSString *anotherString = myString;
--- This is just a pointer assignment
--- You can copy myString using [myString copy]
[anotherString release];
--- You are releasing the owner ship of the anotherString (please read about retain count concept)
anotherString = nil;
--- you are just assigning the pointer to nothing.
I suggest Please read more about memory management apple documents ...

When not to alloc and init an NSString

Whenever I need to create a new NSString variable I always alloc and init it. It seems that there are times when you don't want to do this. How do you know when to alloc and init an NSString and when not to?
Whenever I need to create a new NSString variable I always alloc and init it.
No, that doesn't make sense.
The variable exists from the moment the program encounters the point where you declare it:
NSString *myString;
This variable is not an NSString. It is storage for a pointer to an NSString. That's what the * indicates: That this variable holds a pointer.
The NSString object exists only from the moment you create one:
[[NSString alloc] init];
and the pointer to that object is only in the variable from the moment you assign it there:
myString = [[NSString alloc] init];
//Or, initializing the variable in its declaration:
NSString *myString = [[NSString alloc] init];
Thus, if you're going to get a string object from somewhere else (e.g., substringWithRange:), you can skip creating a new, empty one, because you're just going to replace the pointer to the empty string with the pointer to the other one.
Sometimes you do want to create an empty string; for example, if you're going to obtain a bunch of strings one at a time (e.g., from an NSScanner) and want to concatenate some or all of them into one big string, you can create an empty mutable string (using alloc and init) and send it appendString: messages to do the concatenations.
You also need to release any object you create by alloc. This is one of the rules in the Memory Management Programming Guide.
If you want to initialise it to a known value, there is little point in using alloc, you can just use a string literal:
NSString* myStr = #"Some value";
If you want to initialise it with a format or whatever, but don't need it to stick around beyond the current autorelease pool lifetime, it's a bit neater to use the class convenience methods:
NSString* myTempStr = [NSString stringWithFormat:#"%d", myIntVar];
If you need its lifetime to go beyond that, either alloc/init or else add a retain to the previous call. I tend to slightly prefer the latter, but the two are pretty much equivalent. Either way you will need a balancing release later.
Note that, since NSString is not mutable, this sort of thing is not only unnecessary but actively wrong:
// don't do this!
NSString* myStr = [[NSString alloc] initWithString:#""];
myStr = someOtherStr;
since it leaks the initial placeholder value.
It seems that there are times when you don't want to do this.
I can't think of any time when I would want to alloc/init a NSString. Since NSStringgs are immutable, you pretty much always create new strings by one of:
convenience class method e.g.
NSString* foo = [NSString stringWithFormat:...];
literal
NSString* foo = #"literal";
NSString instance method
NSString* foo = [bar uppercaseString];
copy from mutable string
NSString* foo = [mutableBar copy]; // foo needs to be released or autoreleased in this case
I'm guessing that you are referring to using StringWithString or similar instead of initWithString? StringWithString alloc and inits for you under the hood and then returns an autoreleased string.
If you don't need to do any string manipulation other than to have the string, you can use NSString *str = #"string";
In general with iOS, the tighter you manage your memory the better. This means that if you don't need to return a string from a method, you should alloc init and then release it.
If you need to return a string, of course you'll need to return an autoreleased string. I don't think its any more complicated than that.