Welcome to the MacNN Forums.

If this is your first visit, be sure to check out the FAQ by clicking the link above. You may have to register before you can post: click the register link above to proceed. To start viewing messages, select the forum that you want to visit from the selection below.

You are here: MacNN Forums > Software - Troubleshooting and Discussion > Developer Center > Pointers and Arrays in Cocoa

Pointers and Arrays in Cocoa
Thread Tools
cla
Mac Enthusiast
Join Date: Mar 2000
Status: Offline
Reply With Quote
Feb 7, 2005, 11:59 AM
 
This is really basic, but I still can't get the hang of it. I would be very grateful for help:

I'm playing around with Cocoa and though I'd create a simple Bezier editor.
So I created a class, Anchor, which has the necessary attributes and methods for storing, selecting and manipulating an anchor point.
Clicking, dragging and thus defining an anchor point all works well.

I use one single instance of the Anchor object which I call master_anchor, rewriting it as the user defines another anchor (a click and a drag!).

The thing is, I want to store multiple anchor points in an array, an NSMutableArray kind of array.

At first I simply added every completed Anchor object to my array as soon as the user would release the mouse button: [path addObject:master_anchor];
My stupidness soon discovered that the array was full of pointers to the same object, namely my single anchor instance which I kept reassigning/overwriting every time the user defined a new anchor point.

A couple of sandwiches later I started over, this time determined to store a pointer to a copy of the anchor object in the array. So once a new anchor point was defined, this executed:
Code:
// create a new temporary Anchor Anchor *tempAnchor = [[[Anchor alloc] init] retain]; // copy master_anchor into tempAnchor "manually", // all 3 NSPoints defining the anchor: [tempAnchor set_origin:[master_anchor get_origin]]; [tempAnchor set_back:[master_anchor get_back]]; [tempAnchor set_fwd:[master_anchor get_fwd]]; // add this copy onto the path array [path addObject:tempAnchor];
Just for the record, set_origin, set_back and set_forward is no more complicated than this:
Code:
-(void)set_origin:(NSPoint) pt { origin = NSMakePoint(pt.x, pt.y); }
Creating copies and storing their pointers on the array really ought to do the trick (actually, it was moms idea). Alas, when I printed the coordinates to the anchors in the array, they were STILL the same, namely the last defined anchor point.

I also tried copying the anchor the "right" way, by defining a copyWithZone method in order to use the NSCopying protocol.
As if that would work...

How hard can it be? What am I missing?
     
Clinically Insane
Join Date: Oct 2001
Location: San Diego, CA, USA
Status: Offline
Reply With Quote
Feb 7, 2005, 12:44 PM
 
Can you post a minimal sample case with all the code needed to reproduce the problem? I'm having trouble understanding what you're doing. Overwriting an object doesn't really make much sense, and would probably require some convoluted hacking into the runtime. You seem to be somewhat confused about memory management and the difference between pointers and object, but it's hard to tell exactly what's going on without seeing what you're actually doing. In general, with problems that you don't understand, the problem isn't what you think.
Chuck
___
"Instead of either 'multi-talented' or 'multitalented' use 'bisexual'."
     
cla  (op)
Mac Enthusiast
Join Date: Mar 2000
Status: Offline
Reply With Quote
Feb 7, 2005, 01:51 PM
 
Thanks Chuck, here it goes:

This is the header of the Anchor object, Anchor.h:
Code:
#import <AppKit/AppKit.h> #import <Foundation/Foundation.h> NSPoint origin, back, fwd; @interface Anchor : NSObject { } -(void)drawRect:(NSRect) rect; -(void)set_origin:(NSPoint) pt; -(void)set_back:(NSPoint) pt; -(void)set_fwd:(NSPoint) pt; -(void)set_symmetric:(NSPoint) pt; -(void)dump; -(NSPoint)origin; -(NSPoint)back; -(NSPoint)fwd; -(id)copyWithZone:(NSZone*)zone; @end
The implementation of the same:
Code:
// Anchor.m // // defines an anchor point having a position (origin) and two handles (back and fwd) // o-----------------------o-----------------------o // back origin fwd #import "Anchor.h" @implementation Anchor -(void)drawRect:(NSRect)rect { [[NSColor blackColor] set]; NSBezierPath *temp_hull = [[NSBezierPath bezierPath] retain]; [temp_hull moveToPoint:back]; [temp_hull lineToPoint:fwd]; [temp_hull stroke]; } -(void)set_origin:(NSPoint) pt { origin = NSMakePoint(pt.x, pt.y); } -(void)set_back:(NSPoint) pt { fwd = NSMakePoint(pt.x, pt.y); } -(void)set_fwd:(NSPoint) pt { back = NSMakePoint(pt.x, pt.y); } -(void)set_symmetric:(NSPoint) pt { // set_symmetric set both back and fwd by mirroring the forward point around the origin [self set_fwd:pt]; NSPoint temp = pt; temp.x = 2*origin.x - temp.x; temp.y = 2*origin.y - temp.y; [self set_back:temp]; } -(void)dump { // dumps self into log window NSLog(@"\n(%f, %f) - (%f, %f) - (%f, %f)", origin.x, origin.y, back.x, back.y, fwd.x, fwd.y); } -(NSPoint)origin { return origin; } -(NSPoint)back { return back; } -(NSPoint)fwd { return fwd; } - (id)copyWithZone:(NSZone *)zone { id newObj = [[[self class] allocWithZone:zone] init]; [newObj set_origin:[self origin]]; [newObj set_back:[self back]]; [newObj set_fwd:[self fwd]]; return newObj; } @end
Header of the NSView child, "CocoaDrawing":
Code:
#import <AppKit/AppKit.h> #import <Anchor.h> NSBezierPath *convex_hull; Anchor *master_anchor; NSMutableArray *path; @interface CocoaDrawing : NSView { } @end
... and its implementation:


Code:
#import "CocoaDrawing.h" @implementation CocoaDrawing - (BOOL)acceptsFirstResponder { return YES; } - (id)initWithFrame:(NSRect)frame { self = [super initWithFrame:frame]; if (self) { // init master_anchor = [[Anchor alloc] init]; convex_hull = [[NSBezierPath bezierPath] retain]; path = [[NSMutableArray alloc] init]; } return self; } - (void)drawRect:(NSRect)rect { // Draw the current anchor object [master_anchor drawRect:rect]; } - (NSPoint)getLocation:(NSEvent *) theEvent { // helper function, returns locationInWindow relative to View coordinates: NSPoint loc = [theEvent locationInWindow]; loc.x -= [self frame].origin.x; loc.y -= [self frame].origin.y; return loc; } - (void)mouseDown:(NSEvent *) theEvent { // mouseDown simply sets origin of anchor NSPoint loc = [self getLocation:theEvent]; [master_anchor set_origin:loc]; } - (void)mouseDragged:(NSEvent *) theEvent { // set the back and fwd ctrl points of the anchor NSPoint loc = [self getLocation:theEvent]; [master_anchor set_symmetric:loc]; [self setNeedsDisplay:YES]; } - (void)mouseUp:(NSEvent *) theEvent { // anchor fully defined, so... Anchor *tempAnchor = [[[Anchor alloc] init] retain]; // ...copy it... tempAnchor = [master_anchor copy]; // ...and stack the copy onto path [path addObject:tempAnchor]; // poor man's debugger: could't find class attribs in Xcode 1.2 debugger, so // after three defined anchors, we dump the anchors in the log window: if ([path count]==3) { [[path objectAtIndex:0] dump]; [[path objectAtIndex:1] dump]; [[path objectAtIndex:2] dump]; } } @end
     
Clinically Insane
Join Date: Oct 2001
Location: San Diego, CA, USA
Status: Offline
Reply With Quote
Feb 7, 2005, 03:18 PM
 
The immediate problem is here:
Code:
#import <AppKit/AppKit.h> #import <Foundation/Foundation.h> NSPoint origin, back, fwd; @interface Anchor : NSObject { }
The variables origin, back and fwd should be instance variables (declared between those two brackets after the class name), but these are just ordinary variables declared in the header. This means every instance is sharing these variables, since that's what the getters and setters are acting upon.

Also, it's not the source of your problem, but you are saying [[[Anchor alloc] init] retain]. You already own any object you create, so you shouldn't retain it. And you should be releasing it when you relinquish control of the object (i.e. at the end of that method). Otherwise (to either of these points) you'll be leaking memory like a sieve.
Chuck
___
"Instead of either 'multi-talented' or 'multitalented' use 'bisexual'."
     
cla  (op)
Mac Enthusiast
Join Date: Mar 2000
Status: Offline
Reply With Quote
Feb 7, 2005, 03:57 PM
 

The immediate problem is here:
Whoa - I'm impressed! I moved the line into the brackets and it works like a charm!
Thanks a bunch ChuckIt!

/.../but you are saying [[[Anchor alloc] init] retain]. You already own any object you create, so you shouldn't retain it.
Aah, I thought I had to [retain] it otherwise the array would point out NIL by the end of the function. It seems addObject sends that [retain] message implicitly for me.
So all I do is skip the retain and call release before exiting the function?


/ sieve
     
Clinically Insane
Join Date: Oct 2001
Location: San Diego, CA, USA
Status: Offline
Reply With Quote
Feb 7, 2005, 04:16 PM
 
Originally posted by cla:
Aah, I thought I had to [retain] it otherwise the array would point out NIL by the end of the function. It seems addObject sends that [retain] message implicitly for me.
So all I do is skip the retain and call release before exiting the function?
Yep. The idea behind Cocoa memory management is that every object is responsible for its own stuff. When you pass an object to one of the Cocoa classes, it will retain the object as long as it needs it and then release the object when it's through, and you should do the same with your instance variables.
Chuck
___
"Instead of either 'multi-talented' or 'multitalented' use 'bisexual'."
     
cla  (op)
Mac Enthusiast
Join Date: Mar 2000
Status: Offline
Reply With Quote
Feb 10, 2005, 04:33 PM
 
As a token of my gratitude for helping me past the problem, I shall introduce you all to the crappiest application ever compiled.

It's the tool cocoon chain designers never would do without: a cocoon builder!!

Unfortunately, I intend to keep this application for myself, as the world is hardly ready for it. Anyway, here's a screen shot (PDF)...
(Last edited by cla; Feb 10, 2005 at 05:52 PM. )
     
Fresh-Faced Recruit
Join Date: Oct 2000
Location: Livermore, CA
Status: Offline
Reply With Quote
Feb 13, 2005, 05:23 PM
 
[QUOTE]Originally posted by cla:
[B]As a token of my gratitude for helping me past the problem, I shall introduce you all to the crappiest application ever compiled.

Funny, it doesn't look like Office 2004!
     
   
Thread Tools
Forum Links
Forum Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On
Top
Privacy Policy
All times are GMT -5. The time now is 09:08 AM.
All contents of these forums © 1995-2011 MacNN. All rights reserved.
Branding + Design: www.gesamtbild.com
vBulletin v.3.8.7 © 2000-2011, Jelsoft Enterprises Ltd., Content Relevant URLs by vBSEO 3.3.2