0

这是我正在编写的程序(我自己而不是复制别人的,因此不学习)作为 ObjectiveC 和 Cocoa 学习曲线的一部分。我想在 NSView 上绘制简单的形状(现在限制为椭圆和矩形)。这个想法是我将每个 NSBezierPath 记录到一个 NSMutableArray 中,这样我还可以调查/实现保存/加载、撤消/重做。我有一个画布,可以在上面画画,还有 2 个用于选择工具的按钮。为了处理路径,我创建了另一个对象,该对象可以保存每个绘制对象的 NSBezierPath、颜色值和大小值。这就是我要存储在数组中的内容。我使用 mouseDown/Dragged/Up 来获取绘图路径的坐标。然而,这就是事情变得不稳定的地方。我可以实例化应该保存路径/颜色/等的对象。info 但是,当我尝试更改实例变量时,应用程序崩溃,调试器中没有有用的消息。我会尽量缩短我的代码片段,但如果我需要包含更多,请告诉我。代码也因为我尝试了很多事情来使它工作而退化了一点。

项目:基于 Cocoa 文档的应用程序
我有以下 .m/.h 文件

  • MyDocument:NSDocument- 由 XCode 生成
  • DrawnObject:NSObject- 处理绘制的对象,即路径、颜色、类型(椭圆/矩形)和大小
  • Canvas:NSView- 好吧,显示绘图,处理鼠标和按钮

Canvas 还负责维护NSMutableArray对象DrawnObject

DrawnObject.h看起来像这样:

#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看起来像这样

#进口
#import "drawnObject.h"

@界面画布:NSView {
    NSMutableArray * myDrawing;
    NSPoint 下点;
    NSPoint 当前点;
    NSBezierPath * viewPath;//显示用户拖动鼠标时的路径
    NSNumber * 当前工具类型;
    BOOL mouseUpFlag;//尝试不同的方式使其工作
    布尔鼠标拖动;
}

-(IBAction)useOval:(id)发件人;
-(IBAction)useRect:(id)sender;
-(IBAction)showTool:(id)sender;
-(NSRect)当前矩形;
-(NSBezierPath *)createPath:(NSRect) aRect;
-(void)setCurrentToolType:(NSNumber *) t;
-(NSNumber *)currentToolType;
@结尾

Canvas.m文件中有几个函数来处理鼠标和 NSView/XCode 也放入了
-(id)initWithFrame:(NSRect)frame
-(void)drawRect:(NSRect)rect最初我mouseUp用来尝试将新DrawnObject的插入到数组中,但这导致了崩溃。所以,现在我使用两个BOOL标志来查看鼠标何时被释放(笨拙但我正在尝试......)drawRect插入到数组中。我已经包含了下面的方法,并指出了它导致应用程序失败的位置:

- (void)drawRect:(NSRect)rect { //这是自动调用的
    // 这里绘制代码。
    //NSLog(@"drawRect内工具类型为%d", [self currentTool]);
    NSRect 边界 = [自我边界];
    NSRect aRect = [self currentRect];
    viewPath = [self createPath:aRect];
//createPath 方法使用工具类型在椭圆和矩形贝塞尔曲线之间切换

    if(mouseUpFlag==YES && mouseDrag==YES){
        鼠标拖动=否;
        //在这里新建一个drawedObject
        DrawnObject * anObject = [[DrawnObject alloc]init];//- 工作正常到这里
        NSLog(@"创建新的 drawObject");
        [anObject setAPath:viewPath]; //- 应用程序立即死亡!!!!
        NSLog(@"在drawedObject中设置路径");
        [anObject setToolType:[[NSNumber alloc]initWithInt:5]];
        NSLog(@"在 DrawnObject 中设置 toolType");
        [anObject setToolType:currentToolType];

        [myDrawing addObject:anObject];
        NSLog(@"添加的对象");
    }   

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


    [[NSColor lightGrayColor]set];
    [视图路径描边];//这是为了让用户可以看到正在绘制的位置

    //现在,在数组中绘制路径
    [[NSColor blueColor]set];
    for(DrawnObject * indexedObject in myDrawing){
        [[indexedObject aPath] stroke];//这将做所有对象的实际绘制

    }


}

我想这与对象范围或其他东西有关,但我就是想不通。正如我所说,当我尝试过一些事情时,代码已经发生了某种变化,遗憾的是不是更好。像那些 BOOLS 等。

帮助!任何聪明的人,请指出我正确的方向!

添加这个:


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

6 回答 6

2

你说你的 init 方法是:

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

绝对是错误的;阅读 Obj-C 指南中的如何创建 init 方法或阅读示例代码。它应该是这样的:

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

通过不从 -init 返回任何内容,您正在阻止对象的创建。祝你好运!:-)

编辑:阿什利打败了我......

于 2008-11-28T07:34:50.163 回答
0

它只是挂起。在调试器中,我看到:

  [会议开始于 2008-11-28 14:40:34 +1000。]
2008-11-28 14:40:36.157 CH18Challenge_try2[1893:10b] 鼠标按下 (80.000000,285.000000)
2008-11-28 14:40:36.333 CH18Challenge_try2[1893:10b] 鼠标在 (166.000000,217.000000)
2008-11-28 14:40:36.348 CH18Challenge_try2[1893:10b] 初始化
2008-11-28 14:40:36.349 CH18Challenge_try2[1893:10b] 创建了新的drawedObject

[会议开始于 2008-11-28 14:40:36 +1000。]
正在将程序加载到调试器中……
GNU gdb 6.3.50-20050815(Apple 版本 gdb-962)(2008 年 7 月 26 日星期六 08:14:40 UTC)
版权所有 2004 Free Software Foundation, Inc.
GDB 是自由软件,受 GNU 通用公共许可证保护,您是
欢迎在某些条件下更改和/或分发它的副本。
键入“显示复制”以查看条件。
GDB 绝对没有任何保证。键入“显示保修”以获取详细信息。
此 GDB 配置为“i386-apple-darwin”。程序已加载。
共享库应用加载规则全部
附加到程序:`/Users/johan_kritzinger/Documents/Cocoa/CH18Challenge_try2/build/Debug/CH18Challenge_try2.app/Contents/MacOS/CH18Challenge_try2',进程 1893。
(gdb)

然后我必须强制退出来阻止它。

于 2008-11-28T04:41:30.263 回答
0

我们需要从 DrawnObject.m 中查看 setAPath 的实现。此外,对于调试器左上角的“堆栈跟踪”,它应该列出一堆函数,显示代码中崩溃的位置。确保您在调试模式下运行,而不是发布。

于 2008-11-28T04:54:23.843 回答
0

在命令行上,您可以键入 print-object,然后可以在该行中设置断点并从那里逐步执行。似乎 setAPath 不知何故坏了

问候弗里德里希

于 2008-11-28T06:05:10.720 回答
0

“崩溃”是什么意思?

调试器控制台 (⇧⌘R) 中是否出现任何内容?

调试器窗口中是否出现堆栈跟踪?

如果有堆栈跟踪,它在您的代码中的哪个位置崩溃?

于 2008-11-28T04:26:47.690 回答
0

你所拥有的不是崩溃。崩溃是指发出信号(如 EXC_BAD_ACCESS)或未捕获的异常。

你所拥有的似乎是一个无限循环。

您需要使用调试器中的暂停按钮并查看确切的位置。我猜你的 setAPath: 方法中有一个无限循环。你需要弄清楚为什么这个函数会无限循环。

于 2008-11-29T07:31:33.637 回答