Is there something wrong with my object?

This is a program that I am writing (I am not against copying someone else and therefore not learning) as part of the ObjectiveC and Cocoa learning curve. I want to draw simple shapes in NSView (limiting it to ovals and rectangles for now). The idea is that I write every NSBezierPath to an NSMutableArray, so I can also investigate / implement save / load, undo / redo. I have a canvas that I can draw on and also 2 buttons that I use to select a tool. To handle the path, I created another object that can contain an NSBezierPath, color values, and a size value for each object drawn. This is what I want to store in the array. I am using mouseDown / Dragged / Up to get the coordinates for the drawing path. However, this is where things get uncomfortable. I can instantiate an object,which should contain the path / color / etc. info, but when I try to change the instance variable, the application crashes without a helpful message in the debugger. I'll try to keep my code snippets short, but tell me if you need to include more. The code has also degenerated a bit from me, trying to do so many things to make it work.

Project: Cocoa document based application
I have the following .m / .h files

  •  
  • MyDocument:NSDocument

    - generated by Xcode 
  • DrawnObject:NSObject

    - handles the drawn object, i.e. path, color, type (oval / straight) and size 
  • Canvas:NSView

    - well, shows a picture, deals with mouse and buttons

Canvas is also responsible for persisting NSMutableArray

objects DrawnObject

.

DrawnObject.h

as follows:

#import <Foundation / Foundation.h>
// The drawn object must know what tool it was created with etc as this needs to be used for generating the drawing

@interface DrawnObject: NSObject {
    NSBezierPath * aPath;
    NSNumber * toolType; // 0 for oval, 1 for rectangular etc ....
    float toolSize;
    struct myCol {
        float rd;
        float grn;
        float blu;
        float alp;
    } toolColor;
}

- (void) setAPath: (NSBezierPath *) path;
- (NSBezierPath *) aPath;
@property (readwrite, assign) NSNumber * toolType;
- (float) toolSize;
- (void) setToolSize: (float) size;
- (struct myCol *) toolColor;
- (void) setCurrentColor: (float) ref: (float) green: (float) blue: (float) alpha;

@end

Canvas.h

as follows

#import 
#import "drawnObject.h"

@interface Canvas: NSView {
    NSMutableArray * myDrawing;
    NSPoint downPoint;
    NSPoint currentPoint;
    NSBezierPath * viewPath; // to show the path as the user drags the mouse
    NSNumber * currentToolType;
    BOOL mouseUpFlag; // trying a diff way to make it work
    BOOL mouseDrag;
}

- (IBAction) useOval: (id) sender;
- (IBAction) useRect: (id) sender;
- (IBAction) showTool: (id) sender;
- (NSRect) currentRect;
- (NSBezierPath *) createPath: (NSRect) aRect;
- (void) setCurrentToolType: (NSNumber *) t;
- (NSNumber *) currentToolType;
@end

There Canvas.m

are several functions in the file for working with the mouse, and NSView / XCode also crashed in
-(id)initWithFrame:(NSRect)frame


and -(void)drawRect:(NSRect)rect

I originally use mouseUp

to try to insert a new one DrawnObject

into the array but this crashed. So now I'm using two flags BOOL

