我有一个带有以下代码的自定义NSCell,用于在单击时显示NSColorPanel:
-(void)setColorFromPanel:(NSColorPanel*)panel{
NSLog(@"COLOR is HERE!");
[self setObjectValue:[panel color]];
}
- (NSUInteger)hitTestForEvent:(NSEvent *)event inRect:(NSRect)cellFrame ofView:(NSView *)controlView{
if(self.isColor){
if([event type]==NSLeftMouseDown){
NSColorPanel *panel=[NSColorPanel sharedColorPanel];
[panel setColor:[self objectValue]];
[panel setShowsAlpha:YES];
[panel setAction:@selector(setColorFromPanel:)];
[panel setTarget:self];
[panel makeKeyAndOrderFront:nil];
}
return NSCellHitContentArea;
}
return NSCellHitNone;
}
此代码显示颜色选择器,但是,当我单击颜色时,它会崩溃。如果删除[panel setTarget:self]行,那么它工作正常,虽然没有效果(因为我没有收到颜色值,因为没有目标)。
这是堆栈跟踪。错误是EXC_BAD_ACCESS。
#0 0x00007fff8667811c in objc_msgSend ()
#1 0x00007fff87081e9a in -[NSApplication sendAction:to:from:] ()
#2 0x00007fff871fa1cd in -[NSColorPanel _forceSendAction:notification:firstResponder:] ()
#3 0x00007fff871fe384 in -[NSColorPanel setColor:] ()
#4 0x00007fff8721d112 in -[NSColorPickerWheel setColor:] ()
#5 0x00007fff8721d5ae in -[NSColorPickerWheel brightnessSlider:] ()
#6 0x00007fff87081e9a in -[NSApplication sendAction:to:from:] ()
#7 0x00007fff87081df9 in -[NSControl sendAction:to:] ()
#8 0x00007fff8710d400 in -[NSCell trackMouse:inRect:ofView:untilMouseUp:] ()
#9 0x00007fff873eaf01 in -[NSSliderCell trackMouse:inRect:ofView:untilMouseUp:] ()
#10 0x00007fff8710c215 in -[NSControl mouseDown:] ()
#11 0x00007fff8702634f in -[NSWindow sendEvent:] ()
#12 0x00007fff86f5ba86 in -[NSApplication sendEvent:] ()
#13 0x00007fff86ef24da in -[NSApplication run] ()
#14 0x00007fff86eeb1a8 in NSApplicationMain ()
#15 0x00000001000029bb in main (argc=1, argv=0x7fff5fbff6a0)
答案 0 :(得分:0)
您需要发布崩溃报告/调试器输出的相关部分;否则,很难猜出到底出了什么问题!你知道,我们不是通灵者。崩溃报告包含有关崩溃原因的重要信息。
也就是说,有一个开源彩色单元格可用here。它仅适用于支持GC的应用程序,但如果该代码的许可证适合您的使用,则应该是一个良好的开端。不要重新发明轮子。
让我补充几句话。 NSCell
中的NSTableView
用作戳记来绘制每一行的条目,通常会被重复使用,而不是每行NSCell
生成。从目前的观点来看,这在系统中具有丰富的内存并没有多大意义,但是15年前NeXTStep最初设计时它才有意义。
无论如何,由于这个原因,单元格将自己设置为另一个对象的目标通常不是一个好主意,因为该单元格往往不会持久存在。我猜这就是导致这次崩溃的原因,即NSTableColumn
已经释放了该单元格,因为它已经完成了使用该特定单元格。将控制器类作为面板的目标而不是单元本身通常更安全。