Adding methods to NSArray through categories, code problem.

boyfarrell

Registered
Hello all.

I have added a method called flip to NSArray. It has very limited scope but works find for me because there in only one situation in which I will ever use it.

It's job it to flip an NSMutableArray containing double NSNumber objects, e.g.

[0 1 2 3 4 5] goes in

[5 4 3 2 1 0] comes out.

I have managed to do this fine and it works in isolation. However, when I try to put it into a bigger project that I'm working on to use the flip functionality I keep getting run time errors, can anybody spot where I'm going wrong?

I've attached my Xcode project folder.
 

Attachments

  • arraymessing.zip
    23.6 KB · Views: 2
I haven't tried to understand your code, but you could realize it on an much more easier way:

- (NSArray*) flip {
return [[self reverseObjectEnumerator] allObjects];
}
I would guess that this code is much more faster.

Good night.
Squart

BTW: There are some parts of your code, which are very ugly. E.g. you are creating a category for NSArray, but you use it only for NSMutableArray. Or you have a semicolon in your implementation part right behind the - (NSMutableArray*)flip (I'm not sure if this could be the source of your runtime errors.
 
Wow you where up late too last night!

Thanks for the comments, I'm now categorising the NSMutableArray Class rather than NSArray.

It's possible to just copy your @interface definitions of methods into you @implementation so that's where the semicolon came from.

I'll try messing around with cocoa enumerators (they are always something I have tried to stay away from because I like the idea of accessing elements indiviually, but in this case it's got rather complicated!). So all in alll a very complicated way of doing something quite simple - still thinking more like a physicist rather than a computer scientist.

The code by the way is just matrix multiplication. Whenever you times an single row matrix my an anti-diagonal itenity matrix you get the reverse of what you put it - quite neat!

Thanks for your help.
 
Thanks for the advice on enumerators, it works now but strangely there is a signal 10 (SIGBUS)

Code:
#import <foundation/foundation.h>
#define pts 5


int main(int argc, char *argv[])
{
	
	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
	
	NSMutableArray *x, *xToo;
	x = [NSMutableArray arrayWithCapacity: pts];
	
	int i;
	for (i=0; i < pts; i++)
	{
		[x addObject: [NSNumber numberWithDouble:( (i*10) / (pts-1) )]];
	}
	
	NSEnumerator *enumerator = [x objectEnumerator];
	id anObject;
	
	while (anObject = [enumerator nextObject]) {
		
		NSLog(@"%@\n", anObject);
	}
	
	[enumerator release];
	
	xToo = [NSMutableArray arrayWithCapacity: pts];
	xToo = [[x reverseObjectEnumerator] allObjects];
	
	NSEnumerator *enumeratorToo = [xToo objectEnumerator];
	while (anObject = [enumeratorToo nextObject]) {
		
		NSLog(@"%@\n", anObject);
	}
	
	
	[enumeratorToo release];
	[x release];
	[xToo release];
	[pool release];
	[anObject release];
	return 0;
}

Here is the output

Code:
[Session started at 2005-12-30 15:49:14 +0000.]
2005-12-30 15:49:14.792 arraymessing[1427] 0
2005-12-30 15:49:14.793 arraymessing[1427] 2
2005-12-30 15:49:14.793 arraymessing[1427] 5
2005-12-30 15:49:14.793 arraymessing[1427] 7
2005-12-30 15:49:14.793 arraymessing[1427] 10
2005-12-30 15:49:14.793 arraymessing[1427] 10
2005-12-30 15:49:14.793 arraymessing[1427] 7
2005-12-30 15:49:14.793 arraymessing[1427] 5
2005-12-30 15:49:14.793 arraymessing[1427] 2
2005-12-30 15:49:14.793 arraymessing[1427] 0

arraymessing has exited due to signal 10 (SIGBUS).
 
I would suggest you to recapitulate your knowing about memory managment in Cocoa. I'll describe your errors, when I have time (probably tonight)

Greetings
Squart
 
It looks like NSMutableArray's -arrayWithCapcity and NSEnumerator's -objectEnumerator return objects that are autoreleased?

I have taken out all reference to releasing these object and the code now runs fine.

If this is the case how do I know which objects I own to release and ones that I don't have to worry about?
 
The general rule of thumb is: Objects that you create with an init* method need to be manually released, and anything else is autoreleased. (Note: [NSObject new] is equivalent to [[NSObject alloc] init], and thus must be manually released, as explained in the documentation.)

So your NSEnumerators, NSMutableArrays, and ids are all autoreleased here.
 
Hallo,

there are some other ugly parts. E.g.:
Code:
xToo = [NSMutableArray arrayWithCapacity: pts];
xToo = [[x reverseObjectEnumerator] allObjects];
At first xToo becomes an MutableArray and than it becomes another object. That isn't what you expect.
Also the second line of the code-excerpt returns a normal NSArray, it isn't mutable. It would be better to use xToo = [[NSMutableArray alloc] initWithArray:[[x reverseObjectEnumerator] allObjects]]; and to release it afterwards by yourself.

But the rule of memory managment (which I use) is a little bit different from Mikuro's rule:
You have to send one release (or autorelease) to an object for every:
+ new;
+ copy;
+ alloc;
- retain;
(perhaps there exists a few more methods you have to observe, but you shouldn't meet them so often)

Neither init nor an other method should need a release. The instanz which sends the methods above should release it by itself. Else you'll get some unpredictable surprisings.

Memory Managment is a question of habit. You can find some articles about it via google, e.g. http://www.macdevcenter.com/pub/a/mac/2001/07/27/cocoa.html

so long
Squart
 
Thanks so much for your help everybody, your really bring me along!

I have read those articles before but think I'm the type of person that learns by just doing it. In fact by doing it wrong, doing it wrong, asking for help, getting a bit better, do something wrong, the it clicks....!

So thanks again for your code suggestions and memory managment advice.

Dan.
 
Back
Top