在我的应用程序中有一个NSWindowController
的子类。在- (void)awakeFromNib
中,我创建了一个NSView
子类的实例来创建一个放置在底部的按钮栏:
self.buttonBar = [[CNButtonBar alloc] initWithSize:NSMakeSize(tableViewRect.size.width-1, 25)];
这个CNButtonBar
东西有一个向自己添加按钮的方法。我创建了两个:
[buttonBar addButtonWithTitle:nil
image:[NSImage imageNamed:NSImageNameAddTemplate]
target:self
action:@selector(btnAccountAddAction:)
alignment:CNBarButtonAlignLeft];
[buttonBar addButtonWithTitle:nil
image:[NSImage imageNamed:NSImageNameRemoveTemplate]
target:self
action:@selector(btnAccountRemoveAction:)
alignment:CNBarButtonAlignLeft];
这两个操作方法是在NSViewController
的同一个实例中定义的,我发送了两条addButtonWithTitle:...
消息。
用于设置操作的方法定义如下:
- (void)btnAccountAddAction:(id)sender
{
....
}
- (void)btnAccountRemoveAction:(id)sender
{
....
}
但是,它不起作用。每次如果我点击这两个按钮中的一个按钮,我的应用程序就会抛出像这样的异常:
-[__NSArrayM btnAccountAddAction:]: unrecognized selector sent to instance 0x1001454e0
检查此异常是绝对正确的。 NSArray
没有我想要调用的方法。但是,抛出此异常的对象有时会发生变化。有时会有__NSData
个对象,有时会有__NSDictionary
等等。似乎接收器不是我的NSWindowController
子类。但是,给定的实例ID 0x1001454e0
与我的NSWindowController
相同。
这让我想把头发撕掉!这里出了什么问题......? 感谢。
<小时/> 的更新
我必须说,CNButtonBar
和CNButtonBarButton
都完全由代码绘制。 addButtonWithTitle:image:target:action:alignment:
的完整方法就在这里(请记住,这发生在CNButtonBar
,NSView
的子类(我应该使用NSViewController
而不是它吗?),{{1} }是CNButtonBarButton
)的子类:
NSButton
更新2
问题解决了。经过一些调试后,我发现它一定是ARCs自动保留/释放内容的问题。而且我是对的。但问题是我的- (void)addButtonWithTitle:(NSString*)title image:(NSImage*)image target:(id)target action:(SEL)action alignment:(CNBarButtonAlign)align
{
if (self.buttons == nil)
self.buttons = [[NSMutableArray alloc] init];
CNButtonBarButton *button = [[CNButtonBarButton alloc] init];
[self.buttons addObject:button];
button.title = title;
button.image = image;
button.target = target;
button.action = action;
button.align = align;
NSRect buttonRect;
NSSize titleSize = NSMakeSize(0, 0);
if (button.title.length > 0) {
NSMutableParagraphStyle* textStyle = [[NSMutableParagraphStyle defaultParagraphStyle] mutableCopy];
[textStyle setAlignment: NSCenterTextAlignment];
NSColor *textColor = [[NSColor blackColor] colorWithAlphaComponent:0.9];
NSShadow* textShadow = [[NSShadow alloc] init];
[textShadow setShadowColor: [NSColor whiteColor]];
[textShadow setShadowOffset: NSMakeSize(0, -1)];
[textShadow setShadowBlurRadius: 0];
button.titleTextAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
[NSFont fontWithName:@"Helvetica Neue" size:11.0], NSFontAttributeName,
textShadow, NSShadowAttributeName,
textColor, NSForegroundColorAttributeName,
textStyle, NSParagraphStyleAttributeName,
nil];
titleSize = [title sizeWithAttributes:button.titleTextAttributes];
buttonRect = NSMakeRect(0, 0, roundf(titleSize.width) + kTextInset * 2, NSHeight(self.frame) - 1);
}
if (button.image != nil) {
NSSize imageSize = [image size];
if (button.title.length == 0) {
buttonRect = NSMakeRect(0, 0, imageSize.width + kImageInset * 2, NSHeight(self.frame) - 1);
} else {
buttonRect = NSMakeRect(0, 0,
(imageSize.width + kImageInset * 2) + (roundf(titleSize.width) + kTextInset),
NSHeight(self.frame) - 1);
}
}
switch (self.align) {
case CNButtonBarAlignNormal: {
switch (button.align) {
case CNButtonBarButtonAlignLeft: {
button.frame = NSMakeRect(offsetLeft, 0, NSWidth(buttonRect), NSHeight(buttonRect));
offsetLeft += 1 * [self.buttons indexOfObject:button] + NSWidth(button.frame);
break;
}
case CNButtonBarButtonAlignRight: {
button.frame = NSMakeRect(offsetRight - NSWidth(buttonRect), 0, NSWidth(buttonRect), NSHeight(buttonRect));
offsetRight -= 1 * [self.buttons indexOfObject:button] + NSWidth(button.frame);
break;
}
}
break;
}
case CNButtonBarAlignCentered: {
break;
}
}
[self addSubview:button];
}
子类。由于将实例作为局部变量(没有强指针)而泄漏。感谢Sean D.,这指出了正确的方法。 ( - ;
答案 0 :(得分:2)
看起来发生了两件事之一。第一种可能是你的CNButtonBar对象在按钮仍然存在时被释放。如果按钮仍然存在,他们会尝试将那些选择器发送到CNButtonBar曾经占用的内存中。我会说确保它不会在任何地方自动释放,并且你不会意外在窗口控制器的-awakeFromNib
方法中自动释放它。 (如果你和我一样,那就是最有可能的罪魁祸首。)
第二种可能性是您的-addButtonWithTitle:image:target:action:alignment:
方法设置了按钮的操作,但没有设置其目标。确保该方法的实现在按钮上调用-setTarget:
和-setAction:
。