Why would you use a class method constructor versus alloc/init? - objective-c

There are two choices for constructors in Objective C/Cocoa:
1. Class Constructor
Product *product = [Product productWithIdentifier:#"Chocolate"];
// Use product
2. Alloc/init Constructor
Product *product = [[Product alloc] initWithIdentifier:#"Chocolate"];
// Use product
[product release];
What I do
I tend to use the class method just because it looks cleaner and you don't need a release.
I see a lot of alloc/init - what's the advantage to doing it this way?
My Question
Which one is preferable? Or is it just a matter of taste?
Code
For context, the class Product would have the following:
+(Product *)productWithIdentifier:(NSString *)identifier_ {
return [[[[self class] alloc] initWithIdentifier:identifier] autorelease];
}
-(Product *)initWithIndentifier:(NSString *)identifier_ {
self = [super init]
if (self) {
identifier = identifier_;
}
return self;
}

If you're using ARC, there's not that much of a difference between the two. If you're not using ARC, the difference is extremely important.
The alloc/init combination gives you an owning reference. That means you must release it later on. The classnameWithFoo variant returns a non-owning reference. You may not release it.
This follows the usual Cocoa naming conventions. All methods return non-owning (autoreleased) instances, except for the methods that start with alloc, copy, mutableCopy and new. These return owning references that you must release.
Which one to use is mostly a matter of taste. However, if you need temporary objects that you can dispose quickly the alloc variant results in slightly fewer method calls (the autorelease) and in a loop, it also reduces the maximum memory footprint. However, in most cases this reduced cost is neglectable.

IMO, the biggest difference between the two approaches comes from the fact that using a "class constructor" you get an autoreleased object; this is the most convenient option when you:
assign the allocated object to a retain properties;
when you create "temporary" objects (think of the various NSString methods that build a string from another string: in many case it happens you need to "chain" such calls; the constructor allows you to "forget" about memory management);
when you add the object to some object that retains it (think: addSubview)
In such cases the syntactical advantage of "class constructor" is foremost, but I think it also makes your code "safer" in terms of memory management.
On the other hand, when you create an object to assign it to an assign property (or directly to an ivar for which you have no property), then alloc/init will do perfectly and be preferable to the "constructor" (IMO).
So, in the end, it depends on the way you are going to use the objects you allocate. The class constructor is a convenience method.

Related

When and when to not allocate memory to objects

NSArray *array = [dictionary objectForKey:#"field"];
and
NSArray *array = [[NSArray alloc] initWithArray:[dictionary objectForKey:#"field"]];
I see both kind of approaches very frequently in objective C code.
When tried to understand, I found both of them used in similar situation too, which makes contradiction. I am not clear on when I should use 1st approach and when 2nd one?
Any idea?
Detailed explanation and useful references are moms welcome.
First off, those two examples are doing slightly different things. One is retrieving something from an existing dictionary and one is creating a new array by retrieving something from an existing dictionary (the value of that key is an array).
But, if you're asking the difference between getting objects by alloc vs. convenience methods. ([NSString alloc] init vs [NSString stringWith ...), by convention, you own anything that you call alloc, new copy or mutableCopy on. Anything that you call that is not those, is autoreleased.
See the memory guide here. Specifically, look at the rules.
Getting an autoreleased object means it will go away at some point in the near future. If you don't need to hold onto outside the scope of that function, then you can call autorelease on it or use one of the convenience methods that's not alloc, etc...
For example:
// my object doesn't need that formatted string - create the autoreleased version of it.
- (NSString) description {
return [NSString stringWithFormat:#"%# : %d", _title, _id];
}
// my object stuffed it away in an iVar - I need the retained version of it. release in dealloc
- (void) prepare {
_myVal = [[NSString alloc] initWithFormat:"string I need for %d", _id];
}
In the first example, I created a convenience methods for others to call, my class doesn't need that object beyond the scope of that method so I create the autoreleased version of it and return it. If the caller needs it beyond the scope of his calling method, he can retain it. If not he can use it and let it go away. Very little code.
In the second example, I'm formatting a string and assigning it to an iVar variable that I need to hold onto for the lifetime of my class so I call alloc which will retain it. I own it and releasing it eventually. Now, I could have used the first version here and just called retain on it as well.
You have a fundamental misunderstanding of allocations versus instance methods.
The first example, NSDictionary's -objectForKey method, returns id, not an instance of NSDictionary, therefore it does not allocate or initialize the variable.
The second, however is the classic retain part of the retain-release cycle.
The two methods are fundamentally equal (if we are to assume that array is alloc'd but empty in the first, and nil in the second), and both get ownership of the array object. I would go with the second, as it guarantees a reference, and it's shorter.
What I think you're confusing this with are new and convenience methods. Convenience methods (like NSNumber's +numberWithInt:, NSString's +stringWithFormat:, and NSMutableArray's +array), return an autorelease instance of the class (usually). New takes the place of alloc and init in just one word.

Objective-c object releasing patterns

I've run into some unfamiliar Objective-c memory management code. What is the difference between:
// no property declared for myMemberVariable in interface
id oldID = myMemberVariable;
myMemberVariable = [MyMemberVariable alloc] init];
[oldID release];
and:
// (nonatomic, retain) property is declared for myMemberVariable in interface
self.myMemberVariable = [[MyMemberVariable alloc] init];
Thanks!
The second is technically incorrect, but the first probably stems from someone yet to embrace Objective-C 2.0 property syntax. It was added relatively recently if you're a long-time OS X developer (or an even-longer-time NextStep/OS X developer), so you do see people not using it without gaining any benefit or detriment by not doing so.
So the first is basically the same as:
[myMemberVariable release];
myMemberVariable = [[MyMemberVariable alloc] init];
Given that you have a 'retain' property, the correct version with the setter should be:
// this'll be retained by the setter, so we don't want to own what we pass in
self.myMemberVariable = [[[MyMemberVariable alloc] init] autorelease];
In the first example, you've got an instance variable. In the second, a property with auto memory management attributes (as indicated by the retain).
In the first example, you're allocating an object, assigning it to an instance variable, then releasing it. It also appears that you're also leaking the object that was previously assigned to it since you don't explicitly release it. (Maybe it's autoreleased, can't tell here).
In the second example, you're allocating an object, and assigning it to a property that is retaining it. This means you're going to leak it unless you explicitly release/autorelease it.
self.myMemberVariable = [[[MyMemberVariable alloc] init] autorelease];
or
MyMemberVariable *m = [[MyMemberVariable alloc] init];
self.myMemberVariable = m;
[m release];
It's much better to use properties as you get (most) memory management for free. For example, you won't have to worry about freeing a reference before assigning a new one.
The first form does not use properties. I don't see a good reason not to do:
[myMemberVariable release];
myMemberVariable = [[MyClass alloc] init];
Since the old value is definitely not the same as the new one, so there is no chance any old value is released before it can be retained again.
Properties have the advantage that, in newer compilers, they are synthesized by the compiler and simply do the right thing, i.e. they know how to retain the new and release the old value, if the type is one that must be retained or copied. This is not necessary for types like int, float, etc., since these are simple value types.
In other words, if you use dot notation, either on self or on some other object, you access the property and in fact call either the getter or setter methods, depending on the direction of assignment.
If you access the ivar (member variable) directly, you don't have the protection from the property and have to code retain/release yourself.
You can also write your own setters and getters, and then you'll also have to take care of memory management, where it applies. It does, however, give you more flexibility. You could log items, check the validity of the input, update internal state variables, etc.

Objective-C - Best practice for writing a simple method?

In the following function which one is the best practice?
To send an autoreleased object, and make the caller retain it?
or send an allocated object, and make the caller release it?
- (NSString*) convertDataToString :(NSData*)myData
{
//just an example, method might not exist
NSString *str = [[NSString alloc] initWithData:myData];
return str;
return [str autoRelease];
}
Following up on #Chuck's comment, -convertDataToString must not return an object that the caller must release. That would violate the Three Magic Words. If you do not have "copy," "alloc," or "new" in your name, the caller cannot be expected to release the object. If you have "copy" in your name or start with "new" or "alloc," then the caller must release the object.
Objective-C relies heavily on consistent naming and the names mean things. If you learn the naming, then you won't have any problems.
The memory management rules say your first example is — and this is a direct quote — wrong. It's not even a matter of preference, as some answers here seem to indicate. The caller does not normally own the object you return, so it should be autoreleased.
The specific example from the rules says this:
This is wrong. Following the ownership policy, it would result in a memory leak.
– (NSArray *)sprockets {
NSArray *array = [[NSArray alloc] initWithObjects:mainSprocket,
auxiliarySprocket, nil];
return array;
}
The object’s reference to the new array object is limited to the sprockets method. After the method returns, the object loses its reference to the new object so cannot relinquish ownership. That in itself is not a problem. However, following the naming convention set out earlier, the caller is given no indication that it owns the returned object. The caller would therefore not relinquish ownership of the returned object, leading to a memory leak.
You'd want to return an autoreleased object most of the time.
Unless your method name contains one of the following words [alloc, new, copy], you should return an autoreleased object.
If you create, alloc, or copy an object, you are responsible for releasing it. Based on this, you should return an autoreleased object.
I prefer to return the autorelease. It means that you aren't hunting around trying to find where memory is being freed. Keeping memory allocation and deallocation together makes your life easier. After all, you're coding this, why make it harder on yourself.
Both are acceptable, but you should name your method accordingly : if the caller has the responsibility to deallocate it, you have to make this explicit by having your method name contain "create", "alloc" or "copy", else it should not.
More reading on this at http://developer.apple.com/library/mac/#documentation/cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html%23//apple_ref/doc/uid/20000994-BAJHFBGH
It might be a bit more customary to return an autorelease object, but both are okay.

Memory cleanup on returned array from static method (objective-c)

In objective-c, I have a utility class with a bunch of static methods that I call for various tasks. As an example, I have one method that returns an NSArray that I allocate in the static method. If I set the NSArray to autorelease, then some time later, the NSArray in my calling method (that is assigned to the returned pointer) losses it's reference because the original form the static method is cleaned up. I can't release the NSArray object in the static method because it needs to be around for the return and assignment.
What is the right way to return an object (like the NSArray) from a static class, and have it hang around for the calling class, but then get cleaned up later when it is no longer needed?
Do I have to create the object first in the caller and pass in a pointer to the object and then return that same object form the static method?
I know this is a basic O-O problem, I just never had this issue in Java and I do not do much C/C++.
Thanks for your help.
Your autorelease is correct in the return just retain it when you call the static method.
NSArray *data = [[StaticClass getArray] retain];
If you have a property for the place your assigning the return value to, you can just do self.data = .. and the retain is automatic.
Please take the time to read over the rules. These apply to all of the frameworks you'll be using, and should apply to your code as well. Burn these into your head, and they'll become second nature. Thankfully, it's not complex, rather simple.
It's quite simple. If you do not own an object, it will go away at some indeterminate point in the future. In your case, the "indeterminate" point is when the autorelease pool gets drained, which in the normal case, is at the end of processing the current event.
If you want an object to hang around, you need to own it. The memory management rules referred to by jer will tell you exactly how you get ownership of an object. In this case, you need to retain the object. You must then, of course, release it later when you have done with it.
Regards your comment to Matt's answer. Your code is this:
for (NSString * date in dateList)
{
[historyList addObject:[[BIUtility historyForDate:date] retain]];
}
and
+ (NSArray *) historyForDate:(NSString *)date
{
NSMutableArray * ret = [[[NSMutableArray alloc] init] autorelease];
}
The first thing you need to know is that collections retain their members, so, in fact, your retain of the historyForDate is unnecessary. You don't want to own that object, historyList does. If it's disappearing, it's probably because historyList itself is being deallocated (because you don't own it) or is nil.
By the way, historyForDate: does nothing with the date. Is that correct?

Objective-C memory management--best practices when returning objects?

Suppose I have a function like this:
- (NSSet *) someFunction {
//code...
return [[[NSSet alloc] initWithObjets:obj1, obj2, nil] autorelease];
}
When I call this function, do I need to do retain/release the return value? I'm assuming I do.
However, what if I don't do autorelease, so someFunction now looks like this:
- (NSSet *) someFunction {
//code...
return [[NSSet alloc] initWithObjets:obj1, obj2, nil];
}
In this case, I'm assuming I need to release but not retain the return value.
My question is, what is the suggested/best practice for these kinds of situations? Is one or the other version of someFunction recommended? Thanks.
You should spend some time reading the Memory Management Programming Guide for Cocoa.
The short is that if you get your reference through a method starts with 'alloc' or 'new' or contains 'copy', you own the reference and do not have to retain it. You do have provide for its release, either through a direct release or through using autorelease.
If you get a reference any other way (through a class method or what-have-you), you do not own a reference, so you don't have to release. If you want to keep a reference, you have to retain it.
Over-all, it is really quite simple and effective.
Hmm...
Normally, I follow this "way".
+ (id)MyObj {
return [[[MyObj alloc] init] autorelease];
}
Releasing the object prior to returning it, the object will be deallocated before it reaches the calling object. This will produce an error. Avoid this error by using a autorelease pool instead. Originally introduced to me by Scott Stevenson of Theocacao. It's his and many, preferred way for Obj-C 1.0.
The only reason you should do the code in the second example is if your method name begins with new, alloc, create, copy, or something like that.
Otherwise you are responsible for releasing (or autoreleasing) any object you allocate. The first example is the correct way to do most things.
The calling function should retain the value if it wants it to persist past the functions scope, but it is then responsible for releasing it at some later point.