Objective-C + release Objects - objective-c

I am using the following function in my application:
+(TeamTournamentLookUp *)getOpponentTeamTournamentLookUp:(int)tournamentId:(int)opponentTeamId
{
TeamTournamentLookUp *objOpponentTTL = nil;
const char *sql = "SELECT TeamTournamentLookUpID, TournamentID, TeamID, NumberOfWins, NumberOfLosses, NumberOfDraws, Points, Rank, IsUserTeam from TeamTournamentLookUp where TournamentID = ? and TeamID = ?";
sqlite3_stmt *selectstmt;
if(sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) != SQLITE_OK)
NSAssert1(0, #"Error. '%s'", sqlite3_errmsg(database));
sqlite3_bind_int(selectstmt, 1, tournamentId);
sqlite3_bind_int(selectstmt, 2, opponentTeamId);
if(SQLITE_DONE != sqlite3_step(selectstmt))
{
NSInteger primaryKey = sqlite3_column_int(selectstmt, 0);
objOpponentTTL = [[TeamTournamentLookUp alloc] initWithPrimaryKey:primaryKey];
objOpponentTTL.tournamentId = sqlite3_column_int(selectstmt, 1);
objOpponentTTL.teamId = sqlite3_column_int(selectstmt, 2);
objOpponentTTL.numberOfWins = (sqlite3_column_type(selectstmt, 3) == SQLITE_NULL) ? 0 : sqlite3_column_int(selectstmt, 3);
objOpponentTTL.numberOfLosses = (sqlite3_column_type(selectstmt, 4) == SQLITE_NULL) ? 0 : sqlite3_column_int(selectstmt, 4);
objOpponentTTL.numberOfDraws = (sqlite3_column_type(selectstmt, 5) == SQLITE_NULL) ? 0 : sqlite3_column_int(selectstmt, 5);
objOpponentTTL.points = (sqlite3_column_type(selectstmt, 6) == SQLITE_NULL) ? 0 : sqlite3_column_int(selectstmt, 6);
objOpponentTTL.rank = (sqlite3_column_type(selectstmt, 7) == SQLITE_NULL) ? 0 : sqlite3_column_int(selectstmt, 7);
objOpponentTTL.isUserTeam = (sqlite3_column_type(selectstmt, 9) == SQLITE_NULL) ? 0 : sqlite3_column_int(selectstmt, 9);
}
return objOpponentTTL;
}
Basically I am returning an Object of TeamTournamentLookUp class.
In the code I am allocating the object:
objOpponentTTL = [[TeamTournamentLookUp alloc] initWithPrimaryKey:primaryKey];
Now my question is where should I release the object?

If you are writing for Objective C 2 then you don't need to do more code just build with garbage collection. If for earlier versions including iPhone then you would need to release it at some stage.
In this case the usual way is to autorelease it when you create it. e.g.
objOpponentTTL = [[[TeamTournamentLookUp alloc] initWithPrimaryKey:primaryKey]autorelease];
The object will be released when you reach an autorelease pool. There is one of these by default in NSApplication and gets called in the input loop.
For more on memory management read Apple's docs on memory management

Send it the autoRelease message before you return it. This way it'll get a release message sent to it, but not just yet.
Then whatever is calling your method will have to retain the object that's returned.
You can look up the patterns for handling retain, release, autoRelease in the Apple documentation. It's very handy to learn some basic rules.

Using objective-c, technically your function should autorelease your returned object, eg.
return [autorelease objOpponentTTL];
The calling object should retain the returned object eg.
TeamTournamentLookUp * object = [[self getOpponentTeamTournamentLookUp:5:6] retain];
When you are finished using 'object', you should release it then ie.
[object release]
I haven't really used Objective-C 2.0 and its garbage collection, so I'm not sure what the syntax should be if you have garbage collection turned on. However, if you're using standard Objective-C, then this should be fine for you.
Without garbage collection, the convention is to retain an object when you want to use it, and release it when you're finished with it. If you were to add 'object' to a container (eg. an NSMutableArray), the function you're calling will retain the object, and you can safely release it after adding to the collection, eg.
....
TeamTournamentLookUp * object = [[self getOpponentTeamTournamentLookUp:5:6] retain];
[my_lookup addObject:object];
[object release];
....
Hope this helps!

