Objective-C: Is an autoreleased initialisation followed by a retain wrong in a constructor? - iphone

In my #interface theres a NSArray *Monate followed by:
#property (nonatomic, retain) NSArray* Monate;
If i do:
filePath = [[NSBundle mainBundle] pathForResource:#"SomeFile" ofType:#"plist"];
self.Monate = [NSArray arrayWithContentsOfFile:filePath];
in the constructor, it gets set to an autoreleased object (is that correct?).
So should I do a [Monate retain] afterwards?

This code is correct; you should not add a retain call.
+[NSArray arrayWithContentsOfFile:] will return an autoreleased NSArray. Passing that to -[YourClass setMonate:] will retain the object and assign to the backing ivar. After the constructor returns, the new NSArray will have a retain count of 2 and be added once to the current autorelease pool (resulting in a net retain count of 1)
As long as you release the array in your dealloc, this code is correct.

You should NOT do a retain after. By setting a #property of retain, some special things happen when you use the self.Monate setter
1) Anything in the Monate instance variable, if any, will get a release.
2) the new assignment will get a retain.
if you were to use #property of assign, then you would have to retain, but you are fine the way you are.
As a side note, in objective-c, Capitalized words are usually reserved for Class names. I sugges changin it to "monate" instead of "Monate" as this could lead to confusion down the road

[NSArray arrayWithContentsOfFile:]; returns an autoreleased array which will require retaining if you want it to hang around longer than the end of the method.
Notice how your property declaration specifies 'retain'. This means that any self.property = x; calls you do will retain the object you pass in.
So what you are doing there is correct. Just remember to do self.property = nil; in your dealloc method.
Setting a property to nil will release the old object and set the pointer to nil, which is the correct way to do it.

Related

Does NSStringFromCGPoint return an autoreleased object?

