Why retain a static variable? - objective-c

Isn't it unnecessary to retain a static variable since it stays around for the duration of the program, no matter if you release it?
See this code:
https://github.com/magicalpanda/MagicalRecord/blob/master/Source/Categories/NSManagedObjectContext+MagicalRecord.m#L24-29

I'm assuming you mean a static object pointer, such as static NSString *foobar;.
Such variables indeed have a lifetime as long as the application, but the variables we're talking about are pointers only. In Objective-C, objects are always dynamically allocated, and so we always address them with a pointer to their type, but the underlying data for an object is still present out in the dynamically allocated wild blue yonder.
You must still retain the object because, while the pointer to the object will never go out of scope, the object itself can be deallocated just like any other object, and so your pointer will end up pointing to garbage, or worse, another unrelated object.

A simplified version of Jonathan Grynspan's accepted answer:
The retain isn't for the variable which points to an object. That variable will last forever because it's static. The retain is for the object the variable points to. Without the retain the object could (and should) be deallocated. Then you've got a variable pointing to a thing which will cause a sigabrt. This variable pointing nowhere is known as a "dangling pointer."
For the ARC context, the best thing to do is declare the static variable as strong, so something like this:
static ThatClass * __strong thatStaticVariable;
This ensures that the object that thatStaticVariable points to will be a valid object (i.e., never gets deallocated) once assigned. However, you don't actually need the __strong keyword at all, because it's the default (so sayeth the docs, thanks to #zpasternack), so just use
static ThatClass *thatStaticVariable;
and you're good.
Note: forever = while the application is running

Related

Does objective c compiler automatically set retain in property setting methods?

In Objective C, if I have a class, within the class a method that creates a string using some convenience method and set the property NSString pointer to the newly created string. In this case, because the string is created using convenience method, it will have one owner which is the autorelease pool. When I assign the string to the property NSString pointer, will the compiler set the property as an owner to that string by inserting a retain call?
I think it should. Otherwise, when the autorelease pool is drained, the string will be released. However, if the object of the class still lives outside the autorelease pool, the property will point to memory that is already released, which causes a premature deallocation issue. In this case, there should be a retain call to set the object as a new owner to the string. Am I right on this?
The phrase "assign the string to the property NSString pointer" is a bit ambiguous. If you use the property setter either as a method invocation or with dot syntax the memory management specified or defaulted for the property will be used. If you assign directly to the underlying pointer, then you are bypassing the property attributes and the retain state will remain whatever it was before assignment.

Does copy also transfer the retain count?

Suppose I have an object, for example an NSString, with retain count 5. When I call copy on it, I get a new copy of the object; does this new object have the retain count of its original object ?
It depends. copy is a convenience method for copyWithZone:,
and the "NSCopying Protocol Reference" states:
Your options for implementing this protocol are as follows:
Implement NSCopying using alloc and init... in classes that don’t
inherit copyWithZone:.
Implement NSCopying by invoking the
superclass’s copyWithZone: when NSCopying behavior is inherited. If
the superclass implementation might use the NSCopyObject function,
make explicit assignments to pointer instance variables for retained
objects.
Implement NSCopying by retaining the original instead of
creating a new copy when the class and its contents are immutable.
(I have modified the following two statements after all that feedback.)
For example, NSString is an immutable object, and copy just retains the object
and returns a pointer to the same object. Retaining the object might increase the
retain count, but not necessarily (as in the case of string literals.)
Copying an NSMutableString would probably create a new object and return that.
The new object would have its own retain count independent of the original object.
But you should not care about the difference. With manual reference counting,
copy returns an object that you own and have to release eventually.
With ARC, the compiler with automatically handle that.
copy returns an object that is a semantic [shallow] copy(1) of the object. What the copy method returns is an implementation detail; it may return the same object, it may return a different instance of the same class, or it might even return an instance of a different class.
Doesn't matter.
What matters is that the returned object, under manual retain/release, has a retain count of +1. Not 1, but +1. It might actually be 1, 42, 981, or -1. Doesn't matter.
All that matters is that you must balance that retain with a release or autorelease somewhere if you want to relinquish the object back to the system. Which may not actually cause it to be deallocated; that is an implementation detail of no concern (until optimization time, anyway).
(1) semantic [shallow] copy means that the object returned is an effective shallow copy. The state contained within the copied object (but not within objects contained within the object -- that is the shallow part) will not change when the original object changes state. For a mutable object, copy must actually create a new instance of some object -- most likely an immutable variant class -- that can contain the original state.
For an immutable object, the copy method might be simply implemented as return [self retain];. Or, in the case of static NSStrings (NSCFStrings), it might simply be return self; as retain/release/autorelease are no-ops on such strings.
No, a copied object will have a retain count of 1, just like a newly initialized object.
I highly recommend you read the Memory Management Guide if you wish to learn more.
If you're new to iOS development, the iOS App Programming Guide should be read first, and is a great use of your time.
I just noticed you didn't tag this as iOS specific, if you're coding for Mac, the Programming with Objective-C guide might be more appropriate for you.
To really get your head around this issue, don't think in terms of retain count, think in terms of pointer ownership (like ARC does).
If an object has a "retain count" of 5, that means five pieces of code somewhere are each holding a (strong) pointer to its memory address. If you copy that object, you get a pointer to the address of the new, copied object. The other five pieces of code are still pointing to the original object. There's only one piece of code pointing to the new object, so its "retain count" is one.
As noted in other answers, the Memory Management Guide definitely helps make this all clear.
Why did I put "retain count" in quotes? Because it's only useful as a general concept -- you shouldn't be using retainCount directly, or you'll hear from #bbum.
Objective-C plays some clever tricks when you ask it to copy objects, and as a result retain counts might not be what you think they should be.
Let's say you have an object pointer x with a retain count of n, and call the copy method which returns an object pointer y.
NSObject* x = ...;
NSObject* y = [x copy];
Then the rule is that if you release x n times, and release y once, all objects will be gone. Usually this is achieved by leaving x unchanged, and giving y a retain count of 1.
However, if x points to an immutable object, then Objective-C may decide that no copy needs to be done. The result is that y = x. Still, the rule above still applies: Releasing x n times and y once (even though they are the same object) will free all the objects involved. That's achieved by the copy method returning x with a +1 retain count.
Copy on mutable object like NSMutableArray will create a new copy and retain count will be 1 while copy immutable object like NSArray will point to same reference and increase the retain count by 1.

Objective C: Returning Objects from Methods

I'm learning how to program, and starting off with Objective C. I'm trying to understand exactly what happens when an object is allocated from within a method.
-(Fraction *) add: (Fraction *) f
{ //'result' will store the result of the addition
Fraction *result = [[Fraction alloc]init];
result.numerator = (numerator*f.denominator + denominator*f.numerator);
result.denominator = denominator*f.denominator;
[result reduce];
return result;
}
I understand that I can create an object to store 'result' in when it is returned,
tempStorageObject = [aFraction add: bFraction];
and that i am then responsible for releasing it, but what happens when I don't store it, as in:
[aFraction add: bFraction];
NSLog(#"%i/%i", result.numerator, result.denominator); //result object not declared in main
I am told that I have an undeclared identifier. I get that, but what exactly happens to 'result' after using my 'add' method. Where does it go? Shouldn't I be able to access its variables since it was created and returned in the method? Obviously not, but I'm not clear on why. I've tried re-reading my book and searching this forum but I can't find a clear answer. Thanks. (First post)
Four different things:
Properties
Local variables
Function return values
Heap storage
"I get that, but what exactly happens to 'result' after using my 'add' method. Where does it go?"
It's a local variable. It's gone.
"Shouldn't I be able to access its variables"
Seeing your comment, it looks like you mean access by dot notation. No, dot notation is for properties.
"since it was created"
Dot notation does not give you access to local variables.
"and returned in the method?"
Dot notation does not give you access to function return values.
All of the first three things are pointers, when they refer to objects. The fourth thing is what they point to. When you do alloc, you create an object in heap storage. You then have instance variables, properties, local variables, and function return values refer to the heap storage. In a way you think of them as being the same thing as the object in heap storage. Syntactic sugar like dot notation helps you do that. Your object will last, but in this case the different variables that refer to it are limited in scope and come and go.
When you call alloc, an object is created on the heap.
When you assign it to result, result now has the same object.
When you return result, the local variable result no longer exists, the return value temporarily holds the same object, and the object still exists in the heap.
4a. When you assign the function result to tempStorageObject, another local variable (I guess), the function result goes away. It existed only temporarily to pass a value from inside the function to out. tempStorageObject now holds the object, and the object still exists in the heap.
4b. Instead if you don't assign the function result to anything, then the function result still goes away. But the object still exists on the heap. You have a problem. You have an object on the heap, but you can't refer to it directly there (unless you are good at guessing its address). Without being able to refer to it, you can't get it off the heap, which will be a major problem if you do that kind of thing over and over. The heap will start to get full with objects you can't get rid of and you'll run out of memory. That's what's called a leak.
The correct thing to do in this case is to return [result autorelease]. When you call [something autorelease], it adds "something" to an "autorelease pool" and then returns the same something.
You call alloc and create an object on the heap. Its retain count starts at 1.
You assign it to result, a local variable. Result has the object and it's on the heap.
[result autorelease]. result has the object, it's in an autorelease pool, and it's on the heap.
return that. result is gone, the return value has the object, it's in the autorelease pool, and it's on the heap.
5a. Assign the return value to tempStorageObject. The return value is gone, tempStorageObject has the object, it's in an autorelease pool, and it's on the heap.
6a. You leave the scope of tempStorageObject. tempStorage object is gone. The object is in an autorelease pool and on the heap.
5b. You don't assign the function result to anything. The function result is gone. The object is in an autorelease pool and on the heap.
7ab. The autorelease pool is drained. That is usually done from code in the main run loop provided by the system library, but you can do it yourself if you know how. All the objects in the autorelease pool, including the one we're paying attention to, are sent a release message. The object's retain count goes to 0.
8ab. With a retain count of 0, the object is removed from the heap. The object is in the autorelease pool.
9ab. The second thing drain does is remove all the objects from the pool. Now the object doesn't exist anywhere anymore.
You said you are familiar with release, so I just say you should use autorelease keyword, which releases the allocated object when no more code blocks need it, check document below, from Apple:
Memory Management Programming
The scope of alloc is global: once you have allocated an object, there is room for it in memory and that memory will remain allocated until the release count hits zero (or the app is terminated). Until then, the object will still exist.
The scope of a variable is much shorter. In your example 'result' goes out of scope right at the end of the method 'add'. But that variable is just a name, a reference to an object. So whoever is calling add, should make sure to do something with the returned object. Otherwise there is no more variable referring to the object and so it can not be released.

Difference between retain and copy?

What exactly is the difference between retain and copy? what is its significance on reference counting?
I know that when an object is allocated using alloc/retain, reference count goes up by one.
so how about using copy?
Another question relating to this is, the difference between using
#property(nonatomic, retain) and #property(nonatomic,copy)?
retain -- is done on the created object, it just increase the reference count.
copy -- create a new object
Answering your question to the best of my knowledge.
First, What exactly is the difference between retain and copy? what is its significance on reference counting?
retain - "Specifies that retain should be invoked on the object upon assignment. ... The previous value is sent a release message." So you can imagine assigning an NSString instance (which is an object and which you probably want to retain). So the retain count goes up by 1.
copy - "Specifies that a copy of the object should be used for assignment. ... The previous value is sent a release message." Basically same as retain, but sending -copy rather than -retain. if i remember correctly the count will go up by 1 too.
ok, now going into more detail.
Property attributes are special keywords to tell compiler how to generate the getters and setters. Here you specify two property attributes: nonatomic, which tells the compiler not to worry about multithreading, and retain, which tells the compiler to retain the passed-in variable before setting the instance variable.
In other situations, you might want to use the “assign” property attribute instead of retain, which tells the compiler NOT! to retain the passed-in variable. Or perhaps the “copy” property attribute, which makes a copy of the passed-in variable before setting.
I hope that helps. I found another post in here that might help you too.
Objective C - Assign, Copy, Retain
Cheers!
Jose
Generally speaking, copy creates a new object which has the same value with the original object, and sets the reference count of the new created object to 1 (By the way, reference count of the original object is not affected).
However, copy is equivalent to retain for immutable object, which JUST increate the reference count of the original object by 1.

How to check if an object is alloced or not?

Is there anyway to check if an object is alloced or not? Thanks.
Edit: Here's a better question. Is it ok to alloc an object that was already alloced without changing it's initial value?
You may intend how to check if a pointer points to an allocated object (which, as long as it stays in memory, is referenced by an unique memory address). In that case you could test if that pointer is nil in an if statement (or simply call is name in the condition, since objective-C inherits from C the evaluation of truth conditions, ie if it is not zero than it is true)
No. You can check whether an object is initialised assuming you control the object, by having it change its state once it's fully initialised. However an alloced object is just a block of memory with a pointer at the start. The only possible test would yield too many false positives.
Another way to look at it is this: there is no such thing as an object that has not been alloced.