This form of class method is used to allocate and initialise an object. However you have set objOpponentTTL to nil in its declaration and never allocate it, though you do mention the required allocation line in your description. If that line were included, this function would be basically fine. Although (as ed mentions) the fact that it is called getXXX is against convention; a class method like this should be named after the object type it creates and returns.
As to the question of when to release it, that depends entirely on its lifecycle and the scope of the owning object. The short answer is: when you don't need it any more!
For example, if this object is special data associated with a team and the team belongs to a game, then you would release it in the dealloc method of your game. And the game would probably be created and released by the controller.
Others have mentioned autorelease, but that is probably not what you want here. That is useful when you have a transient object that you want to return from a method, but you will no longer have a handle to it (returning an NSString is a good example). This looks like it is part of a larger set of objects.
You really need to think about the design of your application and how the objects interact. Draw some sequence diagrams, and look at what information is needed, when, and by what objects. The example above (where a controller owns a game which owns players) is a fairly generic starting point.
The scope of an object (and where it is declared) tells you a lot. For example, if an object is a data member, you would usually allocate it in the init or awakeFromNib method, and release it in the dealloc method. If it is a factory method (such as your example), you would create it and (by convention) it is the caller's responsibility to release it. And if it is an accessor that creates a throwaway object, you would probably use autorelease.
As others have pointed out, the Apple documentation on memory management is very good. There are very clear conventions on how to safely manage memory, so it is worth grokking them and following those conventions in your own code.

In addition to the other answers, I'd look at your design and naming convention to give your object management some more clarity. Apple use a convention all over their APIs that makes it quite clear when the caller has the responsibility to release a returned object and when the lifecycle of the object is managed elsewhere.
Have a read of Apple's guidlines.
For starters, the name of your method starts with a 'get'. This implies to me that it is returning an object that has its own lifecycle independent of my calling method and I should not release it at all!
When calling a method that starts with 'make' or 'create' then that tells me that the object returned has been created for me and I have responsibility to release it when I'm done with it.
Note: I should note that this is written from the perspective of iPhone development, which isn't big on the whole autorelease thing...

Related

Simple rules for naming methods, compatible with ARC naming conventions