Question #1
Will NSStringFromCGPoint() return an autorelease object or does the object needs to be released?
Question #2
When you have a property : #property (nonatomic, retain) NSString *someString;
And you set it like so: self.someString = [[[NSString alloc] initWithString:#"Something"] autorelease];
Is this:
[someString release];
someString = nil;
equal to
self.someString = nil;
I haven't checked that one specifically, but by convention those sorts of functions return autoreleased objects. You might be able to test this yourself by setting up a minimal, non-ARC project and calling -retainCount on what you get out of the function, but I'm not sure. (And in general, retainCount isn't something you want to use.)
Yes. The synthesized setter looks something like:
- (void)setSomeString:(NSString *)string
{
if (string != someString) {
[someString release];
}
someString = [string retain];
}
So, whether you call it explicitly or using the dot notation, the old value gets released (and the underlying ivar gets set to nil or whatever you pass in).
Also, I'm not sure if you were just doing it for a random example, but you don't have to wrap a string literal in memory management code to pass it to the property accessor. (That is, self.someString = #"Something" is fine.)
Does the call include the term "new", "alloc", "copy", or "create"? If not, you're getting back an object that you do not own (you may assume it is either autoreleased or that the reference is owned elsewhere).

Memory allocation / release for NSString

I have a class that adopts the MKAnnotation protocol. Along with the two "title and "subtitle" methods to implement, I wanted to add two NSStrings, one to represent each line in a typical US address. For example:
addressLine1 = 123 street
addressline2 = northridge, ca 91326
My subtitle method currently looks like:
- (NSString *)subtitle {
NSMutableString * ret = [NSMutableString stringWithCapacity:kDefaultStringCapacity];
if (streetAddress) {
[ret appendString:streetAddress];
addressLine1 = [[NSString alloc] initWithFormat:streetAddress];
}
... more code
When would I release addressLine1? Because it is a property that I declared with (nonatomic, retain), I already released it in my dealloc method. Or am I to use a class method or autorelease the string? Thanks.
If you autorelease address1, you will lose ownership on the object and without any other owners, it will get deallocated. You would need to autorelease it if you were doing,
self.address1 = [[NSString alloc] initWithString:streetAddress];
which is wrong as you would've taken ownership twice and relinquished it only once in the dealloc method. Right way would've been,
self.address1 = [[[NSString alloc] initWithString:streetAddress] autorelease];
The direct assignment above works only if it were to be assigned a value once. If it is to be assigned again, you would lose the reference to the earlier reference and your application will leak. So it would be good process to use the property accessors here which would ensure that the older values are deallocated.
Another thing with strings is that you would copy them as you wouldn't want them to mutate after assignment so the property should be declared as #property (nonatomic, copy) rather than what it is now.
If your property is (nonatomic, retain), then you're going to leak the addressLine1 resource if you don't explicitly release it. I'd release it as soon as you're done with it. The property should then be released in your dealloc method as you are currently doing.
Somewhat unrelated to the question, but still related, is that anytime you have an object that implements the NSCopying protocol, such as NSString in this case, you should use copy instead of retain. Here's a SO question that provides some great information.

When to access property with self and when not to?

Can anyone explain the difference between setting someObject = someOtherObject; and self.someObject = someOtherObject; if someObject is a class property created with #property (nonatomic, retain) SomeType someObject;
To clarify I have something like:
#interface SomeClass : NSObject {
SomeType* someObject;
}
#property (nonatomic, retain) SomeType* someObject;
#end
I have noticed I get EXC_BAD ACCESS sometimes when I use the property without self and it seems quite random. When I use self my program acts as it should be. I don’t get any compiler errors or warnings when I skip self so I guess it is somehow valid syntax?
self.someObject = someOtherObject makes use of the property. Properties generate setters and getters for you. In your case, you gave the retain attribute to the property, which means that an object set via this property will automatically receive a retain message which increases its retain count by 1. Additionally, the old value of the member variable is sent a release message which decreases its retain count.
Obects are being deallocated, when their retain count reaches 0. You get an EXC_BAD_ACCESS ecxeption if you try to access a deallocated object (e.g. if you try to release it too often).
In your case:
SomeOtherObject *soo = [[SomeOtherObject alloc] init]; //retain count: 1
self.someObject = soo; //soo's retain count is now 2
[soo release]; //soo's retain count is 1 again, as self still uses it.
[self doSomethingWithSoo];
However, if you do not use the setter, you must not release soo.
SomeOtherObject *soo = [[SomeOtherObject alloc] init]; //retain count: 1
someObject = soo; //soo's retain count is still 1
[soo release]; //soo's retain count is 0, it will be deallocated
[self doSomethingWithSoo]; //will fail with an EXC_BAD_ACCESS exception, as soo does not exist anymore.
Properties are just a convenient way to access the data. So when you are declaring the property #property (nonatomic, retain) SomeType* someObject; this means that during access there would be synthesized 2 methods:
getter:
-(SomeType*) someObject {
return someObject;
}
setter
-(void) setSomeObject:(SomeType*) obj {
[someObject release];
someObject = [obj retain];
}
So the main difference between properties and ivars is that properties dynamically creating the setter/getter methods (and you can override them). But when you're writing someObject = new_val, you're just copying the reference to the memory location. No additional work is done there except one assembly instruction.
There is one more thing to mention: atomic and nonatomic.
With atomic, the synthesized setter/getter will ensure that a whole value is always returned from the getter or set by the setter, regardless of setter activity on any other thread. That is, if thread A is in the middle of the getter while thread B calls the setter, an actual viable value -- an autoreleased object, most likely -- will be returned to the caller in A.
In nonatomic, no such guarantees are made. Thus, nonatomic is considerably faster than atomic.
Edit: so if you have some variable, that is accessed from different threads or/and some additional work has to be done (e.g. retain, raise some flags ...), then your choice is property. But sometimes you have a variable, that is accessed very often and access via property can lead to a big overhead, because processor has to perform much more operations to synthesize and call method.
It's all about memory management.
Your class property someObject have generated accessors with annotation #property / #synthsize in your .h / .m files.
When you are accessing you property with someObject, you directly access the property. When you are accessing self.someObject you are calling your accessor [self someObject] whitch take care of memory management for you.
So when you need to assign a class property it's cleaner to do self.someObject = someOtherObject; because you use the setter and does not have to take care about releasing and retaining. When your setter is generated with #property (nonatomic, retain) so it will take care about retaining for you.
The difference between the two is:
1) when you do not use "self." you are assigning the result directly to the member variable.
2) when you are using "self." you are calling the setter method on that property. It is the same as [self setMyObject:...];
so in case of self.myobject, it keeps its retain, and in other case, (without self), if you are not using alloc, then it will be treated as autoreleased object.
In most cases you will find you want to use "self.", except during the initialization of the object.
By the way, you can also use self.someObject = [someOtherObject retain] to increase retain counter

assignment of property and allocation leads to retain count of 2

I had a look at instruments and I saw that the alloc increased the retain count by 1. So far everything clear. But the assignment of the class to my property also increased the retain count to 2.
self.myProperty = [[MyClass alloc] init]
Vs.
MyClass *myCreatedVariable = [[MyClass alloc] init];
self.myProperty = myCreatedVariable
To decrease the retain count to zero I released myCreatedVariable right after my calls. The myProperty instance variable is released in the dealloc method. Am I right that a property only is released in the dealloc method?
Now to my question:
Is the allocation and the assignment to a property always creating a retain count of 2? So don't use
self.myProperty = [[MyClass alloc] init]
because the retain count is never getting zero? Or is this only the case if I'm allocating a class?
Cheers
Your property is most probably declared as retaining or copying:
#property (retain) MyClass myProperty;
or
#property (copy) MyClass myProperty;
This calls your setter that does what its attributes say: retain! Copy will also retain.
Although it worked here, you shouldn't try to get useful information out of the retainCount property.
I cannot recommend the Memory Management Programming Guide highly enough, well worth a first, second and third read. :-)
Creating objects using the init function returns a retained instance by default. ( See the Memory Management Programming Guide)
If the property is defined with the 'retain' attribute, then your object is retained one more time.
So the right way to do is
MyClass *myCreatedVariable = [[MyClass alloc] init];
self.myProperty = myCreatedVariable;
[myCreatedVariable release];
By the way this is good to know also when you using Arrays.
Once an object created with the alloc and init functions is added into an array, it is retained by the array, so you can release your instance after you add it in the array.
In both case, retainCount is then 1, as expected.
if your property is defined with the 'copy' attribute, you can release the object as well, and even kill it, since it has been fully copied and retained once.
( I think there is something there if you use garbage collection instead of managed memory... To check.. )
Finally if your property is set with the 'assign' attribute, only the object's adress is copied, so you should not release your original object in this case.
It is however not recommanded to use the 'assign' attribute, since you may set property with objects that you did not create yourself, and which could be released anytime, letting your property pointing in the fields...
Finally, don't forget that static creators in Cocoa do not return retained objects.
( This is a convention, exceptions may exist... )
example:
NSArray* myArray = [NSArray array];
self.myProperty = myArray;
In this case, do not release myArray, it is already done in the creator function.
Assigning it to the property will retain it.( with retain or copy attribute).
Hope it will help,
Cheers
#property (nonatomic, retain) NSString *strURL;
This will keep the Retain count = 0
When you use an accessor to initialize the strURL then the retain count increases to 1
self.strURL = [NSString stringWithString:#"http://192.168.1.25/shop.php"];
However if you had done this without using the accessor then your reference count would have remain same that is 0
strURL = [NSString stringWithString:#"http://192.168.1.25/shop.php"];
Note that when you use this variable with retain count as 0, the auto release works and the variable gets released, giving "SIGABART" error or “EXC_BAD_ACCESS” when you try to access its value.
Generally when you are using init to get your variables initialized the best practice is to use alloc.
strURL = [[NSString alloc] stringWithString:#"http://192.168.1.25/shop.php"];
Hope this helps!
Sorry ? Noooo. I'm afraid programming is trying to know things we don't know everyday !
Static creators are convenience function, to ease common objects allocations.
A lot of classes in the cocoa framework have this kind of functions. Arrays, Dictionary, Paths, ...
Let's take your class as an example, and suppose you often have to create objects of this class. You may write a function in your 'myClass' implementation like:
+(MyClass*)myClass
{
MyClass *myNewInstance = [[myNewInstance alloc] init];
return [myNewInstance autorelease];
}
Then you can rewrite your original example as:
..
self.myProperty = [MyClass myClass];
..
Straight!
Or you could write a method like
-(void)myFunction
{
MyClass* myTempObject = [MyClass myClass];
if (myTempObject) {
// do something with your temporary object
}
// Simply exit, object will be released later on.
}
It is much shorter ( we should handle the case where object creation failed ) ..
Note that this is all conventions, you can basically do has you like and create retained objects, or use a different name for the creator.
But it is safer to follow the framework rule, it then becomes a reflex when you code.
See methods like [NSDictionary dictionary], [NSArray array], [NSArray arrayWithObjects:] ,...
Cheers

Do I have a leak with this statement?

The statement is:
//Pass the copy onto the child controller
self.childController.theFoodFacilityCopy = [self.theFoodFacility copy];
My property is set to:
#property (nonatomic, retain) FoodFacility *theFoodFacilityCopy;
The reason I think I have a leak is because copy retains the value and then my dot syntax property also retains the value. Doubly retained.
What is the correct way of writing the above statement?
yes, you do have a leak there.
SomeClass *someObj = [self.theFoodFacility copy];
self.childController.theFoodFacilityCopy = someObj;
[someObj release];
This mirrors the recommended approach for initializing an object too:
SomeClass *someObj = [[SomeClass alloc] init];
self.someProperty = someObj;
[someObj release];
In both cases the first line returns an objects with a retain count of 1, and you treat it identically after that.
As mentioned by others, that is indeed a leak. If you expect to be using copies in this way, it’s likely your property should be declared copy instead and the synthesized accessor will do the work for you.
You are right. The cleanest way is something like
id temp = [self.theFoodFacitlity copy];
self.childController.theFoodFacilityCopy = temp;
[temp release]
You want to read the apple site on memory management a lot until these rules become second nature.
What is the advantage of doing this vs just setting the property to copy?
#property (nonatomic, copy) FoodFacility *theFoodFacilityCopy;