2008-11-28 13 views
0

C'est un programme que j'écris (moi-même, par opposition à copier quelqu'un d'autre et donc pas d'apprentissage) dans le cadre de la courbe d'apprentissage ObjectiveC et Cocoa. Je veux dessiner des formes simples sur un NSView (en le limitant aux ovales et aux rectangles pour l'instant). L'idée est que j'enregistre chaque NSBezierPath sur un NSMutableArray afin que je puisse aussi étudier/implémenter save/loading, undo/redo. J'ai une toile, peut dessiner dessus ainsi que 2 boutons que j'utilise pour sélectionner l'outil. Pour gérer le chemin j'ai créé un autre objet qui peut contenir un NSBezierPath, des valeurs de couleur et une valeur de taille pour chaque objet dessiné. C'est ce que je veux stocker dans le tableau. J'utilise mouseDown/Dragged/Up pour obtenir les coordonnées du tracé. Cependant, c'est là que les choses vont de travers. Je peux instancier l'objet supposé contenir le chemin/couleur/etc. info, mais lorsque j'essaie de changer une variable d'instance, l'application se bloque sans message utile dans le débogueur. Je vais essayer de garder mes extraits de code courts mais dites-moi si j'ai besoin d'en inclure d'autres. Le code a aussi dégénéré un peu de moi en essayant tant de choses pour le faire fonctionner.Y a-t-il quelque chose qui ne va pas avec mon Object Scope?

projet: Document de cacao application basée
Je les fichiers .m/.h suivants

  • MyDocument:NSDocument - générée par XCode
  • DrawnObject:NSObject - traite le chemin objet dessiné à-dire, la couleur, le type (ovale/rect) et la taille
  • Canvas:NSView - bien, montre le dessin, traite avec la souris et boutons

Canvas est également responsable du maintien d'objets NSMutableArray de DrawnObject.

DrawnObject.h ressemble à ceci:

 
#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 ressemble à ceci

 
#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 

Dans le fichier Canvas.m il y a plusieurs fonctions pour faire face à la souris et NSView/XCode également abandonné dans
-(id)initWithFrame:(NSRect)frame
et -(void)drawRect:(NSRect)rect Au départ, j'utiliser mouseUp pour essayer d'insérer le nouveau DrawnObject dans le tableau, mais cela a causé un plantage. Donc, maintenant j'utilise deux drapeaux BOOL pour voir quand la souris a été libérée (maladroit mais j'essaye ....) dans drawRect pour insérer dans le tableau. J'ai inclus la méthode ci-dessous et indiqué où elle provoque l'échec de l'application:

 
- (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 

    } 


} 

Je suppose que cela a quelque chose à voir avec la portée de l'objet ou quelque chose, mais je ne peux pas le comprendre. Comme je l'ai dit, comme j'ai essayé des choses le code a subi une sorte de métamorphose, malheureusement pas pour le mieux. Comme ces BOOLS etc.

AIDE! Toute personne intelligente là-bas, dirigez-moi dans la bonne direction s'il vous plaît!

AJOUTE LA 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

Nous devons voir l'implémentation de setAPath à partir de DrawnObject.m. –

+0

- (void) setAPath: chemin (NSBezierPath *) { \t NSLog (@ "Chemin d'accès enregistré"); \t aPath = chemin; } –

+0

Je suppose que je devrais faire le bit release/retain mais le fait est qu'il ne parvient jamais au NSLog dans la méthode. –

Répondre

0

Que voulez-vous dire par « accident »?

Est-ce que quelque chose apparaît dans la console de débogage (⇧⌘R)?

Une trace de pile apparaît-elle dans la fenêtre du débogueur?

S'il y a une trace de pile, où se bloque-t-elle dans votre code?

0

Il se bloque simplement. Dans le débogueur, je vois:

 
    [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) 

Ensuite, je dois forcer quitter pour l'arrêter.

+0

Désolé, c'était la console de débogage. Dans le débogueur, je vois qu'il indique que indexedObject est hors de la portée. Et c'est ce que je ne comprends pas. Je suis probablement juste lent sur l'adoption .. Comme je l'ai mentionné, je suis un noob - où pourrais-je chercher une trace de pile? –

+0

S'il s'est écrasé avant d'avoir atteint la boucle for, la variable indexedObject n'existe pas encore. À quoi ressemble l'implémentation de createPath? –

+0

cas 0: tempPath = [NSBezierPath bezierPathWithOval: aRect]; pause; // autres cas, p.ex. pour rectangle } // fermeture du commutateur retuen tempPath; } –

0

Nous devons voir l'implémentation de setAPath à partir de DrawnObject.m. En outre, pour le "pile trace" look en haut à gauche du débogueur - il devrait énumérer une pile de fonctions montrant où se trouve dans votre code l'accident. Assurez-vous que vous exécutez en mode débogage, pas Release.

+0

Si je comprends bien, c'est ce que dit la trace de la pile (il y a 22 items mais un seul est noir): - [Canvas drawRect:] et si je clique dessus le volet droit des débogueurs dit indexedObject hors de portée . Se pourrait-il que ma mise en œuvre de la boucle for soit incorrecte dans drawRect? –

+0

Non, le crash n'a rien à voir avec indexedObject ou la boucle. "hors de portée" signifie simplement que vous n'avez pas encore atteint la boucle for, donc l'objet est "hors de portée". –

0

Sur la ligne de commande, vous pouvez taper print-object et vous pouvez définir un point d'arrêt dans cette ligne et le parcourir à partir de là. Il semble setAPath est en quelque sorte brisé

Cordialement Friedrich

2

Vous avez dit que votre méthode init était:

-(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); 
} 

C'est certainement mal; lire sur la façon de créer une méthode init dans le guide Obj-C ou en lisant un exemple de code. Voici à quoi cela devrait ressembler:

-(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; 
} 

En ne retournant rien de -init, vous empêchiez la création de l'objet. Bonne chance! :-)

Edit: Ashley m'a devancé ...

0

Qu'est-ce que vous avez est pas un accident. Un plantage survient lorsqu'un signal est déclenché (comme EXC_BAD_ACCESS) ou une exception non interceptée.

Ce que vous avez semble être une boucle infinie.

Vous devez utiliser le bouton de pause dans le débogueur et voir exactement où. Je suppose que vous avez une boucle infinie dans votre méthode setAPath: Vous devez déterminer pourquoi cette fonction est en boucle indéfiniment.