I have difficulties understanding naming conventions of ARC. I have always coded with ARC, and I guess this is the reason.
1. Class methods
What name should I choose for the following method?
What are the differences, concerning memory management, between theses two names?
This name:
+ (MyObject *)newObjectFrom:(MyObject *)anObject
withOptions:(NSDictionary*)options
{
MyObject * newObject = [anObject copy] ;
[newObject modifyWith:options] ;
return newObject ;
}
or this name ?
+ (MyObject *)objectFrom:(MyObject *)anObject
withOptions:(NSDictionary*)options
{
MyObject * newObject = [anObject copy] ;
[newObject modifyWith:options] ;
return newObject ;
}
2. Instance methods
What name should I choose for the following method?
What are the differences, concerning memory management, between theses two names?
This name:
- (MyObject *)newObjectwithOptions:(NSDictionary*)options
{
MyObject * newObject = [self copy] ;
[newObject modifyWith:options] ;
return newObject ;
}
or this name?
- (MyObject *)objectwithOptions:(NSDictionary*)options
{
MyObject * newObject = [self copy] ;
[newObject modifyWith:options] ;
return newObject ;
}
2. Simple rules for naming methods
Is there a basic, simple rule to follow when naming methods?
By "basic, simple", I mean
a rule similar to "strong when the object belongs to the class", "weak when the object is just referred to by this class, and (thus) owned by another class";
(and/or) a rule that does not refer to the memory management without ARC;
(and/or) a rule that does not use words such as "autorelease", "release".
When Rivera said that method names are not important, he probably followed his experience: It always works. And this is correct. And you are correct that you probably do not understand the role of method names because you has always used ARC. So what is the big deal with it?
I added a synopsis to show the problem with MRR at the end of this answer. As you can see there, you do not have to care about naming rules using ARC the way you had to with MRR.
To give you a more detailed explanation, you have to understand what happens using MRR:
Prior to ARC one had to do memory management manually. Doing so he had to know, what kind of ownership a return value has. To make a long story short, one had to know, whether he has to release a returned object:
Rule 1: You do not own an object returned by a method automatically. If you want to hold it, retain it and release it, when you are done with it.
id object = [[object methodThatReturnsAnObject] retain]; // I want to hold it
…
[object release]; // Done with it
id object = [object methodThatReturnsAnObject]; // I do not want to hold it
…
// I do not release it
Doing a deep analysis you can see that there are sometimes problems. (Object deallocation as a side effect.) But this was the basic approach.
The advantage of that was that a retain-release pair could be handled locally (inside a compound statement) and it was easy to follow the ownership of an object.
Rule 2: But when an object was created the first time this could not work: The sender of the message has always to hold it. Otherwise it would be destroyed immediately (= before the sender has the chance to retain it.) So there was a additional rule:
If the name of a class method that returns an object starts with alloc, init, or new you have to handle the returned object as you did a retain on it. Or in one word: Ownership transfer:
id object = [Class allocOrInitOrNewMethod];
…
[object release];
As -retain took the ownership explicitly, alloc–, init…, new… transferred it implicitly.
All other methods behaves like rule 1.
Rule 3: Sometime you need an autorelease pool.
To make the advantage of ARPs visible think of this code: (It is useless, just to demonstrate the problem
Case 1.1:
Person *person = [[Person alloc] initWithName:…]; // Ownership transfer, release person, when you are done
NSString *name = [person name]; // the name object is hold by the person object only
[person release]; // I do not need the person object any more
[name doSomething]; // Crash: The person was the only object holding the name
Another problem:
Case 2.1:
Person *person = [[Person alloc] initWithName:…]; // Ownership transfer, release person, when you are done
if (…)
{
return; // break, continue, goto
}
…
[person release];
Because the last line is never reached, the object is never released.
You can repair that with autoreleasing methods. An object moved to the ARP lives as long as the control flow returns to the run loop. So it lives through every method, through method return and so on. To do it explicitly:
Case 1.2:
Person *person = [[[Person alloc] initWithName:…] autorelease]; // No ownership transfer, persons belongs to the ARP
NSString *name = [person name]; // the name object is hold by the person object only
[name doSomething]; // No Crash: The person object holding the name object is still alive
Case 2.2:
Person *person = [[[Person alloc] initWithName:…] autorelease]; // No ownership transfer, prsons belongs to the AR.
if (…)
{
return; // break, continue, goto
}
…
// No release necessary.
Because one has to be too lazy to type such a long message chain, convenience allocators has been invented to do this for you:
+ (Person*)personWithName:(NSString*)name
{
return [[[self alloc] initWithName:name] autorelease];
}
With the result:
Case 2.3:
Person *person = [personWithName:…]; // No ownership transfer, persons belongs to the AR.
if (…)
{
return; // break, continue, goto
}
…
// No release necessary.
And you can do the same with getters:
- (NSString*)name
{
return [[_name retain] autorelease];
}
So we at the end of the day we have simple rules:
Rule 1: If you want to keep a returned object in memory retain it – and release it, when you do not need it any more.
Rule 2: If the class method's name starts with alloc, new, or init, think of it as an implicit retain (and therefore release it, when you are done with the object.)
Rule 3: Use -autorelease to delay the deallocation of returned objects for convenience.
Synopsis:
Alloc-init creation
// MRR:
Person *person = [[Person alloc] initWithName:#"Amin"];
…
[person release]; // You create it, you release it
// ARC:
Person *person = [[Person alloc] initWithName:#"Amin"];
…
New creator
// MRR:
Person *person = [[Person newPersonWithName:#"Amin"];
…
[person release]; // You create it, you release it
// ARC:
Person *person = [[Person newPersonWithName:#"Amin"];
…
Convenience allocator
// MRR:
Person *person = [[Person personWithName:#"Amin"]; // Autoreleased
…
// ARC:
Person *person = [[Person personWithName:#"Amin"];
…
As you can see, there is no difference for the three ways of object creation using ARC. So Riviera is right, when he said that this is not important any more. But under the hood the last way is different, because it moves the object to the ARP.
It is the same with the implementation of this methods:
Implementing a new allocator
// MRR
+ (Person*)newPersonWithName:(NSString*)name
{
return [[self alloc] initWithName:name];
}
// ARC
+ (Person*)newPersonWithName:(NSString*)name
{
return [[self alloc] initWithName:name];
}
Implementing a convenience allocator
// MRR
+ (Person*)personWithName:(NSString*)name
{
return [[[self alloc] initWithName:name] autorelease];
}
// ARC
+ (Person*)personWithName:(NSString*)name
{
return [[self alloc] initWithName:name];
}
Again the implementation for both methods is identical using ARC.
-> You do not need it any of this rules any more. ARC cares four you.
Especially you do not need convenience allocators any more, because there is nothing inconvenient any more. (And even they are optimized at run time, there is still a minimal runtime penalty.) I do not implement convenience allocators any more, but new allocators.
But ARC has to be compatible with MRR. So it remembers all that rules. To make your code readable for others you should repeat this rules, too. But, of course, now the implementation of a convenience allocator and a new allocator is bitwise identical – the rest is done by ARC.
Method names are important. The official documentation of how ARC interprets method names can be found in the clang ARC documentation in the section on method families.
Method naming conventions are important when converting the code from MRC to ARC, and when interoperating with MRC code from ARC Code.
Apple guide says that with "ARC code only" the naming conventions are "less important", but this is not 100% true.
For example (and this is only one example, I think that there are many other), look at this project
I swizzled release-autorelease calls to log it, and you can see the difference:
when a method begins with a special naming (for example "new"), ARC returns an object with a retain count of +1, that is balanced by release calls.
When a difference name is used, ARC returns an AUTORELEASED object. (look at the NSLog calls)
This can be a big difference in code that alloc a great number of objects in a loop. In this case, the programmer should create an autorelease pool.
So, it's not true that the naming conventions are less important when using ARC-only code.
I don't know all of the details on naming methods 100% conventionally because there are different situations that apply to each. however I think this article in the Apple docs will help you. https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/Conventions/Conventions.html
My experience in the apple world is that factory methods like your examples would usually include 'create' by convention. This is probably less important now with ARC but in the old days 'create' in a method or function signature was a pretty sure fire way to be sure you understood you were taking ownership of the resulting object (owing a release/free() on it) rather than an instance type which you would assume to autorelease [NSArray array] , [UIColor colorWith....] etc, so I still definitely like to follow this convention.
ARC gave semantics to what used to be a naming convention for tracking reference counting responsibilities. So now the compiler uses the same naming patterns to determine whether a method returns a retained object, etc. See the link in #JodyHagens' answer and continue reading with http://clang.llvm.org/docs/AutomaticReferenceCounting.html#semantics-of-method-families
Methods in the alloc, copy, mutableCopy, and new families — that is, methods in all the currently-defined families except init — implicitly return a retained object as if they were annotated with the ns_returns_retained attribute. This can be overridden by annotating the method with either of the ns_returns_autoreleased or ns_returns_not_retained attributes.
The "new family" is the message selectors that start with "new" followed by an upper case letter. So there are memory management differences between newObjectFrom:withOptions: and objectFrom:withOptions:, but you can use an annotation to override that (don't go there), and the compiler should complain if you get it wrong.
(All methods that implement a given message selector had better provide the same reference counting semantics.)
In addition to Apple's article on Conventions that #iRebel_85 points out, Apple has an extensive set of naming guidelines.
Google's style guide adds a few more naming guidelines.
These guidelines are well thought out and useful for making code easier to understand and collaborate on.
First, memory management has nothing to do with the names you choose for your methods or classes. In other words if it compiles and you're not using reserved keywords or critical method names you should be good. (Please refer to Edit note)
As for 1, preceding new is very uncommon in Objective-C, so it's better to use objectFrom: instead.
Even better would be to be more precise about the kind of object you're creating. For example:
[NSArray arrayWithArray:]
[NSString stringWithFormat:]
Or in your case as you create a copy, and supposing you're creating "Client" objects:
[Client clientWithClient:options:]
Where with is not really needed.
For 2 I would choose:
copyWithOptions:
As you're more or less customizing [NSObject copy]. I would also implement only this method and delete the now redundant 1 as less methods is clearer, easier to document, and easier to maintain!
In case of doubt just search the SDK documentation to see how similar methods were named by Apple.
Edit:
In the first paragraph I don't mean to encourage bad naming practices, just to say that they are not the reason for your memory management concerns. Yet you should try to follow the naming conventions pointed in the other answers, or as I said, "do as Apple does".

How to replicate NSArray memory semantics in a subclass

Question
In my ARC project I have a class that manages objects, called LazyMutableArray. Some of the objects are actually nil, but users of my collection will never know about this; therefore I made it a subclass of NSMutableArray, and it tries to do "the same thing". In particular, objects are retained when added.
Now let's take a look at a memory behavior of other methods. It turns out that the NSArray destruction methods are documented by Apple to be an exception to this rule, in that they release, not autoreleased object.
There is some debate as to whether the combination of addObject: + objectAtIndex: + array destruction is documented by Apple to be never autoreleasing or simply happens to be in the examples I tested and in the example Apple includes.
How can I create in my subclass a method with exact same memory semantics?
Last update
After some thought, I've decided implementation based on NSMutableArray is more appropriate in this case compared to NSPointerArray. The new class, I should note, has the same retain/autorelease pair as the previous implementation.
Thanks to Rob Napier I see that no modification of my objectAtIndex: method would change this behavior, which answers my original question about this method.
On a practical level, several people said that any method can tackle an extra retain/autorelease pair for no reason; it's not reasonable to expect otherwise and not reasonable to try to find out which methods do this and which do not. It's been therefore a great learning opportunity for me on several levels.
Code (based on NSMutableArray) is available at GitHub: implementation, header, test (that's -testLazyMutableMemorySemantics).
Thank you all for participating.
Why I try to subclass NSMutableArray:
Subclassing foundation objects, I agree, is not always an appropriate solution. In tho case I have objects (in fact, OData resources), most of which have subobjects. The most natural class for an array of subobjects is obviously NSArray. Using a different class doesn't seem to make sense to me.
But for an OData collection this "array of sub objects", while, being an NSArray, must have a different implementation. Specifically, for a collection of 1000 elements, servers are encouraged to return collection in batches of (say)20, instead of all at once. If there is another pattern appropriate in this case, I'm all ears.
Some more detail in how I found this
I unit test the hell out of this collection, and values can be put into array, read from the array, and so forth. So far, so good. However, I realized that returning the object increases its retain count.
How do I see it? Suppose I insert two objects into lazy array lazy, one held weakly, one held strongly (*see the code *). Then retain count of weakSingleton is, as expected, 1. But now I read element:
XCTAssertEqual(weakSingleton, lazy[0], #"Correct element storage"); // line B
And in the debugger I see the retain count go up to 2. Of course, -retainCount may give me wrong information, so let's try to destroy the reference in array by
lazy[0] = nil; // yep, does the right thing
XCTAssertNil(weakSingleton, #"Dropped by lazy array"); // line C <-- FAIL
indeed, we see that weakSingleton is not released.
By now you probably guess that it's not just a retain, it's an autoreleased retain — putting an #autorelease around line B releases the weakSingleton. The exact source of this pair is not obvious, but seems to come from NSPointerArray -addPointer: (and unfortunately not from ARC's [[object retain] autorelease]). However, I don't want to return an autoreleased object and make method semantics different from its superclass!
After all, the method I'm overriding, NSMutableArray -objectAtIndex:`, doesn't do that; the object it returns will dealloc immediately if an array is released, as noted in the Apple's example. That's what I want: modify the method around line A so that the object it returns does not have an extra retain/autorelease pair. I'm not sure the compiler should even let me do it :)
Note 1 I could turn off ARC for a single file, but this would be my first non-ARC Objective-C code. And in any case the behavior may not some from ARC.
Note 2 What the fuss? Well, in this case I could change my unit tests, but still, the fact is that by adding or deleting line B, I'm changing the result of unit test at line C.
In other words, the described behavior of my method [LazyMutableArray -objectAtIndex] is essentially that by reading an object at index 0, I'm actually changing the retain count of this object, which means I could encounter unexpected bugs.
Note 3 Of course, if nothing is to be done about this, I'll document this behavior and move on; perhaps, this indeed should be considered an implementation detail, not to be included into tests.
Relevant methods from implementation
#implementation LazyMutableArray {
NSPointerArray *_objects;
// Created lazily, only on -setCount:, insert/add object.
}
- (id)objectAtIndex:(NSUInteger)index {
#synchronized(self) {
if (index >= self.count) {
return nil;
}
__weak id object = [_objects pointerAtIndex:index];
if (object) {
return object;
}
}
// otherwise do something else to compute a return value
// but this branch is never called in this test
[self.delegate array:self missingObjectAtIndex:index];
#synchronized(self) {
if (index >= self.count) {
return nil;
}
__weak id object = [_objects pointerAtIndex:index];
if (object) {
return object;
}
}
#throw([NSException exceptionWithName:NSObjectNotAvailableException
reason:#"Delegate was not able to provide a non-nil element to a lazy array"
userInfo:nil]);
}
- (void)createObjects {
if (!_objects) {
_objects = [NSPointerArray strongObjectsPointerArray];
}
}
- (void)addObject:(id)anObject {
[self createObjects];
[_objects addPointer:(__bridge void*)anObject];
}
The complete test code:
// Insert two objects into lazy array, one held weakly, one held strongly.
NSMutableArray * lazy = [LazyMutableArray new];
id singleton = [NSMutableArray new];
[lazy addObject:singleton];
__weak id weakSingleton = singleton;
singleton = [NSMutableDictionary new];
[lazy addObject:singleton];
XCTAssertNotNil(weakSingleton, #"Held by lazy array");
XCTAssertTrue(lazy.count == 2, #"Cleaning and adding objects");
// #autoreleasepool {
XCTAssertEqual(weakSingleton, lazy[0], #"Correct element storage");
XCTAssertEqual(singleton, lazy[1], #"Correct element storage");
// }
lazy = nil;
XCTAssertNotNil(singleton, #"Not dropped by lazy array");
XCTAssertNil(weakSingleton, #"Dropped by lazy array");
The last line fails, but it succeeds if I change first line to lazy = [NSMutableArray new] or if I uncomment #autoreleasepool.
First, I would not make this subclass. This is exactly what NSPointerArray is for. Wrapping that into an NSArray obscures important details that this approach can break. For example, what is the correct behavior for [NSArray arrayWithArray:lazyMutableArray] if lazyMutableArray includes NULLs? Algorithms that assume that NSArray can never include NULL need to be wary of the fact that this one can. It's true that you can get similar issues treating a non-retaining CFArray as an NSArray; I speak from experience that this is exactly why this kind of subclass can be very dangerous (and why I stopped doing that years ago). Don't create a subclass that cannot be used in every case that its superclass can be used (LSP).
If you have a collection with new semantics, I would subclass it from NSObject, and have it conform to <NSFastEnumeration>. See how NSPointerArray is not a subclass of NSArray. This was not an accident. Faced with the same problem, note the direction Apple chose.
By now you probably guess that it's not just a retain, it's an autoreleased retain — putting an #autorelease around line B releases the weakSingleton. This seems to be because line A under ARC translates to [[object retain] autorelease]. However, I don't want to return an autoreleased object and make caller remember this!
The caller should never assume anything else. The caller is never free to assume that a method does not add balanced autoreleases. If a caller wants the autorelease pool to drain, that is their responsibility.
All that said, there is some benefit to avoiding an extra autorelease if it's not required, and it's an interesting learning opportunity.
I would start by reducing this code to the simplest form, without your subclass at all. Just explore how NSPointerArray works:
__weak id weakobject;
#autoreleasepool
{
NSPointerArray *parray = [NSPointerArray strongObjectsPointerArray];
{
id object = [NSObject new];
[parray addPointer:(__bridge void*)object];
weakobject = object;
}
parray = nil;
}
NSAssert(!weakobject, #"weakobject still exists");
My structure here (such as the extra nesting block) is designed to try to avoid accidentally creating strong references I don't mean to make.
In my experiments, this fails without the autoreleasepool and succeeds with it. That indicates that the extra retain/autorelease is being added around or by the call to addPointer:, not by ARC modifying your interface.
If you're not using this implementation for addObject:, I'd be interested in digging deeper. It is an interesting question, even if I don't believe you should be subclassing this way.
I'm going to elaborate on why I said this "looks a lot like a homework assignment." This will likely earn me many down votes, but it will also server as a good learning case for others who later find this question.
Subclassing NSMutableArray not a goal of a program. It is a means to achieve something else. If I were to venture a guess, I expect you were trying to create an array that lazily creates the object when they are accessed. There are better ways to do this without dealing with memory management yourself.
Here's an example of how I would implement a lazy loading array.
#interface LazyMutableArray : NSMutableArray
- (id)initWithCreator:(id(^)(int))creator;
#end
#interface LazyMutableArray ( )
#property (nonatomic, copy) id (^creator)(int);
#property (nonatomic, assign) NSUInteger highestSet;
#end
#implementation LazyMutableArray
- (id)initWithCreator:(id(^)(int))creator
{
self = [super init];
if (self) {
self.highestSet = NSNotFound;
self.creator = creator;
}
return self;
}
- (id)objectAtIndex:(NSUInteger)index
{
id obj = nil;
if ((index < self.highestSet) && (self.highestSet != NSNotFound)) {
obj = [super objectAtIndex:index];
if ([obj isKindOfClass:[NSNull class]]) {
obj = self.creator(index);
[super replaceObjectAtIndex:index withObject:obj];
}
} else {
if (self.highestSet == NSNotFound) {
self.highestSet = 0;
}
while (self.highestSet < index) {
[super add:[NSNull null]];
self.highestSet += 1;
}
obj = self.creator(index);
[super add:obj];
self.highestSet += 1;
}
return obj;
}
Fair Warning: I'm not compiling or syntax checking any of this code. It probably has a few bugs in it, but it should generally work. Additionally, this implementation is missing an implementation of add:, count, removeObjectAtIndex:, insertObject:atIndex:, and possibly replaceObjectAtIndex:withObject:. What I show here is just to get you started.

Objective-C Accessor Methods and Use of Autorelease

I've been reading an apple document on Memory Management and am now a bit confused regarding the recommended implementation of Accessors. Apple cites 3 approaches in implementing accessors.
Technique 1
I've copied the code from the first technique which reflects: "Getter retains and autoreleases the value before returning it; setter releases the old value and retains (or copies) the new value." This first technique is stated to be more robust but suffers performance penalties on frequently called getters.
- (NSString*) title {
return [[title retain] autorelease];
}
- (void) setTitle: (NSString*) newTitle {
if (title != newTitle) {
[title release];
title = [newTitle retain]; // Or copy, depending on your needs.
}
}
skipping Technique 2
Technique 3
The third technique is better for frequently called setters and getters. This is also the method I've always followed.
- (NSString*) title {
return title;
}
- (void) setTitle: (NSString*) newTitle {
if (newTitle != title) {
[title release];
title = [newTitle retain]; // Or copy, depending on your needs.
}
}
My questions are:
(Technique 1) The setter first releases the existing value even if it doesn't point to anything. This would send a message to nil which I understand is supported in Objective-C but still looks odd. Am I understanding this correctly?
(Technique 1) Why is the retain stacked inside an autorelease?
(Technique 1) Is the caller whom uses the getter expected to call release after they're done with the object?
The apple developer documentation page can be found at: Memory Management Programming Guide - Accessor Methods
(Technique 1) The setter first
releases the existing value even if it
doesn't point to anything. This would
send a message to nil which I
understand is supported in Objective-C
but still looks odd. Am I
understanding this correctly?
Yup. Messages to nil matter not.
(Technique 1) Why is the retain
stacked inside an autorelease?
That guarantees that the following doesn't break:
x = [foo title];
[foo setTitle: #"bar"];
[x length]; // x has been released, possibly, if -title didn't retain/autorelease
(Technique 1) Is the caller whom uses
the getter expected to call release
after they're done with the object?
No.
Sending a message to nil is defined to do nothing. This setter is an excellent example of how that allows you to write simpler code: [title release] instead of if (title != nil) [title release];. Note also that no special checks for nil are necessary on newTitle.
The retain/autorelease pair in the getter mean that the returned object will remain valid through the lifetime of the current function call (technically, until the autorelease pool is drained), even if the setter is called. The documentation you cite gives an example of how that can be helpful if there's a variable with a "non-owning reference" to the value.
NO. The value has already been autoreleased; caller must not release it again.

properly creating object in objective-c for avoiding memory leaks

after having spent few months in trying to master the syntax and rules, I am going deeper in memory management rules.
One thing I do not understand and causing me confusion is how one creates objects.
Based on what stated in apple memory management guide, the following is a valid approach:
– (NSArray *)sprockets {
NSArray *array = [NSArray arrayWithObjects:mainSprocket,auxiliarySprocket, nil];
return array;
}
because I am not causing any memory leaks.
The reason why is that it's not using alloc for creating array and therefore sprockets is not the owner.
However I am wondering now what's inside arrayWithObjects.
Because it happens that in my apps I often have factory for creating custom objects using something similiar to:
return [[MyObject alloc] initWithParameter:(id)params]; // possible leak
If I want to change with a static method like:
return [MyObject initWithParameter:(id)params];
what could be in initWithParameter for adhere to memory rules ? And what if MyObject extends some other object ? I also find out that method naming rules are important to properly advise programmer, what are this rule ?
Also could you point out a web link where this is explained (I am not yet good in finding docs on apple web site).
thanks
This is the page you're looking for: Memory Management Rules. It all comes down to adhering to the rules of ownership for an object.
If you create an object using alloc then you own that object and must release it. For example:
NSString* str = [[NSString alloc] init];
//do something with your str object
[str release];
str = nil; //don't forget to set it to nil, it's still
//pointing to the (now unallocated) block of memory
If you create an object using a factory method, for example:
NSString* str = [NSString stringWithString:#"blah"];
Then what is happening here is that it is creating the string object using alloc for you and then returning the object but first adding it to the local autorelease pool. To use the example in your question.
return [[MyObject alloc] initWithParameter:(id)params]; // possible leak
return [[[MyObject alloc] initWithParameter:(id)params] autorelease]; //now autoreleased -- no leak
Here is the page on Autorelease Pools. Apple say it better than me.
An autorelease pool is an instance of NSAutoreleasePool that “contains” other objects that have received an autorelease message; when the autorelease pool is deallocated it sends a release message to each of those objects. An object can be put into an autorelease pool several times, and receives a release message for each time it was put into the pool. Thus, sending autorelease instead of release to an object extends the lifetime of that object at least until the pool itself is released (the object may survive longer if it is retained in the interim).
Method naming rules are important as it gives a strong indication as to whether the method returns an autoreleased object. In this example I would name the method:
[MyObject myObjectWithParameter:(id)param]
Hope this has helped.
It is standard practice for alloc and creation methods to return a retained object. Anything that starts with init, create, or the object name will clue other programmers into the purpose of the method.
Even if you create with alloc, if the purpose of your method is to pass on ownership, you should not release the object.

Is this if needed?

This method is generated by Xcode 3.2 using "Accessor defs to clipboard"
- (void)setBodyMass:(int)newBodyMass {
if (bodyMass != newBodyMass) {
bodyMass = newBodyMass;
}
}
Could I just as easily write this as you see below? It seems to be doing a conditional test to save it doing a possible redundant assignment.
- (void)setBodyMass:(int)newBodyMass {
bodyMass = newBodyMass;
}
cheers -gary-
Normally you do a check like that in a mutator method because you're working with objects that have to be released. Say you have a mutator method without that check:
- (void)setObject:(MyObject *)anObj
{
[obj release];
obj = [anObj retain];
}
Imagine (for some reason) you have a chunk of code like this that uses that method:
MyObject *o = [MyObject object]; // Auto-released
[anotherObject setObject:o];
[anotherObject setObject:o];
On Line 1, you can assume o has a retain count of 0 (since it's autoreleased). On Line 2, o has been passed to setObject:, which retains it and stores it in the instance variable obj. Since we're working with pointers, o and obj point to the same object in memory, which now has a retain count of 1.
On Line 3, you pass the same object to setObject: again. But right away in that method, you release anObj, which is the same object that both o and obj point to! This means that o, obj, and anObj have a retain count of 0. When you set obj to [obj retain], you're making obj point to an object that has been released already.
This is obviously bad, so when working with mutator methods that deal with objects, you should always use that guard, which effectively checks to see if obj and anObj point to the same object in memory; if they do, nothing happens.
However, this guard isn't necessary in your example, because you're passing an int -- not a pointer -- and ints, of course, never get released (since they're not objects).
I'd do it your way; assigning an int is very cheap. The check makes sense if the assignment is to some large data structure or might have unintended side effects, neither of which is true for int.
Does the assignment cause something to trigger (event)? Doesn't seem so. You can compare but for a simple int I do not think it's an obligation to verify if the value is the same or not. Of course, if you want to display something to the user concerning that he has entering the same value, you might check the value, otherwise, I would not check it.