views:

682

answers:

3

Hi,

I'm using the following method in my code:

- (NSMutableArray *) newOrderedArray:(NSMutableArray *)array ByKey:(NSString *)key ascending:(BOOL)ascending {

    NSSortDescriptor *idDescriptor = [[NSSortDescriptor alloc] initWithKey:key ascending:ascending];

    NSArray *sortDescriptors = [NSArray arrayWithObject:idDescriptor];
    NSArray *orderArray = [array sortedArrayUsingDescriptors:sortDescriptors];

    [idDescriptor release];

    NSMutableArray *result = [NSMutableArray arrayWithArray:orderArray];

    return result;
}

Is this a well-coded convenience method? As I think, it returns an autoreleased NSMutableArray.

This method is called by another one:

- (id) otherMethod {

    NSMutableArray *otherResult = [[[NSMutableArray alloc] initWithCapacity:[otherArray count]] autorelease];

   // I add some stuff to otherResult and then...

    NSMutableArray *result = [dbUtils newOrderedArray:otherResult ByKey:@"objectId" ascending:NO];
    return result;
}

This method (otherMethod) is called in some view controller where I want to store returned array and release it when deallocating the view controller. However, when [result retain] is called in this view controller (because I need it to be available and I can't allow it to be deallocated) I receive the following error:

[CFArray release]: message sent to deallocated instance

I've tried to log [result retainCount] just before calling retain and it print "1". I don't understand why an error is thrown when calling retain.

Thank you,

A

A: 

hi there,

try this:

    NSMutableArray *otherResult = [[NSMutableArray initWithCapacity:[otherArray count]];

Because initWithCapacity will return an autoreleased Array. Right now you tell the Autoreleasepool to release the Array twice.

hopefully useful
`initWithCapacity:` does not return an autoreleased object.
Wevah
A: 

I don't see anything technically wrong with the code above--otherMethod should return an autoreleased NSMutableArray. Are you sure you're getting the error when calling retain? It looks more like you might be accidentally be sending release at some point instead of retain.

Stylistically, there's one thing--methods with "new" in the title should always return non-autoreleased objects, so you should either name your method something else (such as orderedArray...) or use [[NSMutableArray alloc] initWithArray:] instead of arrayWithArray. Also, method signatures shouldn't start with a capital (so ByKey should be byKey.

eman
You're right! The problem wasn't on retain message, it was in the assignation self.array = result because in some previous place I was assigning using array = result (without using self)
arielcamus
A: 

initWithCapacity:does not return an autoreleased object. – Wevah

AFAIK initWithCapacity is a convenience initializier, which by convention return autoreleased objects. So if the object is only used within a local method, the autoreleasepool should deallocate it. Care to elaborate?

hopefully useful
You're thinking of `arrayWithCapacity`. `initWithCapacity` is an initializer which should only be used as part of `[[NSMutableArray alloc] initWithCapacity:]`, otherwise you'll get a crash (I think)--alloc returns a non-autoreleased object, so the retain count is 1.
eman
eman is correct. Both of you (“hopefully useful” for knowledge, eman for certainty) should read the memory-management rules: http://developer.apple.com/mac/library/documentation/General/Conceptual/DevPedia-CocoaCore/MemoryManagement.html
Peter Hosey