to see when the mouse was released (clumsy, but I'm trying ...) in drawRect

order to insert into the array. I've included the method below and pointed out where it is causing the application to crash:

- (void) drawRect: (NSRect) rect {// This is called automatically
    // Drawing code here.
    // NSLog (@ "Within drawRect tool type is% d", [self currentTool]);
    NSRect bounds = [self bounds];
    NSRect aRect = [self currentRect];
    viewPath = [self createPath: aRect];
// the createPath method uses the tool type to switch between oval and rect bezier curves

    if (mouseUpFlag == YES && mouseDrag == YES) {
        mouseDrag = NO;
        // Create a new drawnObject here 
        DrawnObject * anObject = [[DrawnObject alloc] init]; // - WORKS FINE UP TO HERE
        NSLog (@ "CREATED NEW drawnObject");
        [anObject setAPath: viewPath]; // - INSTANT APP DEATH !!!!
        NSLog (@ "Set a path in drawnObject");
        [anObject setToolType: [[NSNumber alloc] initWithInt: 5]];
        NSLog (@ "Set toolType in DrawnObject");
        [anObject setToolType: currentToolType];

        [myDrawing addObject: anObject];
        NSLog (@ "Added Object");
    }   

    [[NSColor colorWithCalibratedRed: 0.0 green: 0.9 blue: 0.0 alpha: 0.5] set];
    [NSBezierPath fillRect: bounds];


    [[NSColor lightGrayColor] set];
    [viewPath stroke]; // This is so the user can see where the drawing is being done

    // Now, draw the paths in the array
    [[NSColor blueColor] set];
    for (DrawnObject * indexedObject in myDrawing) {
        [[indexedObject aPath] stroke]; // This will do the actual drawing of ALL objects

    }


}

I'm guessing it has something to do with the object realm or something, but I just can't figure it out. As I said, since I've tried things, the code seems to have undergone a metamorphosis, unfortunately not for the best. Like those BOOLS etc.

HELP! Any smart people out there, point me in the right direction please!

ADD THIS ON:


-(NSBezierPath *)createPath:(NSRect) aRect
{

    NSBezierPath * tempPath;
    //I need to know what tool

    switch(0){  //temporary - this would use the toolType as a selector
        case 0:
            tempPath = [NSBezierPath bezierPathWithOvalInRect:aRect];
            break;
        case 1:
            tempPath = [NSBezierPath bezierPathWithRect:aRect];
            break;
        default:
            tempPath = [NSBezierPath bezierPathWithOvalInRect:aRect];
            break;
    }
    return tempPath;
}

      

0


source to share


6 answers


You said your init method is:

-(void)init {
[super init];
//set default color = black
toolColor.rd=1.0;
toolColor.grn=1.0;
toolColor.blu=1.0;
toolColor.alp=1.0;
//set default size
toolSize=0.8;
//set default toolType
toolType=0;
//oval
NSLog(@"Init %@",self);
}

      

This is definitely wrong; read how to create an init method in the Obj-C manual or by reading the example code. This is how it should look:



-(id)init {
if (self = [super init]) {
    //set default color = black
    toolColor.rd=1.0;
    toolColor.grn=1.0;
    toolColor.blu=1.0;
    toolColor.alp=1.0;
    //set default size
    toolSize=0.8;
    //set default toolType
    toolType=0;
    //oval
    NSLog(@"Init %@",self);
}
return self;
}

      

By not returning anything from -init, you prevented the object from being created. Good luck! :-)

Edit: Ashley beat me ...

+2


source


What do you mean by "crash"?

Does anything appear in the debugger console (โ‡งโŒ˜R)?



Does the stack trace appear in the debugger window?

If there is a stack trace where in your code does the crash occur?

0


source


It just hangs. In the debugger, I see:

  [Session started at 2008-11-28 14:40:34 +1000.]
2008-11-28 14: 40: 36.157 CH18Challenge_try2 [1893: 10b] Mouse Down at (80.000000,285.000000)
2008-11-28 14: 40: 36.333 CH18Challenge_try2 [1893: 10b] Mouse Up at (166.000000,217.000000)
2008-11-28 14: 40: 36.348 CH18Challenge_try2 [1893: 10b] Init 
2008-11-28 14: 40: 36.349 CH18Challenge_try2 [1893: 10b] CREATED NEW drawnObject

[Session started at 2008-11-28 14:40:36 +1000.]
Loading program into debugger ...
GNU gdb 6.3.50-20050815 (Apple version gdb-962) (Sat Jul 26 08:14:40 UTC 2008)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software covered by the GNU General Public License, and you are
welcome to change it and / or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-apple-darwin". Program loaded.
sharedlibrary apply-load-rules all
Attaching to program: `/Users/johan_kritzinger/Documents/Cocoa/CH18Challenge_try2/build/Debug/CH18Challenge_try2.app/Contents/MacOS/CH18Challenge_try2 ', process 1893.
(gdb) 

Then I need to force quit to stop it.

0


source


We need to see the implementation of setAPath from DrawnObject.m. Also, for a "stack trace" look in the upper left corner of the debugger - it should display a stack of functions showing where in your code the failure occurred. Make sure you are running in Debug mode and not Release mode.

0


source


On the command line, you can type print-object and you can set a breakpoint at that line and walk through it from there. It seems setAPath is broken somehow.

Friedrich relationship

0


source


What you have is not a wreck. The crash occurs when a signal is raised (for example EXC_BAD_ACCESS) or an uncaught exception.

What appears to you as an endless loop.

You need to use the pause button in the debugger and see exactly where. I would suggest that you have an infinite loop in your setAPath: method. You need to decide why this function is looping.

0


source







All Articles