NSButton的子类:动作调用方法崩溃

时间:2012-07-28 23:33:42

标签: objective-c action target nsbutton nswindowcontroller

在我的应用程序中有一个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相同。

这让我想把头发撕掉!这里出了什么问题......? 感谢。

<小时/> 的更新

我必须说,CNButtonBarCNButtonBarButton都完全由代码绘制。 addButtonWithTitle:image:target:action:alignment:的完整方法就在这里(请记住,这发生在CNButtonBarNSView的子类(我应该使用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.,这指出了正确的方法。 ( - ;

1 个答案:

答案 0 :(得分:2)

看起来发生了两件事之一。第一种可能是你的CNButtonBar对象在按钮仍然存在时被释放。如果按钮仍然存在,他们会尝试将那些选择器发送到CNButtonBar曾经占用的内存中。我会说确保它不会在任何地方自动释放,并且你不会意外在窗口控制器的-awakeFromNib方法中自动释放它。 (如果你和我一样,那就是最有可能的罪魁祸首。)

第二种可能性是您的-addButtonWithTitle:image:target:action:alignment:方法设置了按钮的操作,但没有设置其目标。确保该方法的实现在按钮上调用-setTarget:-setAction: